訪問像素級數據的過程比您提出的問題稍微複雜一些,因爲正如Martin指出的,JPEG可以是壓縮圖像格式。 Apple討論了在Technical Q&A QA1509中獲取像素數據的批准技術。
底線,以獲取無壓縮的像素數據的UIImage
,你會:
獲取CGImage
爲UIImage
。
通過CGImageGetDataProvider
獲取該數據提供者CGImageRef
。
通過CGDataProviderCopyData
獲取與該數據提供者關聯的二進制數據。
提取一些關於圖像的信息,讓你知道如何解釋該緩衝區。
這樣:
UIImage *image = ...
CGImageRef imageRef = image.CGImage; // get the CGImageRef
NSAssert(imageRef, @"Unable to get CGImageRef");
CGDataProviderRef provider = CGImageGetDataProvider(imageRef); // get the data provider
NSAssert(provider, @"Unable to get provider");
NSData *data = CFBridgingRelease(CGDataProviderCopyData(provider)); // get copy of the data
NSAssert(data, @"Unable to copy image data");
NSInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef); // some other interesting details about image
NSInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
NSInteger bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
NSInteger bytesPerRow = CGImageGetBytesPerRow(imageRef);
NSInteger width = CGImageGetWidth(imageRef);
NSInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorspace = CGImageGetColorSpace(imageRef);
考慮到要操縱這一點,你可能需要一些可變像素緩衝區。最簡單的方法是製作該對象的mutableCopy
並在那裏對其進行操作,但在這些情況下,我傾向於回退到C,創建void *outputBuffer
,其中我複製原始像素並使用傳統C數組技術進行操作。
要創建緩衝區:
void *outputBuffer = malloc(width * height * bitsPerPixel/8);
NSAssert(outputBuffer, @"Unable to allocate buffer");
有關如何操作它精確的細節,你必須看看bitmapInfo
(它會告訴你它是否RGBA或ARGB;無論是浮點或整數)和bitsPerComponent
(它會告訴你它是8位還是16位,每個組件等)。例如,非常常見的JPEG格式是每個分量8位,四個分量RGBA(即按順序,紅色,綠色,藍色和阿爾法)。但你真的需要檢查我們從CGImageRef
中提取的各種屬性以確保。有關更多信息,請參閱Quartz 2D Programming Guide - Bitmap Images and Image Masks中的討論。我個人發現「圖11-2」特別具有啓發性。
下一個邏輯問題是當你完成操縱像素數據時,如何爲此創建一個UIImage
。簡而言之,你可以改變上述過程,例如創建一個數據提供者,創造CGImageRef
,然後創建一個UIImage
:
CGDataProviderRef outputProvider = CGDataProviderCreateWithData(NULL, outputBuffer, sizeof(outputBuffer), releaseData);
CGImageRef outputImageRef = CGImageCreate(width,
height,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorspace,
bitmapInfo,
outputProvider,
NULL,
NO,
kCGRenderingIntentDefault);
UIImage *outputImage = [UIImage imageWithCGImage:outputImageRef];
CGImageRelease(outputImageRef);
CGDataProviderRelease(outputProvider);
哪裏releaseData
是簡單地調用free
與數據提供相關的像素緩衝器中的C函數:
void releaseData(void *info, const void *data, size_t size)
{
free((void *)data);
}
您閱讀JPEG壓縮圖像。要操縱像素,你必須首先將文件解壓縮成位圖... –
我用bmp文件做了它,當我改變一些像素,然後我收到一個(int)0的數組。當我把它放在UIImage數據中時,調試告訴我UIImage是零。 ??? – user2032083