AVPlayer和GPUImagede学习iOS开发技术分享

图片滤镜基本原理和简单实现

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);
上一篇下一篇

猜你喜欢

热点阅读