我們都知道圖片是由很多個(gè)像素點(diǎn)組成的,而iOS中的圖片通常又由UIImage承載。
如果我們想查看一張圖片的每個(gè)像素點(diǎn)應(yīng)該怎么做呢?或者如果我們有一堆像素點(diǎn)的數(shù)據(jù),要怎么才能轉(zhuǎn)換成UIImage呢?再或者我們想對(duì)一些圖片進(jìn)行像素點(diǎn)的處理應(yīng)該怎么做呢?
1.第一個(gè)問(wèn)題,把UIImage轉(zhuǎn)換成像素點(diǎn)數(shù)據(jù)
UIImage轉(zhuǎn)換成像素點(diǎn)需要用到一個(gè)Quartz的接口CGBitmapContextCreate。
聽(tīng)這個(gè)名字就知道這是用來(lái)創(chuàng)建位圖上下文的。
CG_EXTERN CGContextRef CGBitmapContextCreate(
void *data, //如果data非空,指向一個(gè)內(nèi)存區(qū)域,大小至少bytesPerRow *height的字節(jié)。如果data為空,data上下文自動(dòng)分配和釋放收回。
size_t width, //像素寬
size_t height, //像素高
size_t bitsPerComponent, //位的數(shù)量為每個(gè)組件的指定一個(gè)像素
size_t bytesPerRow, //每一行的位圖的字節(jié),至少要寬*每個(gè)像素的字節(jié)
CGColorSpaceRef space, //指定一個(gè)顏色空間
CGBitmapInfo bitmapInfo //指定位圖是否應(yīng)該包含一個(gè)alpha通道和它是如何產(chǎn)生的,以及是否組件是浮點(diǎn)或整數(shù)
)
所以只要根據(jù)CGBitmapContextCreate需要的參數(shù)就能得出image的像素點(diǎn)數(shù)據(jù),方法如下:
CGImageRef inputCGImage = [image CGImage];
NSUInteger width = CGImageGetWidth(inputCGImage);
NSUInteger height = CGImageGetHeight(inputCGImage);
CGRect rect = CGRectMake(0, 0, width, height);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel *width;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); //色彩空間
unsigned char * imagedata=malloc(width*height*bytesPerPixel); //分配內(nèi)存空間
CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); //創(chuàng)建位圖上下文
CGContextDrawImage(context, rect, inputCGImage);
CGColorSpaceRelease(colorSpace); //內(nèi)存釋放
CGContextRelease(context);
這樣imagedata就是我們需要的像素點(diǎn)數(shù)據(jù)了。
2.第二個(gè)問(wèn)題,怎么把像素點(diǎn)轉(zhuǎn)換成UIImage。
這次我們同樣要用到Quartz的接口:CGDataProviderCreateWithData
根據(jù)接口名字我們能知道這是一個(gè)創(chuàng)建dataprovider的接口。
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, imagedata, bytesPerRow * height, NULL); //創(chuàng)建provider
CGImageRef imageRef = CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace,
kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,
NULL, true, kCGRenderingIntentDefault); //由provider創(chuàng)建CGImage
CGDataProviderRelease(dataProvider);
UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef]; //由CGImage創(chuàng)建UIImage
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
3.處理像素點(diǎn)。
有了方法1,我們就能拿到像素點(diǎn)了。我們可以按照喜好處理像素點(diǎn)。然后通過(guò)方法2把我們處理后的像素點(diǎn)轉(zhuǎn)換成UIImage。
這里,舉一個(gè)把像素點(diǎn)上下翻轉(zhuǎn)的例子:
把方法1中的imageData轉(zhuǎn)成Data方便我們傳值:
size_t bufferLength = bytesPerRow * height;
NSData* data = [NSData dataWithBytes:imageData length:bufferLength];
然后通過(guò)下面這個(gè)方法就可以翻轉(zhuǎn)了。
+ (NSData*)downMirrorImageData:(NSData*)data width:(NSInteger)width height:(NSInteger)height bytesPerPixel:(NSInteger)bytesPerPixel
{
if (!data || data.length == 0) return nil;
unsigned char* buffer = (unsigned char*)[data bytes];
for (NSInteger h = 0; h < height/2; h++) {
for (NSInteger w = 0; w < width*bytesPerPixel; w++) {
NSInteger targetH = height - 1 - h;
NSInteger sourceIndex = w + width*bytesPerPixel*h;
NSInteger targetIndex = w + width*bytesPerPixel*targetH;
buffer[sourceIndex] = buffer[sourceIndex]+buffer[targetIndex];
buffer[targetIndex] = buffer[sourceIndex] - buffer[targetIndex];
buffer[sourceIndex] = buffer[sourceIndex] - buffer[targetIndex];
}
}
return [NSData dataWithBytes:buffer length:width*height*bytesPerPixel];
}