2015-07-03 84 views
0

我正在尋找優化從CGImage提取像素數據的例程。目前完成(非常低效)的方式是創建一個新的CGContext,將CGImage繪製到上下文中,然後從上下文中獲取數據。從CGImageRef獲取像素數據包含額外的字節?

我有以下優化程序來處理這個問題:

CGImageRef imageRef = image.CGImage; 
uint8_t *pixelData = NULL; 

CGDataProviderRef imageDataProvider = CGImageGetDataProvider(imageRef); 
CFDataRef imageData = CGDataProviderCopyData(imageDataProvider); 
pixelData = (uint8_t *)malloc(CFDataGetLength(imageData)); 
CFDataGetBytes(imageData, CFRangeMake(0, CFDataGetLength(imageData)), pixelData); 
CFRelease(imageData); 

這幾乎工程。在查看並比較通過兩種方法獲得的像素數據的十六進制轉儲後,我發現在上述情況下,每個6360字節有8個字節的0。否則,數據是相同的。例如 enter image description here

這裏是與沒有優化的版本比較: enter image description here

8個字節的0之後,正確的像素數據繼續。任何人都知道這是爲什麼發生?

UPDATE: 這裏是我的優化程序(將剪斷的代碼是剛開的尺寸信息和其他非重要的事情;相關的位是像素數據返回):

CGContextRef context = NULL; 
CGImageRef imageRef = image.CGImage; 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst; 

// ... SNIP ... 

context = CGBitmapContextCreate(...); 
CGColorSpaceRelease(colorSpace); 

// ... SNIP ... 

CGContextDrawImage(context, rect, imageRef); 
uint8_t *pixelData = (uint8_t *)CGBitmapContextGetData(context); 

CGContextRelease(context); 

顯然,這僅僅是爲了得到基礎像素數據而做的工作量過大。創建一個上下文,然後繪製到上下文中。第一個例程的速度是5到10倍之間。但正如我所指出的,除了在優化代碼中每6360字節插入8個零字節值(在圖像中突出顯示)之外,兩個例程返回的像素數據幾乎完全相同。

否則,其他一切都是相同的 - 顏色值,字節順序等

+1

我不清楚你是如何得到這兩個不同的像素緩衝區,什麼樣的資格作爲「優化」和其他「未優化」。我不清楚爲什麼你要經歷你描述的這個過程。要麼更清楚地描述你是如何得到這兩個像素緩衝區的,或者只是告訴我們你想要做什麼。 – Rob

+0

@Rob參見上面的更新。我正在通過該過程從CGImage獲取底層像素數據,以便將其傳遞給對各個像素進行操作的自定義渲染引擎。 – Chris

+0

我的觀點是,如果你想要圖像的底層像素數據,你不必經歷這個往返過程。 (但是,這個過程在處理異構圖像格式時很有用,並且您希望以單一一致的格式來獲取它。)爲了回答爲什麼有多餘的字節,我想保證兩個CGImageGetBytesPerRow會返回不同的價值。 – Rob

回答

2

位圖數據具有填充在每行像素的端部,舍入每行的字節數達到一較大的價值。 (在這種情況下,是16字節的倍數)。

添加此填充以使其更快地處理和繪製圖像。

您應該使用CGImageGetBytesPerRow()找出每行所佔的字節數。不要認爲它與CGImageGetWidth() * CGImageGetBitsPerPixel()/8相同;每行的字節數可能會更大。

請記住,任意CGImage背後的數據可能不是您所期望的格式。您不能假定所有圖像都是不帶填充的每像素32位ARGB。您應該使用CG函數來確定數據可能的格式,或者將圖像重新繪製到您期望的確切格式的位圖上下文中。後者通常要容易得多 - 讓CG爲你做轉換。 (你沒有顯示你傳遞給CGBitmapContextCreate的參數,你正在計算一個確切的bytesPerRow還是你傳入0?如果你傳入0,CG可以爲你添加填充,你可能會發現繪圖的上下文更快。)

+0

它確實看起來像是填充,CGImageGetBytesPerRow()比根據圖像的寬度計算大8個字節。是的,我知道CGImage可能有多種格式,但ARGB將被強制執行。並且繪製到位圖上下文中是它已經在做的事情,對於被重複調用的方法來說,這太低效了。 – Chris

+0

我剛剛花了整整一個早上試圖找出發生了什麼事。感謝這個,upvoted。 – Vik