这是我使用压缩保存JPG的MonoMac代码。这很简单,只需设置NSImageCompressionFactor
即可。羞耻它不起作用。
public void SaveImage(NSImage MyNSImage,string Location, float Quality)
{
NSBitmapImageRep BRep=(NSBitmapImageRep)MyNSImage.Representations()[0];
NSDictionary Dic= NSDictionary.FromObjectAndKey(new NSNumber(Quality),new NSString("NSImageCompressionFactor"));
NSData D=BRep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Jpeg,Dic);
System.IO.Stream S=D.AsStream();
SaveStream(Location,S);
S.Dispose();
D.Dispose();
}
//This save function works fine so ignore it.
void SaveStream(string FileName, Stream Source)
{
FileStream FS=File.OpenWrite(FileName);
int Read=0;
byte[] Buffer=new byte[1024];
Source.Seek(0, SeekOrigin.Begin);
do{
Read = Source.Read(Buffer, 0, 1024);
FS.Write(Buffer, 0, Read);
}while(Read>0);
FS.Close();
}
它总是保存为100%,但我做错了什么?希望有些聪明的人知道答案。
答案 0 :(得分:0)
有一个包含所有这些属性字典的通用设计模式:它们的键是字符串常量(具有该名称的变量),而不是字符串,而Objective C运行时按地址匹配它们,而不是按值匹配。< / p>
例如,在您的情况下,NSImageCompressionFactor
被声明为
NSString *NSImageCompressionFactor;
在Objective C中它被初始化为一些常量字符串(理论上可能是任何东西),它基本上是指向某个不透明值的指针。
在Objective C中填充属性字典时,您使用变量的名称(即您只需编写NSImageCompressionFactor
)而不是创建新的字符串实例(@"NSImageCompressionFactor"
)。
在MonoMac中,我们为这些字典键创建字符串属性,例如参见MonoMac.Foundation.NSUrl.ContentAccessDateKey。
但是,它们在一些地方丢失了(您的位图图像属性就是其中之一,我只是将它们添加到monomac commit 115f1eb中的NSBitmapImageRep
)。如果以后有人发现更多丢失的属性,请只需在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中的示例(完整示例here,图片来自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应用程序(完整样本here):
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样本相同的大小,因此这实际上有效。
答案 1 :(得分:0)
好的,我越来越接近,但它仍然保存在100%,还有更多的建议吗?:
public void SaveImage(NSImage MyNSImage,string Location, float Quality)
{
NSBitmapImageRep BRep=(NSBitmapImageRep)MyNSImage.Representations()[0];
NSDictionary Dic= NSDictionary.FromObjectAndKey(new NSNumber(Quality),NSImageCompressionFactor);
NSData D=BRep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Jpeg,Dic);
System.IO.Stream S=D.AsStream();
SaveStream(Location,S);
S.Dispose();
D.Dispose();
}
static readonly IntPtr AppKit_libraryHandle = MonoMac.ObjCRuntime.Dlfcn.dlopen (MonoMac.Constants.AppKitLibrary, 0);
static NSString _NSImageCompressionFactor;
public static NSString NSImageCompressionFactor {
get {
if (_NSImageCompressionFactor == null) {
_NSImageCompressionFactor= MonoMac.ObjCRuntime.Dlfcn.GetStringConstant (AppKit_libraryHandle, "NSImageCompressionFactor");
}
return _NSImageCompressionFactor;
}
}
答案 2 :(得分:0)
我最终放弃了尝试让它按上述方式工作。
我找到了这个C#jpeg编码器。
http://www.codeproject.com/Articles/83225/A-Simple-JPEG-Encoder-in-C
您需要更正评论中指定的一行。