当前位置:首页 > 技术心得 > 正文内容

获取NSImage图片的准确大小

xjtudll11年前 (2016-01-07)技术心得16150

问题:

NSImage加载图片的时候无法准确获得图片的大小

测试代码:

NSImage *image = [NSImage imageNamed:@"image"];

NSLog(@"%f, %f", image.size.width, image.size.height);

//终端Log到的图片的尺寸是:185.250000, 106.500000,而实际的大小是274.0, 142.0。

//image.size = NSMakeSize(247.0, 142.0); //强制指定尺寸能够解决问题

分析:

用一个Image Well来显示图片的时候,发现图片居然比实际的要小!我试着NSLog图片的大小,发现NSImage加载的图片的size根本就是错的!我根据图片的实际大小,强制设置了图片的尺寸,图片就显示正常了,而且也没有被拉伸的痕迹。这说明图片数据在加载后并没有损耗,只是图片的size属性出错了,因此,强制设置size属性,图片就能正常显示了。

在搜索了一番之后,发现这个问题似乎和图片的DPI有关。如果图片的DPI不是72,NSImage加载图片后size属性就会出错。我在iOS上用同样的方法做了测试,发现UIImage则没有类似的问题。虽然我对图片的DPI的概念也是一知半解,但是,像72 DPI这种应该算是历史的包袱了,毕竟Cocoa是一个非常古老的框架了。

虽然在这里,人肉设置图片大小能够解决问题,不过总不能在以后的代码中都人肉设置每张图片的尺寸吧。总有什么准确的方法来获取图片的真实像素尺寸的。然后就找到了Stack Overflow里的这个问题,解决方法是这样的:// 不要用这个方法,这个方法并不一定总能成功。

NSBitmapImageRep *rep = [[image representations] objectAtIndex: 0];

NSSize size = NSMakeSize([rep pixelsWide], [rep pixelsHigh]);

[image setSize: size];

我试了一下这个方法,确实能够解决我的问题。不过这个方法下面,两个开发人员的对话很有启发,其中一人提到了一个问题,那就是NSImage可能并不存在NSBitmapImageRep--这并不稀奇,比如,用Mac的摄像头拍下的图片就没有!因此,一定有更好的方法。

解决办法:

在Stack Overflow上找到了另一个更加靠谱的方法

NSImage *image = [NSImage imageNamed:@"image"];

NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];

NSSize size = NSMakeSize([rep pixelsWide], [rep pixelsHigh]);

[image setSize: size];

至此,问题完美解决。不过这个问题提醒了我,不要对Cocoa的内建对象想当然,一定要注意Cocoa框架中的陷阱。这种方法其实在原理上和之前说的那个有缺陷的方法并没有非常本质的不同。只是这种方法是创建了一个NSBitmapImageRep,而不是从图片中获取一个。这样,就不会存在图片对象中无法获取NSBitmapImageRep的问题了。

扫描二维码推送至手机访问。

版权声明:本文由鸟的天空发布,如需转载请注明出处。

本文链接:http://www.xjtudll.cn/Exp/381/

标签: cocoa
分享给朋友:

“获取NSImage图片的准确大小” 的相关文章

远程连接:发生身份验证错误 要求的函数不受支持

远程连接:发生身份验证错误 要求的函数不受支持

问题: 远程连接失败,提示:发生身份验证错误 要求的函数不受支持 操作系统: Win7 64bit 原因:打了系统补丁,权限被限制了,需要修改客户端电脑相关权限。 解决过程如下: 双击“加密Oracle修正“ 然后重新打开远程登录客户端就可以登录了。...

运放输出电压摆幅的问题

运放的输出电压是有限制的,普通运放的输出电压范围一般是(Vss+1.5~Vcc-1.5)V,比如电源电压是±15V,运放能输出的最低电压为-13.5V,最高电压为13.5V,超过这个电压范围即被限幅。这个特性导致电源电压不能被充分利用,特别是电池工作的设备,工作电压很低,这个问题特别突出,于是出现了...

Excel引用单元格地址的方法

单元格本身有两种表示方式: 1、列用字母,行用数字 例如:A1表示第一行第一列,A2表示第二行第一列 2、R表示行,C表示列 例如:R1C1就表示1行1列,R5C8就表示第5行第8列。 Excel单元格地址引用有两大方式:相对引用和绝对引用。 (1) 对于第一种单元格表示方式(A1) 其相对引用和绝...

如何去掉页眉的表格后的回车

如何去掉页眉的表格后的回车

原文链接:http://club.excelhome.net/forum.php?mod=viewthread&tid=901578&highlight=&jdfwkey=piezu 想在页眉里加入一个表格,但是加入表格后,表格后多了一行回车,导致页眉与正文之间有较大的间距,...

金蝶 KFO.Dictionary 怎么写

.Net 调用,以C#为例,调用如下: 1、添加kfo.dll的引用。 2、调用方法 KFO.Dictionary dct=new KFO.Dictionary(); dct.let_value("FInteID",100);...

IAR STM8 #pragma optimize 指令

IAR STM8 #pragma optimize 指令

参考资料:http://blog.csdn.net/niepangu/article/details/38066319 #pragma optimize= none  //one of none, low, medium, high, size, or speed放在被优化函数前 ...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。