iOS关于@2x,@3x的区别及图片的绘制

2018-09-04  本文已影响0人  周_xing_xing

为什么会有2倍,3倍图

网络上会有很多的解释,这些解释都是对的。

通俗点说,出现这种区别是因为,屏幕尺寸没有屏幕分辨率增长的快(所以更高清了)。所以,对于iPhone6来说,1pt(代码中的尺寸值单位,也可理解为屏幕物理尺寸的换算单位)代表2px。对于iPhone6P来说,1pt代表3px。

所以对于iPhone6P和iPhone6来说,我们如果都想在屏幕上显示一个100ptx100pt的图片。

iPhone6就需要加载一个尺寸 200px x 200px 的图片。

iPhone6P需要加载一个尺寸 300px x 300px 的图片。

因为如果iPhone6加载一个100px x 100px的图片,它实际上要填充的是200px x 200px像素的空间。所以会被放大,看起来就模糊了。

分2倍3倍图,是为了让不同设备显示图片能够更加清晰。

但是我们开发的时候,设计师通常会将3种大小的图都输出出来,我们也通常选择将3种规格的图片都拖到工程中(现在1x的设备快绝迹了,所以也可以只添加2x和3x)。

如果仅仅是为了显示更清晰,我们为什么不只用3倍图呢?

只用3倍图,不同手机加载之后也只会去缩小,可以避免因放大而导致的模糊。还会因为引入更少的图片,减少包的大小。

看起来挺好的,也没什么问题。

但是如果只用3倍图,可能会引入如下问题(按照上面例子):

iPhone6加载3倍图时,首先会将3倍图数据加载到内存中,造成了一定的内存损耗,因为大多数情况下,2倍图会比3倍图尺寸小一些。

iPhone6加载300px x 300px 的图片后,图片尺寸会变成 150pt x 150pt,如果显示要求 100pt x 100pt,需要给ImageView设定具体尺寸。而且缩放会增加一些计算量。

iPhone6在将要显示图片的时候,会将图片发送到GPU,GPU会为图片分配计算空间。如果图片大了一些,会消耗过多的GPU计算量。

有一些GPU只允许传入长宽都是2的N次幂尺寸的图片,所以传入GPU前,需要将图片变大为长宽均为2的N次幂。如果图片大了一些,会增加很多计算量,也会急剧增加内存消耗。

如果同时引入3种尺寸的图片,能够避免上述问题。根据经验,多引入的2种尺寸图片,对ipa包体的大小影响极小。

获取当前屏幕px和pt的关系

可以使用 UIScreen.main.scale (OC: [UIScreen mainScreen].scale)来获取 1pt = ?px 的值。

iPhone6中 这个值为2。

iPhone6p中 这个值为3。

比如,我们想要绘制一条高度为1px的线。我们就可以这样写:

//这个 1.0 / UIScreen.main.scale 得到的就是1px对应的pt数值let lineView =UIView(frame:CGRect(x:0, y:100, width:UIScreen.main.bounds.width, height:1.0/UIScreen.main.scale));superView.addSubview(lineView);

绘制图片

如果我们有如下需求,可能就需要自己绘制图片了。

需要对已存在的图片进行修改,比如尺寸修改,添加水印等。

需要根据不同的需求生成图片,比如将富文本变成图片。

需要将当前的某个View输出成图片。

绘制的基本代码如下:

func test(){    let size =CGSize(width:100, height:100)    var img =nil;//开启绘制环境//第一个参数 size 表示将要绘制的图片尺寸(单位是pt)。//第二个参数 固定传false,如果置为true,则不会绘制透明区域,透明区域会变成黑色。//第三个参数 表示输出的图片是几倍图。一般设为 UIScreen.main.scale,如果你设置的数值小于 UIScreen.main.scale,绘制出的图片可能会比较模糊(图片的物理尺寸小于size),如果大于UIScreen.main.scale,图片可能会被缩放(图片物理尺寸大于size)。这里物理尺寸指将生成的图片,输出成文件后的图片文件尺寸。//另一个重载函数:UIGraphicsBeginImageContext(CGSize) scale值总是1。UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.main.scale);        ...具体绘制工作//从环境中将绘制的图片输出到img中img =UIGraphicsGetImageFromCurrentImageContext();//结束绘制,释放资源UIGraphicsEndImageContext();// img 就是绘制后的图片iflet i = img {        let imgData =UIImagePNGRepresentation(i);//若UIGraphicsBeginImageContextWithOptions第三个参数为scale,输出的sava.png的尺寸将为 (size.width x scale, size.height x scale),单位是px。imgData?.write(to: URL.init(fileURLWithPath:"save.png"));    }}

细节请看上面注释,另外有2点需要注意。

整个过程所有计算尺寸都是pt。

scale只与输出图片的大小有关,不参与任何尺寸计算。

内容就这么多,下面介绍几个常用的绘制图片的例子:

publicclassTest {//缩放publicstaticfunc resize(srcImg:UIImage, toSize:CGSize) ->UIImage? {UIGraphicsBeginImageContextWithOptions(toSize,false,UIScreen.main.scale);                srcImg.draw(in:CGRect(x:0, y:0, width: toSize.width, height: toSize.height));                let img =UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();returnimg;    }//截图publicstaticfunc screenShot() ->UIImage? {iflet windowLayer =UIApplication.shared.keyWindow?.layer {UIGraphicsBeginImageContextWithOptions(UIScreen.main.bounds.size,false,UIScreen.main.scale);iflet ctx =UIGraphicsGetCurrentContext() {                windowLayer.render(in: ctx);            }            let img =UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();returnimg;        }returnnil;    }//根据传入颜色生成图片publicstaticfunc createImage(color:UIColor, size:CGSize) ->UIImage? {UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.main.scale);iflet ctx =UIGraphicsGetCurrentContext() {            let layer =CALayer.init();            layer.backgroundColor = color.cgColor;            layer.bounds =CGRect(x:0, y:0, width: size.width, height: size.height);            layer.render(in: ctx);        }        let img =UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();returnimg;    }//根据富文本生成图片publicstaticfunc createImage(attributedString:NSAttributedString, size:CGSize) ->UIImage? {UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.main.scale);                attributedString.draw(in:CGRect(x:0, y:0, width: size.width, height: size.height));                let img =UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();returnimg;    }}

作者:hard_man

链接:https://www.jianshu.com/p/cd72ad707bf3

來源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

上一篇下一篇

猜你喜欢

热点阅读