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}];
版权声明:本文为博主原创文章,未经博主允许不得转载。
iOS中的图像处理(一)——基础滤镜的更多相关文章
- iOS中的图像处理(二)——卷积运算
关于图像处理中的卷积运算,这里有两份简明扼要的介绍:文一,文二. 其中,可能的一种卷积运算代码如下: - (UIImage*)applyConvolution:(NSArray*)kernel { C ...
- iOS中的图像处理(三)——混合运算
有时候,单独对一张图像进行处理是很难或者根本达不到我们想要的效果的.一个好的滤镜效果的诞生,往往要经过很多复杂步骤.细致微调.图片应用效果观察以及很多图层叠加. 我在JSWidget上发现了一些常用混 ...
- iOS中数据库应用基础
iOS 数据库入门 一.数据库简介 1.什么是数据库? 数据库(Database) 是按照数据结构来组织,存储和管理数据的仓库 数据库可以分为2大种类 关系型数据库(主流) PC端 Oracle My ...
- iOS 中的 HotFix 方案总结详解
相信HotFix大家应该都很熟悉了,今天主要对于最近调研的一些方案做一些总结.iOS中的HotFix方案大致可以分为四种: WaxPatch(Alibaba) Dynamic Framework(Ap ...
- iOS中assign、copy 、retain等关键字的含义
iOS中assign.copy .retain等关键字的含义 转自:http://my.oschina.net/majiage/blog/267409 assign: 简单赋值,不更改索引计数cop ...
- iOS中几种常用的数据存储方式
自己稍微总结了一下下,方便大家查看 1.write直接写入文件的方法 永久保存在磁盘中,可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...
- Cordoval在iOS中的运用整理
一:关于Cordoval理论知识 1:PhoneGap是手机平台上流行的一款中间件.它构建在各种手机平台所提供的WebView(浏览器内核)组件的基础之上,使用javascript语言对应用开发者提供 ...
- iOS中集成ijkplayer视频直播框架
ijkplayer 是一款做视频直播的框架, 基于ffmpeg, 支持 Android 和 iOS, 网上也有很多集成说明, 但是个人觉得还是不够详细, 在这里详细的讲一下在 iOS 中如何集成ijk ...
- iOS开发UI篇—Button基础
iOS开发UI篇—Button基础 一.简单说明 一般情况下,点击某个控件后,会做出相应反应的都是按钮 按钮的功能比较多,既能显示文字,又能显示图片,还能随时调整内部图片和文字的位置 二.按钮的三种状 ...
随机推荐
- iOS 技能集结号
1. 获取磁盘总空间大小 2. 获取磁盘可用空间大小 3. 获取指定路径下某个文件的大小 4. 获取文件夹下所有文件的大小 5. 获取字符串(或汉字)首字母 6. 将字符串数组按照元素首字母顺序进行排 ...
- USACO Section 5.3 Big Barn(dp)
USACO前面好像有类似的题目..dp(i,j)=min(dp(i+1,j),dp(i+1,j+1),dp(i,j+1))+1 (坐标(i,j)处无tree;有tree自然dp(i,j)=0) .d ...
- Mysql开启远程
改表法: x:\>mysql -u root -pvmware mysql> use mysql;mysql> update User set Host = ‘%’ where Us ...
- [LeetCode]题解(python):085-Maximal Rectangle
题目来源: https://leetcode.com/problems/maximal-rectangle/ 题意分析: 给定一个二维的二进制矩阵,也就是只包括0 和 1的,找出只包括1的最大的矩阵的 ...
- shell学习-读取输入
功能:读取输入,打印:如果长度小于MINLEN,那么输出空格. #!/bin/bash # paragraph-space.sh # Insert a blank line between parag ...
- ASP.NET MVC进阶之路:深入理解依赖注入(DI)和控制反转(IOC)
0X1 什么是依赖注入 依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点.在程序运行过程中,客户 ...
- viewpager的layout_width="wrap_content"无效问题
在viewpager当中直接使用layout_width="wrap_content"是无效的,扩展了一下.解决这个问题. package com.soulagou.ui; imp ...
- 基于Visual C++2013拆解世界五百强面试题--题17-程序结果分析1
分析程序结果,分析过程我们就写在程序注释里面. 写出下列代码的输出内容 #include <stdio.h> int inc(int a) { return (++a); } int mu ...
- 字符串模式匹配KMP算法
一篇不错的博客:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP字符串模式匹配通俗点说就是一种在一个字符串中 ...
- Flex 按钮添加图标
第一种是在Flex应用中创建一个变量,利用[Bindable]和[Embed] ,在代码中以参数形式传入制定图标(icon)的路径,然后利用类似icon="{Icon}"的代码嵌入 ...