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


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

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

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

    1. typedef struct _singleRGBA  
    2. {  
    3.     unsigned char red;  
    4.     unsigned char green;  
    5.     unsigned char blue;  
    6.     unsigned char alpha;  
    7. } RGBA;  
    8.   
    9. @interface UIImage (ImageFilter)  


    首先,我们需要获得目标图像的位图信息;然后对每个像素进行变换;最后再生成图像。
    1. - (UIImage*)applyFilter:(FilterFunction)filter context:(void*)context  
    2. {  
    3.     CGImageRef inImage = self.CGImage;  
    4.     CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));  
    5.     UInt8 *m_PixelBuf = (UInt8 *)CFDataGetBytePtr(m_DataRef);  
    6.       
    7.     int length = CFDataGetLength(m_DataRef);  
    8.       
    9.     for (int i=0; i<length; i+=4) {  
    10.         filter(m_PixelBuf, i, context);  
    11.     }  
    12.       
    13.     CGContextRef ctx = CGBitmapContextCreate(m_PixelBuf,  
    14.                                              CGImageGetWidth(inImage),  
    15.                                              CGImageGetHeight(inImage),  
    16.                                              CGImageGetBitsPerComponent(inImage),  
    17.                                              CGImageGetBytesPerRow(inImage),  
    18.                                              CGImageGetColorSpace(inImage),  
    19.                                              CGImageGetBitmapInfo(inImage)  
    20.                                              );  
    21.       
    22.     CGImageRef imageRef = CGBitmapContextCreateImage(ctx);  
    23.     CGContextRelease(ctx);  
    24.     UIImage *finalImage = [UIImage imageWithCGImage:imageRef];  
    25.     CGImageRelease(imageRef);  
    26.     CFRelease(m_DataRef);  
    27.       
    28.     return finalImage;  
    29. }  


    其中,FilterFunction声明如下:
    1. typedef void (*FilterFunction)(UInt8 *pixelBuf, UInt32 offset, void *context);  

    在此基础上,我们可以把每个变换操作独立出来,比如调整亮度、对比度、色调、透明度等:
    1. void filterOpacity(UInt8 *pixelBuf, UInt32 offset, void *context)  
    2. {  
    3.     double val = *((double*)context);  
    4.       
    5.     int a = offset+3;  
    6.       
    7.     int alpha = pixelBuf[a];  
    8.       
    9.     pixelBuf[a] = SAFECOLOR(alpha * val);  
    10. }  
    11.   
    12. void filterBrightness(UInt8 *pixelBuf, UInt32 offset, void *context)  
    13. {  
    14.     double t = *((double*)context);  
    15.       
    16.     int r = offset;  
    17.     int g = offset+1;  
    18.     int b = offset+2;  
    19.       
    20.     int red = pixelBuf[r];  
    21.     int green = pixelBuf[g];  
    22.     int blue = pixelBuf[b];  
    23.       
    24.     pixelBuf[r] = SAFECOLOR(red * t);  
    25.     pixelBuf[g] = SAFECOLOR(green * t);  
    26.     pixelBuf[b] = SAFECOLOR(blue * t);  
    27. }  
    28.   
    29. void filterSaturation(UInt8 *pixelBuf, UInt32 offset, void *context)  
    30. {  
    31.     double t = *((double*)context); // t (- [0, 2]  
    32.       
    33.     int r = offset;  
    34.     int g = offset+1;  
    35.     int b = offset+2;  
    36.       
    37.     int red = pixelBuf[r];  
    38.     int green = pixelBuf[g];  
    39.     int blue = pixelBuf[b];  
    40.       
    41.     red = red * (0.3086 * (1-t) + t) + green * (0.6094 * (1-t)) + blue * (0.0820 * (1-t));  
    42.     green = red * (0.3086 * (1-t)) + green * ((0.6094 * (1-t)) + t) + blue * (0.0820 * (1-t));  
    43.     blue = red * (0.3086 * (1-t)) + green * (0.6094 * (1-t)) + blue * ((0.0820 * (1-t)) + t);  
    44.       
    45.     pixelBuf[r] = SAFECOLOR(red);  
    46.     pixelBuf[g] = SAFECOLOR(green);  
    47.     pixelBuf[b] = SAFECOLOR(blue);  
    48. }  
    49.   
    50. void filterContrast(UInt8 *pixelBuf, UInt32 offset, void *context)  
    51. {  
    52.     double t = *((double*)context); // t (- [0, 10]  
    53.       
    54.     int r = offset;  
    55.     int g = offset+1;  
    56.     int b = offset+2;  
    57.       
    58.     int red = pixelBuf[r];  
    59.     int green = pixelBuf[g];  
    60.     int blue = pixelBuf[b];  
    61.       
    62.     red = red * t + 128 * (1-t);  
    63.     green = green * t + 128 * (1-t);  
    64.     blue = blue * t + 128 * (1-t);  
    65.       
    66.     pixelBuf[r] = SAFECOLOR(red);  
    67.     pixelBuf[g] = SAFECOLOR(green);  
    68.     pixelBuf[b] = SAFECOLOR(blue);  
    69. }  
    70.   
    71. void filterPosterize(UInt8 *pixelBuf, UInt32 offset, void *context)  
    72. {  
    73.     double levels = *((double*)context);  
    74.     if (levels == 0) levels = 1; // avoid divide by zero  
    75.     int step = 255 / levels;  
    76.       
    77.     int r = offset;  
    78.     int g = offset+1;  
    79.     int b = offset+2;  
    80.       
    81.     int red = pixelBuf[r];  
    82.     int green = pixelBuf[g];  
    83.     int blue = pixelBuf[b];  
    84.       
    85.     pixelBuf[r] = SAFECOLOR((red / step) * step);  
    86.     pixelBuf[g] = SAFECOLOR((green / step) * step);  
    87.     pixelBuf[b] = SAFECOLOR((blue / step) * step);  
    88. }  
    89.   
    90. void filterDesaturate(UInt8 *pixelBuf, UInt32 offset, void *context)  
    91. {  
    92.     int r = offset;  
    93.     int g = offset+1;  
    94.     int b = offset+2;  
    95.       
    96.     int red = pixelBuf[r];  
    97.     int green = pixelBuf[g];  
    98.     int blue = pixelBuf[b];  
    99.       
    100.     red = red * 0.3086 + green * 0.6094 + blue * 0.0820;  
    101.     green = red * 0.3086 + green * 0.6094 + blue * 0.0820;  
    102.     blue = red * 0.3086 + green * 0.6094 + blue * 0.0820;  
    103.       
    104.     pixelBuf[r] = SAFECOLOR(red);  
    105.     pixelBuf[g] = SAFECOLOR(green);  
    106.     pixelBuf[b] = SAFECOLOR(blue);  
    107. }  
    108.   
    109. void filterInvert(UInt8 *pixelBuf, UInt32 offset, void *context)  
    110. {  
    111.     int r = offset;  
    112.     int g = offset+1;  
    113.     int b = offset+2;  
    114.       
    115.     int red = pixelBuf[r];  
    116.     int green = pixelBuf[g];  
    117.     int blue = pixelBuf[b];  
    118.       
    119.     pixelBuf[r] = SAFECOLOR(255-red);  
    120.     pixelBuf[g] = SAFECOLOR(255-green);  
    121.     pixelBuf[b] = SAFECOLOR(255-blue);  
    122. }  
    123.   
    124. void filterTint(UInt8 *pixelBuf, UInt32 offset, void *context)  
    125. {  
    126.     RGBA *rgbaArray = (RGBA*)context;  
    127.     RGBA maxRGBA = rgbaArray[0];  
    128.     RGBA minRGBA = rgbaArray[1];  
    129.       
    130.     int r = offset;  
    131.     int g = offset+1;  
    132.     int b = offset+2;  
    133.       
    134.     int red = pixelBuf[r];  
    135.     int green = pixelBuf[g];  
    136.     int blue = pixelBuf[b];  
    137.       
    138.     pixelBuf[r] = SAFECOLOR((red - minRGBA.red) * (255.0 / (maxRGBA.red - minRGBA.red)));  
    139.     pixelBuf[g] = SAFECOLOR((green - minRGBA.green) * (255.0 / (maxRGBA.green - minRGBA.green)));  
    140.     pixelBuf[b] = SAFECOLOR((blue - minRGBA.blue) * (255.0 / (maxRGBA.blue - minRGBA.blue)));  
    141. }  


    其中SAFECOLOR宏如下:

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

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


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

    1. return [originImage changeOpacityByFactor:0.5];  

    1. return [originImage changeBrightnessByFactor:1.2];  

    1. return [originImage changeSaturationByFactor:2.0];  

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

      

     



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Web存储
    JavaScript模块化
    jQuery挖源码——事件绑定
    观察者模式——JavaScript
    Node.js之网络小爬虫
    ECMAScript的严格模式
    JavaScript和jQuery的事件
    认识Ajax
    Redis之intset数据结构
    Redis之Hash数据结构
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4946671.html
Copyright © 2020-2023  润新知