iOS中的图像处理(一)——基础滤镜

简介:

最近在稍微做一些整理,翻起这部分的代码,发现是两个多月前的了。

这里讨论的是基于RGBA模型下的图像处理,即将变换作用在每个像素上。

代码是以UIImage的category形式存在的:

typedef struct _singleRGBA
{
    unsigned char red;
    unsigned char green;
    unsigned char blue;
    unsigned char alpha;
} RGBA;

@interface UIImage (ImageFilter)


首先,我们需要获得目标图像的位图信息;然后对每个像素进行变换;最后再生成图像。

- (UIImage*)applyFilter:(FilterFunction)filter context:(void*)context
{
	CGImageRef inImage = self.CGImage;
	CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
	UInt8 *m_PixelBuf = (UInt8 *)CFDataGetBytePtr(m_DataRef);
	
	int length = CFDataGetLength(m_DataRef);
	
	for (int i=0; i<length; i+=4) {
		filter(m_PixelBuf, i, context);
	}
	
	CGContextRef ctx = CGBitmapContextCreate(m_PixelBuf,
											 CGImageGetWidth(inImage),
											 CGImageGetHeight(inImage),
											 CGImageGetBitsPerComponent(inImage),
											 CGImageGetBytesPerRow(inImage),
											 CGImageGetColorSpace(inImage),
											 CGImageGetBitmapInfo(inImage)
											 );
	
	CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
	CGContextRelease(ctx);
	UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
	CGImageRelease(imageRef);
	CFRelease(m_DataRef);
    
	return finalImage;
}


其中,FilterFunction声明如下:

typedef void (*FilterFunction)(UInt8 *pixelBuf, UInt32 offset, void *context);

在此基础上,我们可以把每个变换操作独立出来,比如调整亮度、对比度、色调、透明度等:

void filterOpacity(UInt8 *pixelBuf, UInt32 offset, void *context)
{
	double val = *((double*)context);
	
	int a = offset+3;
	
	int alpha = pixelBuf[a];
	
	pixelBuf[a] = SAFECOLOR(alpha * val);
}

void filterBrightness(UInt8 *pixelBuf, UInt32 offset, void *context)
{
	double t = *((double*)context);
	
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
	
	pixelBuf[r] = SAFECOLOR(red * t);
	pixelBuf[g] = SAFECOLOR(green * t);
	pixelBuf[b] = SAFECOLOR(blue * t);
}

void filterSaturation(UInt8 *pixelBuf, UInt32 offset, void *context)
{
	double t = *((double*)context); // t (- [0, 2]
	
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
    
    red = red * (0.3086 * (1-t) + t) + green * (0.6094 * (1-t)) + blue * (0.0820 * (1-t));
    green = red * (0.3086 * (1-t)) + green * ((0.6094 * (1-t)) + t) + blue * (0.0820 * (1-t));
    blue = red * (0.3086 * (1-t)) + green * (0.6094 * (1-t)) + blue * ((0.0820 * (1-t)) + t);
	
	pixelBuf[r] = SAFECOLOR(red);
	pixelBuf[g] = SAFECOLOR(green);
	pixelBuf[b] = SAFECOLOR(blue);
}

void filterContrast(UInt8 *pixelBuf, UInt32 offset, void *context)
{
    double t = *((double*)context); // t (- [0, 10]
	
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
    
    red = red * t + 128 * (1-t);
    green = green * t + 128 * (1-t);
    blue = blue * t + 128 * (1-t);
	
	pixelBuf[r] = SAFECOLOR(red);
	pixelBuf[g] = SAFECOLOR(green);
	pixelBuf[b] = SAFECOLOR(blue);
}

void filterPosterize(UInt8 *pixelBuf, UInt32 offset, void *context)
{
    double levels = *((double*)context);
	if (levels == 0) levels = 1; // avoid divide by zero
	int step = 255 / levels;
	
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
	
	pixelBuf[r] = SAFECOLOR((red / step) * step);
	pixelBuf[g] = SAFECOLOR((green / step) * step);
	pixelBuf[b] = SAFECOLOR((blue / step) * step);
}

