我们都知道图片是由很多个像素点组成的,而iOS中的图片通常又由UIImage承载。
如果我们想查看一张图片的每个像素点应该怎么做呢?或者如果我们有一堆像素点的数据,要怎么才能转换成UIImage呢?再或者我们想对一些图片进行像素点的处理应该怎么做呢?
1.第一个问题,把UIImage转换成像素点数据
UIImage转换成像素点需要用到一个Quartz的接口CGBitmapContextCreate。
听这个名字就知道这是用来创建位图上下文的。
CG_EXTERN CGContextRef CGBitmapContextCreate(
void *data, //如果data非空,指向一个内存区域,大小至少bytesPerRow *height的字节。如果data为空,data上下文自动分配和释放收回。
size_t width, //像素宽
size_t height, //像素高
size_t bitsPerComponent, //位的数量为每个组件的指定一个像素
size_t bytesPerRow, //每一行的位图的字节,至少要宽*每个像素的字节
CGColorSpaceRef space, //指定一个颜色空间
CGBitmapInfo bitmapInfo //指定位图是否应该包含一个alpha通道和它是如何产生的,以及是否组件是浮点或整数
)
所以只要根据CGBitmapContextCreate需要的参数就能得出image的像素点数据,方法如下:
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); //分配内存空间
CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); //创建位图上下文
CGContextDrawImage(context, rect, inputCGImage);
CGColorSpaceRelease(colorSpace); //内存释放
CGContextRelease(context);
这样imagedata就是我们需要的像素点数据了。
2.第二个问题,怎么把像素点转换成UIImage。
这次我们同样要用到Quartz的接口:CGDataProviderCreateWithData
根据接口名字我们能知道这是一个创建dataprovider的接口。
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, imagedata, bytesPerRow * height, NULL); //创建provider
CGImageRef imageRef = CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace,
kCGImageAlphaLast | kCGBitmapByteOrder32Little, dataProvider,
NULL, true, kCGRenderingIntentDefault); //由provider创建CGImage
CGDataProviderRelease(dataProvider);
UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef]; //由CGImage创建UIImage
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
3.处理像素点。
有了方法1,我们就能拿到像素点了。我们可以按照喜好处理像素点。然后通过方法2把我们处理后的像素点转换成UIImage。
这里,举一个把像素点上下翻转的例子:
把方法1中的imageData转成Data方便我们传值:
size_t bufferLength = bytesPerRow * height;
NSData* data = [NSData dataWithBytes:imageData length:bufferLength];
然后通过下面这个方法就可以翻转了。
+ (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];
}