当前位置:520彩票注册网址 > 520彩票登录 > 【520彩票登录】iOS中图片处理之马赛克算法

【520彩票登录】iOS中图片处理之马赛克算法

文章作者:520彩票登录 上传时间:2019-10-13

PS照片调色实例教程,photoshop给晚霞风景照调出火烧云效果,霞光图片制作思路比较简单就是给把图片调成金黄色,并增强层次感。不过处理过程会有点复杂,因为需要处理的细节较多,如天空部分的颜色比较浓烈,对比较强,地面及水面等颜色会淡一点,需要自己慢慢处理。

没有找到合适的图片,效果不是特别好,但是方法真心不错。本文中所有的图片均来自网络,如侵则删。

马赛克

马赛克在图片效果中应该是一种最常见的处理方式,日常生活中也几乎处处可见。前段时间项目中要实现图片马赛克处理,就研究了一下。其实,用苹果滤镜CIFilter就能非常便捷的实现加码,但使用的过程中我发现滤镜只能处理.png格式的图片,如果遇到.jpeg格式的图片就没有效果了,于是决定研究一下马赛克算法,发现可以通过操作图片的像素点来实现同样的效果。当然后者的实用性更加广泛,随便你什么类型的图片都可以。文章最后还有涂抹马赛克效果实现以及“复原”的Demo,希望多多star支持~

最终效果

做摄影的朋友在修片的时候经常会遇到环境光不相匹配的问题,调整环境光需要的步骤也很多,做的多了肯定会很熟练。可是不经常处理这样问题的同学们该如何解决呢?

操作像素点实现马赛克

我们都知道图片是一个一个像素点构成的,其实很早之前就有想过为什么所有的图片都是矩形的?有没有那种不规则的图片?计算机中的图片为什么都是矩形的?显示圆形也只能周围透明?,估计只有非科班出身的我才会问这种问题吧~简单来说,其实就是为了统一、更加方便的来处理图片,所以图片就是由像素矩阵构成的,平时我们看到的不规则的图片没有颜色的地方只是透明了而已。然后我就会想能不能局部的改变图片的颜色呢,比如把指定的不规则区域颜色改为别的颜色,以上都是自己以前胡乱想的,研究了之后发现其实都可以实现,我们可以通过操作图片的像素点来实现,直接上代码吧……

