当我使用UIImagePNGRepresentation或UIImageJPEGRepresentation将UIImage转换为NSData时,图像大小增加得太多。

14

当我使用UIImagePNGRepresentation或UIImageJPEGRepresentation将UIImage转换为NSData时,图像大小增加了很多。

重现步骤:

1)打开Xcode并选择新项目作为基于单个视图的应用程序

2)打开ViewController.xib并添加两个按钮,分别命名为i)Test Online Image ii)Test Local image

3)添加两个IBAction

  i)  -(IBAction)ClickLocalImageTest:(id)sender;

  ii) -(IBAction)ClickOnLineImageTest:(id)sender;

4)将“测试在线图片”连接到“-(IBAction)ClickOnLineImageTest:(id)sender”,将“测试本地图片”连接到“-(IBAction)ClickLocalImageTest:(id)sender”;

5)实现以下方法:-(IBAction)ClickLocalImageTest:(id)sender

- (IBAction)ClickLocalImageTest:(id)sender {
    NSLog(@"*************Test Local Image****************\n");
    NSString *path=[[NSBundle mainBundle] pathForResource:@"hero_ipad_retina" ofType:@"jpg"];
    NSLog(@"Before testing image size is :<---- %u kb",[[NSData dataWithContentsOfFile:path] length]/1024);
    UIImage *img  = [UIImage imageNamed:@"hero_ipad_retina.jpg"];
     NSLog(@"UIImagePNGRepresentation: image size is---->: %u kb",[UIImagePNGRepresentation(img) length]/1024);
    NSLog(@"UIImageJPEGRepresentation with scale 1.0: image size is---->: %u kb \n",[UIImageJPEGRepresentation(img, 1.0) length]/1024);
    NSLog(@"*************Completed test****************\n\n\n\n");
} 

6) 将 impalement 方法 "- (IBAction)ClickOnLineImageTest:(id)sender" 编写如下:

- (IBAction)ClickOnLineImageTest:(id)sender {
     NSLog(@"*************Test Online Image****************\n");
NSLog(@"Before testing image size is :<---- %u kb",[[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://images.apple.com/home/images/hero_ipad_retina.jpg"]] length]/1024);
UIImage *img  = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://images.apple.com/home/images/hero_ipad_retina.jpg"]]];
NSLog(@"UIImagePNGRepresentation: image size is---->: %u kb",[UIImagePNGRepresentation(img) length]/1024);
NSLog(@"UIImageJPEGRepresentation with scale 1.0: image size is---->: %u kb \n",[UIImageJPEGRepresentation(img, 1.0) length]/1024);
NSLog(@"*************Completed test****************\n\n\n\n");
}

7)请从这里下载"hero_ipad_retina.jpg"图像,并将其命名为"hero_ipad_retina.jpg"保存在您的资源中。

7)现在在Xcode 4.0及以上版本和IOS3.0以上版本的SDK上运行此项目。

**

Expected Results:
1)Click on "Test Online Image" button result should be as following 
*************Test Online Image****************
Before testing image size is :<---- 78 kb
UIImagePNGRepresentation: image size is---->: 78 kb
UIImageJPEGRepresentation with scale 1.0: image size is---->: 78 kb
*************Completed test****************
2)1)Click on "Test Local image" button result should be as following
*************Test Local Image****************
Before testing image size is :<---- 78 kb
UIImagePNGRepresentation: image size is---->: 78 kb
UIImageJPEGRepresentation with scale 1.0: image size is---->: 78 kb 
*************Completed test****************
Actual Results:
1)Click on "Test Online Image" button result should be as following 
*************Test Online Image****************
Before testing image size is :<---- 78 kb
UIImagePNGRepresentation: image size is---->: 480 kb
UIImageJPEGRepresentation with scale 1.0: image size is---->: 180 kb
*************Completed test****************
2)1)Click on "Test Local image" button result should be as following
*************Test Local Image****************
Before testing image size is :<---- 78 kb
UIImagePNGRepresentation: image size is---->: 480 kb
UIImageJPEGRepresentation with scale 1.0: image size is---->: 180 kb 
*************Completed test******************

我的问题:

为什么它的大小在增加?将图像转换为NSData的最佳方法是什么?

注: 请从这里下载“hero_ipad_retina.jpg”图像,并保存到您的资源中。


1
哇,这是我读到的第一个看起来像苹果雷达的问题...不确定我的感觉如何。 - CodaFi
@GovindaraoKondala,你提出问题的方式很棒,点赞!我想知道…… - Honey
1个回答

9
"

hero_ipad_retina.jpg"是一张经过压缩的jpg图片。

这行代码:

[[NSData dataWithContentsOfFile:path] length]/1024

这里是需要翻译的内容:

给出它的压缩文件大小...

这一行:

[UIImagePNGRepresentation(img) length]/1024

解压图像并将其转换为PNG格式,这是一种无损文件格式。它的大小不可避免地更大。

这行:

[UIImageJPEGRepresentation(img, 1.0) length]/1024  

解压缩图像并将其重新压缩为JPG表示。您已将质量设置为最高(1.0),因此与原始图像相比,后者无疑被压缩到较低的质量,因此文件大小更大。如果将质量设置为0.5,则文件大小较小(约为42K)。

这是一个很好的提醒,告诉我们为什么应该谨慎处理JPEG图像。每次访问JPEG图像时,都会进行解压缩。如果你再重新压缩-即使使用全质量-图像的质量也会降低(因为每次有损压缩都比上一次更差)。伴随着平面颜色、直/对比较明显的边缘,锯齿状增加变得特别明显。PNG总是更安全的选择——它在24位下是无损的,在8位下可以很好地处理平面颜色区域。

更新

要获取内存中图像的大小:

NSUInteger sizeInBytes  = 
  CGImageGetHeight(image.CGImage) * CGImageGetBytesPerRow(image.CGImage);

通过这个你可以计算PNG、JPG和原始文件的压缩比(将以上数字除以1024即可得到以千字节为单位的正确比率)。


即使我从本地或在线阅读,大小差异可能只有20到30%。但在这种情况下,它超过了300%? - Govindarao Kondala
@HelpMeToHelpYou 这是预料中的。这就是为什么在线使用JPEG格式 - 它可以将文件大小缩小到原来的10倍甚至更多(这完全取决于质量设置)。如果你在预览中打开原始的JPEG文件并导出为(1)PNG;(2)JPG副本,你会得到同样的结果。调整压缩设置,你会看到文件大小和质量的巨大差异。 - foundry
假设我读取本地或在线的PNG图像,那么它们的大小会相同吗?谢谢。 - Govindarao Kondala
这个也适用于透明PNG图片吗?比如说我把我的透明图片保存成JPEG格式,这样可以让图片更小(以KB为单位)吗? - Reza.Ab
2
@Reza.Ab - JPEG不支持透明度。当您重新打开JPEG版本时,您将获得较小的文件大小,但透明度将丢失。 - foundry
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接