如何用Cocoa压缩jpeg图像?
我有一个 jpeg 图像,我希望能够使用 Cocoa/Core Image/Core Graphics 增量压缩它。例如,我有A.jpg(3MB),我压缩A并得到B.jpg(1MB),压缩B并得到C.jpg(400KB),依此类推,直到图像无法再压缩。
我尝试使用 NSBitmapImageReprepresentationUsingType:properties 但没有取得太大成功。我使用从压缩图像数据创建的图像代表来尝试进一步压缩,但如果我使用与创建初始压缩数据相同的压缩因子,则效果不佳。
这是我一直在争论的代码
NSString * fileName = @"largeImage.jpg"; NSLog(@"== Initializing ==\n"); NSData * imageData = [NSData dataWithContentsOfFile:fileName]; NSLog(@"imageData length: %d\n", [imageData length]); NSImage * image = [[NSImage alloc] initWithData:imageData]; NSBitmapImageRep * bitmapRep = [[image representations] objectAtIndex:0]; NSData * data = [bitmapRep representationUsingType:NSJPEGFileType properties:nil]; NSLog(@"data length: %d\n", [data length]); NSDictionary * dict = [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat:0.5] forKey:NSImageCompressionFactor]; NSData * data5 = [bitmapRep representationUsingType:NSJPEGFileType properties:dict]; NSLog(@"data5 length: %d\n", [data5 length]); NSLog(@"== End ==\n\n"); NSLog(@"== Image from Data5 ==\n"); NSImage * imageFromData5 = [[NSImage alloc] initWithData:data5]; NSBitmapImageRep * bitmapRepFromData5 = [[imageFromData5 representations] objectAtIndex:0]; NSData * dataFromImageFromData5 = [bitmapRepFromData5 representationUsingType:NSJPEGFileType properties:nil]; NSLog(@"dataFromImageFromData5 length: %d\n", [dataFromImageFromData5 length]); dict = [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat:0.5] forKey:NSImageCompressionFactor]; NSData * dataFiveFromImageWithData5 = [bitmapRepFromData5 representationUsingType:NSJPEGFileType properties:dict]; NSLog(@"dataFiveFromImageWithData5 length: %d\n", [dataFiveFromImageWithData5 length]); NSLog(@"== End ==\n\n");
这是我的结果
> == Initializing == > imageData length: 1882694 > data length: 1888365 > data5 length: 1102461 > == End == > == Image from Data5 == > dataFromImageFromData5 length: 1646137 > dataFiveFromImageWithData5 length: 1102115 > == End == Try a different image > == Initializing == > imageData length: 3620257 > data length: 2889458 > data5 length: 1404750 > == End == > == Image from Data5 == > dataFromImageFromData5 length: 2007951 > dataFiveFromImageWithData5 length: 1405398 > == End ==
I have an jpeg image and I want to be able to incrementally compress it using Cocoa/Core Image/Core Graphics. For example, I have A.jpg (3MB), I compress A and get B.jpg (1MB), compress B and get C.jpg (400KB), and so on till the image can't be compressed anymore.
I am trying to use NSBitmapImageRep representationUsingType:properties without much success. I use an image rep created from compressed image data to try and compress further, but this doesn't work well, if I use a compression factor that is the same factor used to create the initial compressed data.
Here is the code that I have been wrangling with
NSString * fileName = @"largeImage.jpg"; NSLog(@"== Initializing ==\n"); NSData * imageData = [NSData dataWithContentsOfFile:fileName]; NSLog(@"imageData length: %d\n", [imageData length]); NSImage * image = [[NSImage alloc] initWithData:imageData]; NSBitmapImageRep * bitmapRep = [[image representations] objectAtIndex:0]; NSData * data = [bitmapRep representationUsingType:NSJPEGFileType properties:nil]; NSLog(@"data length: %d\n", [data length]); NSDictionary * dict = [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat:0.5] forKey:NSImageCompressionFactor]; NSData * data5 = [bitmapRep representationUsingType:NSJPEGFileType properties:dict]; NSLog(@"data5 length: %d\n", [data5 length]); NSLog(@"== End ==\n\n"); NSLog(@"== Image from Data5 ==\n"); NSImage * imageFromData5 = [[NSImage alloc] initWithData:data5]; NSBitmapImageRep * bitmapRepFromData5 = [[imageFromData5 representations] objectAtIndex:0]; NSData * dataFromImageFromData5 = [bitmapRepFromData5 representationUsingType:NSJPEGFileType properties:nil]; NSLog(@"dataFromImageFromData5 length: %d\n", [dataFromImageFromData5 length]); dict = [NSDictionary dictionaryWithObject: [NSNumber numberWithFloat:0.5] forKey:NSImageCompressionFactor]; NSData * dataFiveFromImageWithData5 = [bitmapRepFromData5 representationUsingType:NSJPEGFileType properties:dict]; NSLog(@"dataFiveFromImageWithData5 length: %d\n", [dataFiveFromImageWithData5 length]); NSLog(@"== End ==\n\n");
This is my result
> == Initializing == > imageData length: 1882694 > data length: 1888365 > data5 length: 1102461 > == End == > == Image from Data5 == > dataFromImageFromData5 length: 1646137 > dataFiveFromImageWithData5 length: 1102115 > == End == Try a different image > == Initializing == > imageData length: 3620257 > data length: 2889458 > data5 length: 1404750 > == End == > == Image from Data5 == > dataFromImageFromData5 length: 2007951 > dataFiveFromImageWithData5 length: 1405398 > == End ==
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每次都需要减小该系数。使用相同的质量级别重新压缩未经编辑的 JPEG 图像实际上根本不会改变结果太多,这应该可以解释为什么您没有看到尺寸有任何减小。
(如果您想确保质量不会降低超过必要的程度,则可以用递减的因子一遍又一遍地重新压缩原始图像,而不是像示例中那样链接它们。)
You need to decrease the factor every time. Recompressing a JPEG image that hasn't been edited, using the same quality level actually doesn't change the result much at all, which should explain why you aren't seeing any decrease in size.
(If you want to make sure the quality doesn't degrade more than necessary, it could make sense to recompress the original image over and over with decreasing factor instead of chaining them like in your example.)