在页面多圆角视图的情况下,会导致页面卡顿,取消圆角绘制后会明显察觉页面流畅;
若在在tableview下,滚动视图每次都会执行绘制圆角,自然会造成页面UI阻塞。因而需要对圆角优化,提高页面流畅度。
self.layer.cornerRadius = cornerRadius;
self.layer.masksToBounds = YES;
// 设置栅格化后,图层会被渲染成图片,并且缓存,再次使用时,不会重新渲染
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
self.layer.shouldRasterize = YES;
/* When true, the layer is rendered as a bitmap in its local coordinate
* space ("rasterized"), then the bitmap is composited into the
* destination (with the minificationFilter and magnificationFilter
* properties of the layer applied if the bitmap needs scaling).
* Rasterization occurs after the layer's filters and shadow effects
* are applied, but before the opacity modulation. As an implementation
* detail the rendering engine may attempt to cache and reuse the
* bitmap from one frame to the next. (Whether it does or not will have
* no affect on the rendered output.)
*
* When false the layer is composited directly into the destination
* whenever possible (however, certain features of the compositing
* model may force rasterization, e.g. adding filters).
*
* Defaults to NO. Animatable. */
@property BOOL shouldRasterize;
/* The scale at which the layer will be rasterized (when the
* shouldRasterize property has been set to YES) relative to the
* coordinate space of the layer. Defaults to one. Animatable. */
@property CGFloat rasterizationScale;
当 shouldRasterize 设成 YES 时,layer 被渲染成一个 bitmap位图,并缓存起来,等下次使用时不会再重新去渲染了。实现圆角本身就是在做颜色混合(blending),如果每次页面出来时都blending,消耗太大,这时shouldRasterize = ,下次就只是简单的从渲染引擎的缓存里读取那张 bitmap位图,节约系统资源。
位图就是一个像素数组,数组中的每个像素就代表着图片中的一个点。我们在应用中经常用到的 JPEG 和 PNG 图片就是位图。
但需要注意一点,在对UIImageView使用栅格化圆角后并使用SDWebImage
加载网络图片会造成图片模糊问题,此时还是尽量使用无栅格化的圆角绘制方式。
self.layer.cornerRadius = cornerRadius;
self.layer.masksToBounds = YES;
不管是 JPEG 还是 PNG 图片,都是一种压缩的位图图形格式,而SDWebImage则是对图片进行强制解压缩。
猜测原因在于SDWebImage使用 CGBitmapContextCreate
强制解压缩后的位图布局信息与绘制圆角渲染成的位图布局信息冲突,系统在CGImageAlphaInfo
上只识别到了绘制圆角使用到的kCGImageAlphaNoneSkipFirst
而非SDWebImage设置的kCGImageAlphaNoneSkipLast
属性,导致颜色分量使用的是5位而不是8位,因此造成图像质量降低,造成了模糊问题。
/* Create a bitmap context. The context draws into a bitmap which is `width'
pixels wide and `height' pixels high. The number of components for each
pixel is specified by `space', which may also specify a destination color
profile. Note that the only legal case when `space' can be NULL is when
alpha is specified as kCGImageAlphaOnly.The number of bits for each component
of a pixel is specified by `bitsPerComponent'. The number of bytes per pixel
is equal to `(bitsPerComponent * number of components + 7)/8'. Each row of
the bitmap consists of `bytesPerRow' bytes, which must be at least
`width * bytes per pixel' bytes; in addition, `bytesPerRow' must be an
integer multiple of the number of bytes per pixel. `data', if non-NULL,
points to a block of memory at least `bytesPerRow * height' bytes.
If `data' is NULL, the data for context is allocated automatically and freed
when the context is deallocated. `bitmapInfo' specifies whether the bitmap
should contain an alpha channel and how it's to be generated, along with
whether the components are floating-point or integer. */
/*CGBitmapContextCreate这个函数用于创建一个位图上下文,用来绘制一张宽 width 像素,高 height 像素的位图。*/
/*
data :如果不为 NULL ,那么它应该指向一块大小至少为 bytesPerRow * height 字节的内存;如果 为 NULL ,那么系统就会为我们自动分配和释放所需的内存,所以一般指定 NULL 即可;
width 和 height :位图的宽度和高度,分别赋值为图片的像素宽度和像素高度即可;
bitsPerComponent :像素的每个颜色分量使用的 bit 数,在 RGB 颜色空间下指定 8 即可;
bytesPerRow :位图的每一行使用的字节数,大小至少为 width * bytes per pixel 字节。有意思的是,当我们指定 0 时,系统不仅会为我们自动计算,而且还会进行 cache line alignment 的优化
space :就是我们前面提到的颜色空间,一般使用 RGB 即可;
bitmapInfo :位图的布局信息。
*/
CG_EXTERN CGContextRef __nullable CGBitmapContextCreate(void * __nullable data,
size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow,
CGColorSpaceRef cg_nullable space, uint32_t bitmapInfo)
CG_AVAILABLE_STARTING(10.0, 2.0);
第三方库参数信息
//CGBitmapInfo
typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {
kCGImageAlphaNone, /* For example, RGB. */
kCGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */
kCGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */
kCGImageAlphaLast, /* For example, non-premultiplied RGBA */
kCGImageAlphaFirst, /* For example, non-premultiplied ARGB */
kCGImageAlphaNoneSkipLast, /* For example, RBGX. */
kCGImageAlphaNoneSkipFirst, /* For example, XRGB. */
kCGImageAlphaOnly /* No color data, alpha data only */
};
* alpha 的信息;
* 颜色分量是否为浮点数;
* 像素格式的字节顺序。
//CGImageAlphaInfo
typedef CF_OPTIONS(uint32_t, CGBitmapInfo) {
kCGBitmapAlphaInfoMask = 0x1F,
kCGBitmapFloatInfoMask = 0xF00,
kCGBitmapFloatComponents = (1 << 8),
kCGBitmapByteOrderMask = kCGImageByteOrderMask,
kCGBitmapByteOrderDefault = (0 << 12),
kCGBitmapByteOrder16Little = kCGImageByteOrder16Little,
kCGBitmapByteOrder32Little = kCGImageByteOrder32Little,
kCGBitmapByteOrder16Big = kCGImageByteOrder16Big,
kCGBitmapByteOrder32Big = kCGImageByteOrder32Big
} CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
* 是否包含 alpha ;
* 如果包含 alpha ,那么 alpha 信息所处的位置,在像素的最低有效位,比如 RGBA ,还是最高有效位,比如 ARGB ;
* 如果包含 alpha ,那么每个颜色分量是否已经乘以 alpha 的值,这种做法可以加速图片的渲染时间,因为它避免了渲染时的额外乘法运算。比如,对于 RGB 颜色空间,用已经乘以 alpha 的数据来渲染图片,每个像素都可以避免 3 次乘法运算,红色乘以 alpha ,绿色乘以 alpha 和蓝色乘以 alpha 。
像素格式
像素格式是用来描述每个像素的组成格式,包含信息内容
- Bits per component :一个像素中每个独立的颜色分量使用的 bit 数;
- Bits per pixel :一个像素使用的总 bit 数;
- Bytes per row :位图中的每一行使用的字节数。
对于位图来说,像素格式并不是随意组合的,目前只支持以下有限的17种组合格式
组合模式
对于 iOS 来说,只支持 8 种像素格式。其中颜色空间为 Null 的 1 种,Gray 的 2 种,RGB 的 5 种,CMYK 的 0 种。换句话说,iOS 并不支持 CMYK 的颜色空间。
在16 或 32 位像素格式的 CMYK 和 RGB 颜色空间下,一个像素的表示方式
16 或 32 位像素格式的 CMYK 和 RGB 颜色空间下,一个像素的表示方式
在 32 位像素格式下,每个颜色分量使用 8 位;而在 16 位像素格式下,每个颜色分量则使用 5 位。
色彩模式ARGB_8888、ARGB_4444、 RGB_565、 ALPHA_8的区别
Bitmap.Config ARGB_8888:由4个8位组成,即A=8,R=8,G=8,B=8,那么一个像素点占8+8+8+8=32位(4字节)
Bitmap.Config ARGB_4444:由4个4位组成,即A=4,R=4,G=4,B=4,那么一个像素点占4+4+4+4=16位 (2字节)
Bitmap.Config RGB_565:没有透明度,R=5,G=6,B=5,,那么一个像素点占5+6+5=16位(2字节)
Bitmap.Config ALPHA_8:每个像素占8位,只有透明度,没有颜色。
一般情况下我们使用的色彩模式为ARGB_8888,这种模式下一个像素所占的大小为4字节,一个像素的位数总和越高,图像也就越逼真。
假设有一张480x800的图片,在色彩模式为ARGB_8888的情况下,会占用 4808004/1024KB=1500KB 的内存;而在RGB_565的情况下,占用的内存为:4808002/1024KB=750KB。
网友评论