void filterDesaturate(UInt8 *pixelBuf, UInt32 offset, void *context)
{
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
    
    red = red * 0.3086 + green * 0.6094 + blue * 0.0820;
    green = red * 0.3086 + green * 0.6094 + blue * 0.0820;
    blue = red * 0.3086 + green * 0.6094 + blue * 0.0820;
	
	pixelBuf[r] = SAFECOLOR(red);
	pixelBuf[g] = SAFECOLOR(green);
	pixelBuf[b] = SAFECOLOR(blue);
}

void filterInvert(UInt8 *pixelBuf, UInt32 offset, void *context)
{
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
	
	pixelBuf[r] = SAFECOLOR(255-red);
	pixelBuf[g] = SAFECOLOR(255-green);
	pixelBuf[b] = SAFECOLOR(255-blue);
}

void filterTint(UInt8 *pixelBuf, UInt32 offset, void *context)
{
    RGBA *rgbaArray = (RGBA*)context;
    RGBA maxRGBA = rgbaArray[0];
    RGBA minRGBA = rgbaArray[1];
    
	int r = offset;
	int g = offset+1;
	int b = offset+2;
	
	int red = pixelBuf[r];
	int green = pixelBuf[g];
	int blue = pixelBuf[b];
	
	pixelBuf[r] = SAFECOLOR((red - minRGBA.red) * (255.0 / (maxRGBA.red - minRGBA.red)));
	pixelBuf[g] = SAFECOLOR((green - minRGBA.green) * (255.0 / (maxRGBA.green - minRGBA.green)));
	pixelBuf[b] = SAFECOLOR((blue - minRGBA.blue) * (255.0 / (maxRGBA.blue - minRGBA.blue)));
}


其中SAFECOLOR宏如下:

#define SAFECOLOR(color) MIN(255,MAX(0,color))

最后,拿一张帅气的Andy照片来实践下,希望没有侵犯到肖像权。
原图如下:


通过以下四种变换,可以分别得到四张处理过的图片:

return [originImage changeOpacityByFactor:0.5];

return [originImage changeBrightnessByFactor:1.2];

return [originImage changeSaturationByFactor:2.0];

return [originImage tintWithMaxRGBA:(RGBA){190, 190, 230} minRGBA:(RGBA){50, 35, 10}];

   

 



目录
相关文章
|
并行计算 算法 Swift
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
|
前端开发 API 开发工具
基础篇必看,史上最全的iOS开发教程集锦,没有之一
基础篇必看,史上最全的iOS开发教程集锦,没有之一
|
程序员 API iOS开发
iOS开发:个人对于textView基础用法的总结(其一)
从事了这么久ios开发,对于textView的使用并不陌生,它和textfield有相似的地方,也有不同的地方,这里只对textView的一些基础用法进行描述,textfield不在这里描述。
300 0
|
算法 iOS开发 计算机视觉
iOS 图像处理 + 人脸检测相关示例 🤖
Faceu脸萌一定是有一套自己的核心算法,所以它会说“有人模仿我的脸...” 最近在研究一些图像处理的技术,其中最常见的应用就要数 “Faceu 脸萌” 了,为了展示更清晰,我选择拆分功能的方式来实现 Demo。
159 0
iOS 图像处理 + 人脸检测相关示例 🤖
|
缓存 编译器 iOS开发
iOS - Runtime基础(下)
Runtime合集 iOS - isa、superclass指针,元类superclass指向基类本身
iOS - Runtime基础(下)
|
存储 缓存 API
iOS - Runtime基础(上)
Runtime合集 iOS - isa、superclass指针,元类superclass指向基类本身
iOS - Runtime基础(上)
|
小程序 前端开发 安全
《iOS逆向》小程序的基础配置:文章的特色图片(缩略图/封面)模糊的解决方案
《iOS逆向》小程序的基础配置:文章的特色图片(缩略图/封面)模糊的解决方案
221 0
《iOS逆向》小程序的基础配置:文章的特色图片(缩略图/封面)模糊的解决方案
|
小程序 前端开发 安全
《iOS逆向》小程序的基础配置
《iOS逆向》小程序的基础配置
91 0
《iOS逆向》小程序的基础配置
|
JavaScript 前端开发 iOS开发
iOS中动态更新补丁策略JSPatch运用基础二
iOS中动态更新补丁策略JSPatch运用基础二
141 0
|
JavaScript 前端开发 iOS开发
iOS中动态更新补丁策略JSPatch运用基础一
iOS中动态更新补丁策略JSPatch运用基础一
195 0