官方文档Large Image Downsizing
https://developer.apple.com/library/content/samplecode/LargeImageDownsizing/Introduction/Intro.html
#define bytesPerMB 1048576.0f //1MB=1024KB=1024*1024字节
#define bytesPerPixel 4.0f //1像素4字节
#define pixelsPerMB ( bytesPerMB / bytesPerPixel ) //1MB中有多少像素
//use the width and height to calculate the total number of pixels in the input image.
sourceTotalPixels = sourceResolution.width * sourceResolution.height;
//calculate the number of MB that would be required to store this image uncompressed in memory.
sourceTotalMB = sourceTotalPixels / pixelsPerMB;
//根据机型设置 期望的未压缩的图片大小 kDestImageSizeMB, 并 * pixelsPerMB = destTotalPixels (期望的像素大小)
//计算出压缩倍数
imageScale = destTotalPixels / sourceTotalPixels;
//得出期望的宽高
destResolution.width = (int)( sourceResolution.width * imageScale );
destResolution.height = (int)( sourceResolution.height * imageScale );
// create an offscreen bitmap context that will hold the output image pixel data,
// as it becomes available by the downscaling routine.
// use the RGB colorspace as this is the colorspace iOS GPU is optimized for.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
//bitmap的每一行在内存所占的比特数
int bytesPerRow = bytesPerPixel * destResolution.width;
// allocate enough pixel data to hold the output image.
void* destBitmapData = malloc( bytesPerRow * destResolution.height );
// create the output bitmap context
destContext = CGBitmapContextCreate( destBitmapData, destResolution.width, destResolution.height, 8,
bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast );
//通过调用CGContextTranslateCTM函数来修改每个点的x, y坐标值
CGContextTranslateCTM( destContext, 0.0f, destResolution.height );
//缩放操作根据指定的x, y因子来改变坐标空间的大小,从而放大或缩小图像。
//x, y因子的大小决定了新的坐标空间是否比原始坐标空间大或者小。
//另外,通过指定x因子为负数,可以倒转x轴,同样可以指定y因子为负数来倒转y轴。
CGContextScaleCTM( destContext, 1.0f, -1.0f );
// sub rect of the input image bounds that represents the
// maximum amount of pixel data to load into mem at one time.
CGRect sourceTile;
sourceTile.size.width = sourceResolution.width;
kSourceImageTileSizeMB
//设置压缩时对于源图像使用到的*块*的最大字节数。
//The tile size will be (x)MB of uncompressed image data.
#define tileTotalPixels kSourceImageTileSizeMB * pixelsPerMB
sourceTile.size.height = (int)( tileTotalPixels / sourceTile.size.width );
函数原型:
CGContextRef CGBitmapContextCreate (
void *data,
size_t width,
size_t height,
size_t bitsPerComponent,
size_t bytesPerRow,
CGColorSpaceRef colorspace,
CGBitmapInfo bitmapInfo
);
参数:
data 指向要渲染的绘制内存的地址。这个内存块的大小至少是(bytesPerRow*height)个字节
width bitmap的宽度,单位为像素
height bitmap的高度,单位为像素
bitsPerComponent 内存中像素的每个组件的位数.例如,对于32位像素格式和RGB 颜色空间,你应该将这个值设为8.
bytesPerRow bitmap的每一行在内存所占的比特数
colorspace bitmap上下文使用的颜色空间。
bitmapInfo 指定bitmap是否包含alpha通道,像素中alpha通道的相对位置,像素组件是整形还是浮点型等信息的字符串。
描述:
当你调用这个函数的时候,Quartz创建一个位图绘制环境,也就是位图上下文。当你向上下文中绘制信息时,
Quartz把你要绘制的信息作为位图数据绘制到指定的内存块。
一个新的位图上下文的像素格式由三个参数决定:
每个组件的位数,颜色空间,alpha选项。alpha值决定了绘制像素的透明性。
iOS kCGImageAlphaPremultipliedLast与kCGImageAlphaLast区别和联系
原文 http://blog.csdn.net/jeffasd/article/details/78142067
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 */
};
CGImageAlphaInfo包含以下信息:
* 是否包含 alpha ;
* 如果包含 alpha ,那么 alpha 信息所处的位置,在像素的[最低有效位](https://zh.wikipedia.org/wiki/%E6%9C%80%E4%BD%8E%E6%9C%89%E6%95%88%E4%BD%8D),比如 RGBA ,还是[最高有效位](https://zh.wikipedia.org/wiki/%E6%9C%80%E9%AB%98%E6%9C%89%E6%95%88%E4%BD%8D),比如 ARGB ;
* 如果包含 alpha ,那么每个颜色分量是否已经乘以 alpha 的值,这种做法可以加速图片的渲染时间,因为它避免了渲染时的额外乘法运算。比如,对于 RGB 颜色空间,用已经乘以 alpha 的数据来渲染图片,每个像素都可以避免 3 次乘法运算,红色乘以 alpha ,绿色乘以 alpha 和蓝色乘以 alpha 。
那么我们在解压缩图片的时候应该使用哪个值呢?根据 [Which CGImageAlphaInfo should we use](http://stackoverflow.com/questions/23723564/which-cgimagealphainfo-should-we-use)和官方文档中对 UIGraphicsBeginImageContextWithOptions 函数的讨论:
You use this function to configure the drawing environment for rendering into a bitmap. The format for the bitmap is a ARGB 32-bit integer pixel format using host-byte order. If the opaque parameter is YES, the alpha channel is ignored and the bitmap is treated as fully opaque (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host). Otherwise, each pixel uses a premultipled ARGB format (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host).
我们可以知道,当图片不包含 alpha 的时候使用 kCGImageAlphaNoneSkipFirst ,否则使用 kCGImageAlphaPremultipliedFirst 。
alpha 通道布局信息,实际上也有一个枚举值:
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 */
};
上面的注释其实写很清楚,如果没有 alhpa 分量,那就是 kCGImageAlphaNone。带有 skip 的两个 kCGImageAlphaNoneSkipLast和kCGImageAlphaNoneSkipFirst即有 alpha 分量,但是忽略该值,相当于透明度不起作用。kCGImageAlphaOnly只有 alpha 值,没有颜色值。另外 4 个都表示带有 alpha 通道。带有 Premultiplied,说明在图片解码压缩的时候,就将 alpha 通道的值分别乘到了颜色分量上,我们知道 alpha 就会影响颜色的透明度,我们如果在压缩的时候就将这步做掉了,那么渲染的时候就不必再处理 alpha 通道了,这样可以提高渲染速度。First 和 Last的区别就是 alpha 分量是在像素存储的哪一边。例如一个像素点32位,表示4个分量,那么从左到右,如果是 ARGB,就表示 alpha 分量在 first,RGBA 就表示 alpha 分量在 last。
综上可知:kCGImageAlphaPremultipliedLast提前把alpha信息和RGB做了相乘已经把计算结果计算好了,这样在显示位图的时候直接显示就行了,这样就提高了性能,而kCGImageAlphaLast没有计算alpha的值,这样的话在显示位图的时候就需要计算alpha信息,导致性能低下。能使用kCGImageAlphaPremultipliedLast就尽量使用。
参考文章:
[http://blog.imerc.xyz/2017/07/09/ios-image-decode/](http://blog.imerc.xyz/2017/07/09/ios-image-decode/)
[http://blog.leichunfeng.com/blog/2017/02/20/talking-about-the-decompression-of-the-image-in-ios/](http://blog.leichunfeng.com/blog/2017/02/20/talking-about-the-decompression-of-the-image-in-ios/)