Large Image Downsizing

官方文檔Large Image Downsizing
https://developer.apple.com/library/content/samplecode/LargeImageDownsizing/Introduction/Intro.html

#define bytesPerMB 1048576.0f   //1MB=1024KB=1024*1024字節(jié)
#define bytesPerPixel 4.0f              //1像素4字節(jié)
#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;

//根據(jù)機(jī)型設(shè)置 期望的未壓縮的圖片大小 kDestImageSizeMB, 并 * pixelsPerMB = destTotalPixels (期望的像素大小) 
//計(jì)算出壓縮倍數(shù)
 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的每一行在內(nèi)存所占的比特?cái)?shù)
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 );

//通過調(diào)用CGContextTranslateCTM函數(shù)來修改每個點(diǎn)的x, y坐標(biāo)值
CGContextTranslateCTM( destContext, 0.0f, destResolution.height );
//縮放操作根據(jù)指定的x, y因子來改變坐標(biāo)空間的大小,從而放大或縮小圖像。
//x, y因子的大小決定了新的坐標(biāo)空間是否比原始坐標(biāo)空間大或者小。
//另外,通過指定x因子為負(fù)數(shù),可以倒轉(zhuǎn)x軸,同樣可以指定y因子為負(fù)數(shù)來倒轉(zhuǎn)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  
//設(shè)置壓縮時對于源圖像使用到的*塊*的最大字節(jié)數(shù)。  
//The tile size will be (x)MB of uncompressed image data.
#define tileTotalPixels kSourceImageTileSizeMB * pixelsPerMB
sourceTile.size.height = (int)( tileTotalPixels / sourceTile.size.width );  


函數(shù)原型:
CGContextRef CGBitmapContextCreate (
   void *data,
   size_t width,
   size_t height,
   size_t bitsPerComponent,
   size_t bytesPerRow,
   CGColorSpaceRef colorspace,
   CGBitmapInfo bitmapInfo
);

參數(shù):
data         指向要渲染的繪制內(nèi)存的地址。這個內(nèi)存塊的大小至少是(bytesPerRow*height)個字節(jié)
width       bitmap的寬度,單位為像素
height       bitmap的高度,單位為像素
bitsPerComponent        內(nèi)存中像素的每個組件的位數(shù).例如,對于32位像素格式和RGB 顏色空間,你應(yīng)該將這個值設(shè)為8.
bytesPerRow   bitmap的每一行在內(nèi)存所占的比特?cái)?shù)
colorspace       bitmap上下文使用的顏色空間。
bitmapInfo      指定bitmap是否包含alpha通道,像素中alpha通道的相對位置,像素組件是整形還是浮點(diǎn)型等信息的字符串。

描述:
當(dāng)你調(diào)用這個函數(shù)的時候,Quartz創(chuàng)建一個位圖繪制環(huán)境,也就是位圖上下文。當(dāng)你向上下文中繪制信息時,
Quartz把你要繪制的信息作為位圖數(shù)據(jù)繪制到指定的內(nèi)存塊。
一個新的位圖上下文的像素格式由三個參數(shù)決定:
每個組件的位數(shù),顏色空間,alpha選項(xiàng)。alpha值決定了繪制像素的透明性。
iOS kCGImageAlphaPremultipliedLast與kCGImageAlphaLast區(qū)別和聯(lián)系
原文 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 ,那么每個顏色分量是否已經(jīng)乘以 alpha 的值,這種做法可以加速圖片的渲染時間,因?yàn)樗苊饬虽秩緯r的額外乘法運(yùn)算。比如,對于 RGB 顏色空間,用已經(jīng)乘以 alpha 的數(shù)據(jù)來渲染圖片,每個像素都可以避免 3 次乘法運(yùn)算,紅色乘以 alpha ,綠色乘以 alpha 和藍(lán)色乘以 alpha 。

那么我們在解壓縮圖片的時候應(yīng)該使用哪個值呢?根據(jù) [Which CGImageAlphaInfo should we use](http://stackoverflow.com/questions/23723564/which-cgimagealphainfo-should-we-use)和官方文檔中對 UIGraphicsBeginImageContextWithOptions 函數(shù)的討論:

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).

我們可以知道,當(dāng)圖片不包含 alpha 的時候使用 kCGImageAlphaNoneSkipFirst ,否則使用 kCGImageAlphaPremultipliedFirst 。

alpha 通道布局信息,實(shí)際上也有一個枚舉值:

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 */

};

上面的注釋其實(shí)寫很清楚,如果沒有 alhpa 分量,那就是 kCGImageAlphaNone。帶有 skip 的兩個 kCGImageAlphaNoneSkipLast和kCGImageAlphaNoneSkipFirst即有 alpha 分量,但是忽略該值,相當(dāng)于透明度不起作用。kCGImageAlphaOnly只有 alpha 值,沒有顏色值。另外 4 個都表示帶有 alpha 通道。帶有 Premultiplied,說明在圖片解碼壓縮的時候,就將 alpha 通道的值分別乘到了顏色分量上,我們知道 alpha 就會影響顏色的透明度,我們?nèi)绻趬嚎s的時候就將這步做掉了,那么渲染的時候就不必再處理 alpha 通道了,這樣可以提高渲染速度。First 和 Last的區(qū)別就是 alpha 分量是在像素存儲的哪一邊。例如一個像素點(diǎn)32位,表示4個分量,那么從左到右,如果是 ARGB,就表示 alpha 分量在 first,RGBA 就表示 alpha 分量在 last。

綜上可知:kCGImageAlphaPremultipliedLast提前把a(bǔ)lpha信息和RGB做了相乘已經(jīng)把計(jì)算結(jié)果計(jì)算好了,這樣在顯示位圖的時候直接顯示就行了,這樣就提高了性能,而kCGImageAlphaLast沒有計(jì)算alpha的值,這樣的話在顯示位圖的時候就需要計(jì)算alpha信息,導(dǎo)致性能低下。能使用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/)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容