图片滤镜基本原理和简单实现
2018-02-06 本文已影响77人
喵子G
一张图像就是像素点的集合,每一个像素都是一个独立明了的颜色。图像一般情况下都存储成数组,可以想象成二维数组。
bitmap(文件格式):
图片文件属性(width+height+格式)
图片内容( RGBA: 255 255 255 255 255 255 255 255 255 255 255 255…)
滤镜的原理就是取出每一个像素点,然后按照一个统一的规则修改它的RGBA四个颜色通道的值后,整张图片的风格就会改变。
UIImage *image = [UIImage imageNamed:@"testImage"];
CGImageRef imageRef = image.CGImage;
// 图片宽度
size_t width = CGImageGetWidth(imageRef);
// 图片高度
size_t height = CGImageGetHeight(imageRef);
// 每个颜色值存储的字节数
size_t bits = CGImageGetBitsPerComponent(imageRef);
// 每行的字节数
size_t bitsPerRow = CGImageGetBytesPerRow(imageRef);
// 透明度
int alphaInfo = CGImageGetAlphaInfo(imageRef);
// colorSpace RGBA AGBR RGB: 颜色空间
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
// bitmap data provider:bitmap数据提供器
CGDataProviderRef providerRef = CGImageGetDataProvider(imageRef);
// bitmap data:bitmap数据
CFDataRef dataRef = CGDataProviderCopyData(providerRef);
// bitmap数据长度
int length = (int)CFDataGetLength(dataRef);
// 颜色通道字符格式数组
Byte *pixelBuf = (UInt8 *)CFDataGetMutableBytePtr((CFMutableDataRef)dataRef);
// 遍历像素点,4个颜色通道一组组成一个像素点
for (int i = 0; i < length; i+=4) { // i+=4因为4个一组:RGBA
// 原始R序列号
int offsetR = i;
// 原始G序列号
int offsetG = i + 1;
// 原始B序列号
int offsetB = i + 2;
// 原始A序列号
int offsetA = i + 3;
// 原始R值
int red = pixelBuf[offsetR];
// 原始G值
int green = pixelBuf[offsetG];
// 原始B值
int blue = pixelBuf[offsetB];
// 原始A值
int alpha = pixelBuf[offsetA];
// 修改原始像素RGB数据
int gray = (red + green + blue) / 3;
// 用修改的RGB数据替换原数据
pixelBuf[offsetR] = gray;
pixelBuf[offsetG] = gray;
pixelBuf[offsetB] = gray;
pixelBuf[offsetA] = alpha;
}
// bitmap生成上下文
CGContextRef contextRef = CGBitmapContextCreate(pixelBuf, width, height, bits, bitsPerRow, colorSpace, alphaInfo);
// 通过上下文生成图片
CGImageRef backImageRef = CGBitmapContextCreateImage(contextRef);
UIImage *backImage = [UIImage imageWithCGImage:backImageRef scale:[UIScreen mainScreen].scale orientation:self.imageOrientation];
// 内存释放
CFRelease(dataRef);
CFRelease(contextRef);
CFRelease(backImageRef);