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}];  

  

 



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

posted @ 2015-11-08 00:44  brave-sailor  阅读(274)  评论(0编辑  收藏  举报