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

来源:未知 责任编辑:智问网络 发表时间:2013-09-22 21:28 点击:

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

这里讨论的是基于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}]; 

 
\ \ 

 

\ \


 

 

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • cocos2d-x学习笔记(19)--label 、label atlas
    • cocos2d-x学习笔记(23)--地图的使用3--CCTMXLayer
    • Cocos2d-x学习(一):HelloWorld
    • cocos2dx在xcode下开发,编译到android上(2)
    • cocos2d 设置屏幕默认方向
    • Cocos2d-x 2.0 之 Actions “三板斧” 之一
    • cocos2d-x学习笔记(22)--地图的使用2(TMX) --Z-Order、AnchorPoi
    • cocos2d-x学习笔记(18)--游戏打包(windows平台)
    • cocos2d-x学习笔记(16)--spritesheet(精灵表单)
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1