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

获取NSImage图片的准确大小

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

问题:

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图片的准确大小” 的相关文章

手表EL升压电路分析

手表EL升压电路分析

前言:折腾了许久的EL升压电路,总算是搞清楚原理了。 EL(Electroluminescence)发光屏是一种电致发光材料发光屏,在结构上,电致发光材料夹在两个电极之间。它的上电极是一种透明的导电膜,称为ITO膜(Indium Tin Oxide film),用于透射光线,而下电极是第二电极,其...

ios开发者帐号扣费成功 但是还是提示快到期??

ios开发者帐号扣费成功 但是还是提示快到期??

公司的ios开发者帐号快到期了,在apple developer(developer.apple.com),资料填写完毕后,按照提示,说可能要等24小时。 过了一段时间,信用卡收到了扣费通知,想着扣费成功了,帐号应该就是续费成功了,就没管了。加上那几天比较忙,就没去看邮件(gmail,访问太麻烦),...

android禁止屏幕自动锁屏(或背光自动灭)

  Android开发过程中,一些程序在运行时,不希望手机自动锁屏,即保持系统的背景灯常亮,以防止程序执行时出现异常,实现起来很简单,只需要在创建Activity时,在onCreate()方法中,加入如下语句即可。   getWindow().addFlags(WindowMan...

Protel99SE PCB各层的含义

本文收集于网络,整理而成,原文作者未知。 我们在进行印制电路板设计前,第一步就是要选择适用的工作层。Protel 99 SE提供有多种类型的工作层。只有在了解了这些工作层的功能之后,才能准确、可靠地进行印制电路板的设计。 Protel 99 SE所提供的工作层大致可以分为7类:Signal La...

水晶报表的文本对象中怎么插入换行符

水晶报表的文本对象中如何插入换行符?我的文本对象要显示的值是从RichTextBox中读出来的,但文本对象不能显示“\n”,怎么让文本对象换行呢?------解决方案--------------------1:不要用文本对象,用公式2:把\n替换成水晶报表里的换行符号Replace(字段,'...

布丁软件引起的桌面闪烁

问题描述: 进入桌面后,屏幕闪烁。 查找到系统日志: 错误应用程序名称: explorer.exe,版本: 6.3.9600.18231,时间戳: 0x56b8c9f1 错误模块名称: PDZipMenu64.dll,版本: 1.4.3.11014,时间戳: 0x5da4349a 异常代码: 0xc...

发表评论

访客

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