所有这些属性字典都有一个通用的设计模式:它们的键是字符串常量(具有该名称的变量),而不是字符串,并且 Objective C 运行时通过地址而不是值来匹配它们。
例如,在您的情况下,NSImageCompressionFactor
声明为
NSString *NSImageCompressionFactor;
在Objective C中,它被初始化为一些常量字符串(理论上可以是任何东西),它基本上是一个指向一些不透明值的指针。
在Objective C 中填充属性字典时,您使用变量的名称(即您只需编写NSImageCompressionFactor
)而不是创建一个新的字符串实例(@"NSImageCompressionFactor"
)。
在 MonoMac 中,我们为这些字典键创建字符串属性,例如参见MonoMac.Foundation.NSUrl.ContentAccessDateKey。
但是,它们在一些地方丢失了(您的位图图像属性就是其中之一,我只是将它们添加到NSBitmapImageRep
monomac commit 115f1eb 中)。如果将来有人发现更多缺失的属性,请简单地在 中提交错误报告bugzilla.xamarin.com
。
如果您使用的是旧版本的 MonoMac,还有一种解决方法。在生成器输入文件(monomac/src/appkit.cs)中,这些声明如下:
[Field ("NSImageCompressionMethod")]
NSString CompressionMethod { get; }
[Field ("NSImageCompressionFactor")]
NSString CompressionFactor { get; }
然后生成器发出:
[CompilerGenerated]
static readonly IntPtr AppKit_libraryHandle = Dlfcn.dlopen (Constants.AppKitLibrary, 0);
[CompilerGenerated]
static NSString _CompressionMethod;
public static NSString CompressionMethod {
get {
if (_CompressionMethod == null)
_CompressionMethod = Dlfcn.GetStringConstant (AppKit_libraryHandle, "NSImageCompressionMethod");
return _CompressionMethod;
}
}
[CompilerGenerated]
static NSString _CompressionFactor;
public static NSString CompressionFactor {
get {
if (_CompressionFactor == null)
_CompressionFactor = Dlfcn.GetStringConstant (AppKit_libraryHandle, "NSImageCompressionFactor");
return _CompressionFactor;
}
}
你可以简单地在你的应用程序的某个地方做同样的事情。
更新
让我们首先从 Objective C 中的一个示例开始(此处为完整示例,图片来自Wikipedia):
- (NSData *)saveImage:(NSImage *)image location:(NSString *)location quality:(float)quality {
NSBitmapImageRep *imageRep = [[image representations] objectAtIndex:0];
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat:quality], NSImageCompressionFactor, nil];
NSData *data = [imageRep representationUsingType:NSJPEGFileType properties:dict];
printf("DATA: %ld\n", [data length]);
return data;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *resDir = [[path stringByAppendingPathComponent:@"Contents"] stringByAppendingPathComponent:@"Resources"];
NSString *filePath = [resDir stringByAppendingPathComponent:@"Neptune.jpg"];
NSImage *image = [[NSImage alloc] initWithContentsOfFile:filePath];
[self saveImage:image location:@"output.jpg" quality:0.0];
[self saveImage:image location:@"output.jpg" quality:0.25];
[self saveImage:image location:@"output.jpg" quality:0.5];
[self saveImage:image location:@"output.jpg" quality:1.0];
}
现在让我们把它变成一个 MonoMac 应用程序(完整示例在这里):
public override void FinishedLaunching (NSObject notification)
{
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
var path = Path.Combine (NSBundle.MainBundle.BundlePath, "Contents", "Resources");
var filePath = Path.Combine (path, "Neptune.jpg");
var image = new NSImage (filePath);
Console.WriteLine (image);
SaveImage (image, "output.jpg", 0.0f);
SaveImage (image, "output.jpg", 0.25f);
SaveImage (image, "output.jpg", 0.5f);
SaveImage (image, "output.jpg", 1.0f);
}
public void SaveImage (NSImage image, string location, float quality)
{
var brep = (NSBitmapImageRep)image.Representations ()[0];
var dict = NSDictionary.FromObjectAndKey (NSNumber.FromFloat (quality), NSBitmapImageRep.CompressionFactor);
var data = brep.RepresentationUsingTypeProperties (NSBitmapImageFileType.Jpeg, dict);
Console.WriteLine (data.Length);
}
这将打印与 Objective C 示例相同的大小,因此这确实有效。