一 基本概念
1.图形图像其实就是像素的集合,2D图像通过坐标系展现出来
2.像素颜色具有好多种表现方式,又称为颜色空间,一般有32位RGBA 、24位 RGB 、 灰阶 、HSV、YUV等颜色空间。R、G等成为颜色通道。
3.像素组合成图形的坐标系,苹果中不同地方可能不同。比如UIImage,UIView使用的是左上角坐标系,Core Image ,Core Graphics 使用的是左下角坐标系,所以通常他两个之间生成的图片相互使用各时候,都是倒着的,需要处理一下。
4.图形压缩 GPU绘制图像时,会将图像尺寸进行压缩。
二代码处理
1.打印图像
- CGImageRef inputCGImage = [image CGImage];
- NSUInteger width = CGImageGetWidth(inputCGImage);
- NSUInteger height = CGImageGetHeight(inputCGImage);
将普通图片对象转化为CGImageRef格式的对象,并得到宽高
- // 2.
- NSUInteger bytesPerPixel = 4;
- NSUInteger bytesPerRow = bytesPerPixel * width;
- NSUInteger bitsPerComponent = 8;
- UInt32 * pixels;
- pixels = (UInt32 *) calloc(height * width, sizeof(UInt32));
使用32位RGBA颜色空间,需要定义一些参数,bytesPerPixel:每像素大小有几个字节,bytesPerRow:每行有多少字节,bitsPerComponent:每个颜色通道有多大。
然后calloc创建一个数组
- // 3.
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- CGContextRef context = CGBitmapContextCreate(pixels, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
创建一个颜色空间colorSpace和一个容器context,将像素指针参数传递到容器中缓存进行存储。
- // 4.
- CGContextDrawImage(context, CGRectMake(0, 0, width, height), inputCGImage);
- CGImageRef outPutImgRef = CGBitmapContextCreateImage(context);
- UIImage *outPutImage = [UIImage imageWithCGImage:outPutImgRef];
将绘制中的图形展示在屏幕上,像素的填充格式是在创建context的时候指定的。
- // 5. Cleanup
- CGColorSpaceRelease(colorSpace);
- CGContextRelease(context);
清除颜色空间和容器。
- #define Mask8(x) ( (x) & 0xFF )
- #define R(x) ( Mask8(x) )
- #define G(x) ( Mask8(x >> 8 ) )
- #define B(x) ( Mask8(x >> 16) )
- NSLog(@"Brightness of image:");
- // 2.
- UInt32 * currentPixel = pixels;
- for (NSUInteger j = 0; j < height; j++) {
- for (NSUInteger i = 0; i < width; i++) {
- // 3.
- UInt32 color = *currentPixel;
- printf("%3.0f ", (R(color)+G(color)+B(color))/3.0);
- // 4.
- currentPixel++;
- }
- printf("\n");
- }
currentPixel是一个指向UInt32的指针,每次+1,都会向前移动4字节,从而指向下一个像素的值。
2.修改图像
依然是遍历图像然后修改,其实我们上面说过,将图像存储在一个数组中后,我们可以通过一个数组去存储它,然后可以遍历这个数组,修改其中的像素值,假如是混合图像的话,还需要修改他们的透明度。
一般混合图像的公式:
NewColor = TopColor * TopColor.Alpha + BottomColor * (1 - TopColor.Alpha)
即
newR = oldR1 * (1-alpha2) + oldR2 * oldAlpha;
拿到新的color后赋值给指针指向的内存就可以了,color = R + G <<8 + B<<16 + A<<24;
以上算是图像较为底层的处理方式了