+ (NSArray *)getRGBsArrFromImage:(UIImage *)image{ //1.get the image into your data buffer CGImageRef imageRef = [image CGImage]; NSUInteger imageW = CGImageGetWidth; NSUInteger imageH = CGImageGetHeight; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); NSUInteger bytesPerPixel = 4;//一个像素四个分量,即ARGB NSUInteger bytesPerRow = bytesPerPixel * imageW; unsigned char *rawData = (unsigned char *)calloc(imageH*imageW*bytesPerPixel, sizeof(unsigned char)); NSUInteger bitsPerComponent = 8;//每个分量8个字节 /* 参数1:数据源 参数2:图片宽 参数3:图片高 参数4:表示每一个像素点,每一个分量大小 在我们图像学中,像素点:ARGB组成 每一个表示一个分量(例如,A,R,G,B) 在我们计算机图像学中每一个分量的大小是8个字节 参数5:每一行大小(其实图片是由像素数组组成的) 如何计算每一行的大小,所占用的内存 首先计算每一个像素点大小: ARGB是4个分量 = 每个分量8个字节 * 4 参数6:颜色空间 参数7:是否需要透明度 */ CGContextRef context = CGBitmapContextCreate(rawData, imageW, imageH, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGContextDrawImage(context, CGRectMake(0, 0, imageW, imageH), imageRef); //2.Now your rawData contains the image data int the RGBA8888 pixel format NSUInteger blackPixel = 0; NSMutableArray *pixelsArr = [NSMutableArray array]; for (int y = 0; y < imageH; y++) { for (int x = 0; x < imageW; x++) { NSUInteger byteIndex = bytesPerRow*y + bytesPerPixel*x; //rawData一维数组存储方式RGBARGBA NSUInteger red = rawData[byteIndex]; NSUInteger green = rawData[byteIndex+1]; NSUInteger blue = rawData[byteIndex+2]; NSUInteger alpha = rawData[byteIndex+3]; XPixelItem *pixelItem = [[XPixelItem alloc] init]; pixelItem.color = [UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:alpha/255.0]; pixelItem.location = CGPointMake; [pixelsArr addObject:pixelItem]; if (red+green+blue == 0 && (alpha/255.0 >= 0.5)){//计算黑色部分所占比例 blackPixel++; } } } NSLog(@"黑色所占的面积--%f,%lu",blackPixel*1.0/(imageW*imageH),(unsigned long)pixelsArr.count); imageRef = CGBitmapContextCreateImage; CGContextRelease; CGColorSpaceRelease(colorSpace); free; return pixelsArr;}

其中最主要的方法就是CGBitmapContextCreate,根据分配好的内存创建一个Bitmap的上下文,其中rawData中存放的就是我们所需要的像素点的集合。每个像素点由ARGB四个分量组成,我们看到的不规则图片没有颜色的地方也就是A为0的像素点,像素在数组中存放的是方式也是一个分量一个分量的存进去的,这样我们就可以通过修改数组中的数据来实现修改像素点。通过上述方法我们就可以把一个图片的局部不规则区域修改颜色,效果如下图:

520彩票登录 1修改图片像素.jpeg

520彩票登录 2

安利一个很不起眼但是很好用的功能:匹配颜色。

马赛克算法

马赛克核心算法的大概原理就是把某一个点的颜色赋值给它周围的指定区域,这个区域大小可以我们自己来定义。

unsigned char *pixels[4] = {0};if (i % sizeLevel == 0) { if (j % sizeLevel == 0) { memcpy(pixels, bitMapData+4*currentIndex, 4); }else{ //将上一个像素点的值赋给第二个 memcpy(bitMapData+4*currentIndex, pixels, 4); }}else{ preCurrentIndex = *imageW+j; memcpy(bitMapData+4*currentIndex, bitMapData+4*preCurrentIndex, 4);}

memcpy指的是c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。其实就是先把某个像素点的ARGB存到一个空数组pixels中,然后遍历像素点,如果是sizeLevel的整数倍就获取新的像素信息,不是的话就更换当前像素点的信息,这样就能实现sizeLevel大小区域的颜色是统一的了,也就是我们看到的马赛克中一个方块区域。下边这张图片描述的就很贴切

520彩票登录 3马赛克

其实这样做的话还会有问题,因为透明区域的像素点RGB信息也为0,0,0,跟黑色一样,这么一来后边再跟根据bitmap去绘制图片的时候,会把透明区域当成黑色来处理,所以我在中间进行了一下过滤

if (red+green+blue == 0 && (alpha/255.0 <= 0.5)) { rawData[currentIndex*4] = 255; rawData[currentIndex*4+1] = 255; rawData[currentIndex*4+2] = 255; rawData[currentIndex*4+3] = 0; continue;}

这种做法也不太严谨,但暂时想不到什么好的办法。

原图

1-  打开PS

涂抹实现马赛克

马赛克平时的运用更多的是跟用户交互息息相关的,比如手指涂抹区域打上马赛克,其实这种实现也挺简单。刚开始做的时候觉得还要去计算,但这样显然不易于实现。其实用两张图片就可以搞定了,一张是原图,用imageView来显示;一张是用马赛克处理过的图片,用CALayer来显示;马赛克处理过的图片覆盖在原图上边,然后利用layer的mask属性来控制CALayer指定区域的显示与否。

self.imageLayer = [CALayer layer];self.imageLayer.frame = self.bounds;[self.layer addSublayer:self.imageLayer]; self.shapeLayer = [CAShapeLayer layer];self.shapeLayer.frame = self.bounds;self.shapeLayer.lineCap = kCALineCapRound;self.shapeLayer.lineJoin = kCALineJoinRound;self.shapeLayer.lineWidth = 20;self.shapeLayer.strokeColor = [UIColor blueColor].CGColor;self.shapeLayer.fillColor = nil;//此处必须设为nil,否则后边添加addLine的时候会自动填充self.imageLayer.mask = self.shapeLayer;self.path = CGPathCreateMutable();

然后我们在touchMove方法中根据手指移动轨迹设置self.shapeLayer的path属性就可以实现想要的效果了。我把这些都封装在XScratchView类中了,使用的时候只需要初始化并给图片属性赋值,

XScratchView *scratchView = [[XScratchView alloc] initWithFrame:CGRectMake(0, 100, kScreenWidth, 300)];scratchView.surfaceImage = [UIImage imageNamed:@"smoke.jpeg"];scratchView.mosaicImage = [XRGBTool getMosaicImageWith:[UIImage imageNamed:@"smoke.jpeg"] level:0];

复原时只需要调用recover方法,

[_scratchView recover];

需要保存的时候只需要截取图片区域就可以获取加码后的图片了。效果如下

520彩票登录 4马赛克.gif

具体实现代码都在我的RGBTool这个Demo中,有什么问题还请大家多多指教,共同进步!

520彩票登录 5

目标图片:想要这张图片的颜色效果

待修图片:需要调整的图片

待修图片比较偏白,颜色较为素雅,缺少浪漫的气息;目标图片偏紫,紫色有浪漫的气息。所以,想要把目标图片中的色彩添加到待修图片中。

520彩票登录 6

目标图片

520彩票登录 7

待修图片

(敲黑板~~)注意看,这里是重点

一定是在两个psd文件中打开哈~

2-  调整

在待修图片中进行如下操作:图像-调整-匹配颜色-选择“源”-确定。

520彩票登录 8

操作步骤

520彩票登录 9

选择源

520彩票登录 10

注意源名称的对应

520彩票登录 11

效果

以上是图片颜色之间的匹配,细心的同学可以看出来,在匹配颜色的同时,环境光也发生了变化。为了更好的看出来效果,我还做了另外两张图。

这是处理前的效果:

520彩票登录 12

待修图片

520彩票登录 13

目标图片

待修图片亮度、饱和度都不够,可以利用目标图片的色彩进行匹配。

520彩票登录 14

直接匹配后的效果

很明显,直接匹配后有点过~所以可以进行适当的调整。

520彩票登录 15

手动调整

这是调整之后的效果图。

520彩票登录 16

效果图

最后,给大家来对比一下。

520彩票登录 17

调整前

520彩票登录 18

调整后

520彩票登录 19

调整前

520彩票登录 20

调整后

这种方法还可以用在哪里?

抠好的图放在另一个环境光的图片中

处理环境光的方法还有很多,欢迎大家提出,互相学习。


王旋子同学

本文由520彩票注册网址发布于520彩票登录,转载请注明出处:【520彩票登录】iOS中图片处理之马赛克算法

关键词: