iOS中的图像处理(一)——基础滤镜
最近在稍微做一些整理,翻起这部分的代码,发现是两个多月前的了。
这里讨论的是基于RGBA模型下的图像处理,即将变换作用在每个像素上。
代码是以UIImage的category形式存在的:
[cpp]
typedef struct _singleRGBA
{
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
} RGBA;
@interface UIImage (ImageFilter)
首先,我们需要获得目标图像的位图信息;然后对每个像素进行变换;最后再生成图像。
[cpp]
- (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声明如下:
[cpp]
typedef void (*FilterFunction)(UInt8 *pixelBuf, UInt32 offset, void *context);
在此基础上,我们可以把每个变换操作独立出来,比如调整亮度、对比度、色调、透明度等:
[cpp]
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宏如下:
[cpp]
#define SAFECOLOR(color) MIN(255,MAX(0,color))
最后,拿一张帅气的Andy照片来实践下,希望没有侵犯到肖像权。
原图如下:
通过以下四种变换,可以分别得到四张处理过的图片:
[cpp]
return [originImage changeOpacityByFactor:0.5];
[cpp]
return [originImage changeBrightnessByFactor:1.2];
[cpp]
return [originImage changeSaturationByFactor:2.0];
[cpp]
return [originImage tintWithMaxRGBA:(RGBA){190, 190, 230} minRGBA:(RGBA){50, 35, 10}];
相关新闻>>
- 关于cocos2dx lua中的clone函数的源码解读
- cocos2d-x在iOS/Android双平台上嵌入WebView
- [cocos2dx 3.0 + ios]如何编写iAd的plugin
- cocos2d-x 3.0rc 较于2.2v 诸多变化中的一些小点
- iPhone开发中Cocoa中的CGRectMake具体用法
- [cocos2d-x IOS游戏开发]2014年开发及学习计划:cocos2d-x视频专
- cocos2d-x中的CCArray
- cocos iOS 编译
- Cocos2dx中的引用计数和自动回收池
- Cocos2dx 中的CCCallFunc,CCCallFuncN,CCCallFuncND,CCCallFuncO
- 发表评论
-
- 最新评论 更多>>