iOS中的图像处理(三)——混合运算

有时候,单独对一张图像进行处理是很难或者根本达不到我们想要的效果的。一个好的滤镜效果的诞生,往往要经过很多复杂步骤、细致微调、图片应用效果观察以及很多图层叠加。

我在JSWidget上发现了一些常用混合算法,对应着一些常用混合模式,通过这些blend modes,我们可以指定两张图像如何混合。

不过在此之前,我们需要纯颜色图像和渐变图像来做辅助:

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size
{
    // http://stackoverflow.com/questions/1213790/how-to-get-a-color-image-in-iphone-sdk

    //Create a context of the appropriate size
    UIGraphicsBeginImageContext(size);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();

    //Build a rect of appropriate size at origin 0,0
    CGRect fillRect = CGRectMake(0, 0, size.width, size.height);

    //Set the fill color
    CGContextSetFillColorWithColor(currentContext, color.CGColor);

    //Fill the color
    CGContextFillRect(currentContext, fillRect);

    //Snap the picture and close the context
    UIImage *colorImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return colorImage;
}

+ (UIImage *)imageWithGradient:(UIImage *)image startColor:(UIColor *)startColor endColor:(UIColor *)endColor
{
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
    CGContextDrawImage(context, rect, image.CGImage);

    // Create gradient
    NSArray *colors = [NSArray arrayWithObjects:(id)endColor.CGColor, (id)startColor.CGColor, nil];
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColors(space, (CFArrayRef)colors, NULL);

    // Apply gradient
    CGContextClipToMask(context, rect, image.CGImage);
    CGContextDrawLinearGradient(context, gradient, CGPointMake(0,0), CGPointMake(0, image.size.height), 0);
    UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGGradientRelease(gradient);
    CGColorSpaceRelease(space);

    return gradientImage;
}

而且在第一篇文章中提到的透明度滤镜(作用域像素的alpha值上)是没效果的,可以通过Quartz 2D来实现:

- (UIImage *)setAlpha:(CGFloat)alpha
{
    // http://stackoverflow.com/questions/5084845/how-to-set-the-opacity-alpha-of-a-uiimage 

    UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGRect area = CGRectMake(0, 0, self.size.width, self.size.height);

    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -area.size.height);

    CGContextSetBlendMode(ctx, kCGBlendModeMultiply);

    CGContextSetAlpha(ctx, alpha);

    CGContextDrawImage(ctx, area, self.CGImage);

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

在此基础上,通过下面四行代码,可以分别得到四种不同效果:

return [[UIImage imageWithColor:[UIColor purpleColor] size:originImage.size] changeOpacityByFactor:0.5];;

return [UIImage imageWithGradient:originImage startColor:[UIColor whiteColor] endColor:[UIColor yellowColor]];

return [[originImage tintWithMaxRGBA:(RGBA){190, 190, 230} minRGBA:(RGBA){50, 35, 10}] overlayWithImage:[[UIImage imageWithColor:[UIColor purpleColor] size:originImage.size] changeOpacityByFactor:0.3]];

return [originImage softlightWithImage:[[UIImage imageWithColor:[UIColor yellowColor] size:originImage.size] changeOpacityByFactor:0.8]];

  

 

其中,overlay算法如下:

double calcOverlay(float b, float t)
{
	return (b > 128.0f) ? 255.0f - 2.0f * (255.0f - t) * (255.0f - b) / 255.0f: (b * t * 2.0f) / 255.0f;
}

void filterOverlay(UInt8 *pixelBuf, UInt8 *pixedBlendBuf, 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];

	int blendRed = pixedBlendBuf[r];
	int blendGreen = pixedBlendBuf[g];
	int blendBlue = pixedBlendBuf[b];

        pixelBuf[r] = SAFECOLOR(calcOverlay(red, blendRed));
	pixelBuf[g] = SAFECOLOR(calcOverlay(green, blendGreen));
	pixelBuf[b] = SAFECOLOR(calcOverlay(blue, blendBlue));
}
时间: 2024-09-19 09:35:51

iOS中的图像处理(三)——混合运算的相关文章

iOS中如何判断中英文混合的字符长度_IOS

废话不多说,直接给大家贴代码了. 一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //第一种方法 NSLog(@"--first-%i",[self convertToInt:@"123我爱你"]); //第二种方法 NSLog(@"--second--%ld",[self getToInt:@&

iOS中的图像处理(二)——卷积运算

关于图像处理中的卷积运算,这里有两份简明扼要的介绍:文一,文二. 其中,可能的一种卷积运算代码如下: - (UIImage*)applyConvolution:(NSArray*)kernel { CGImageRef inImage = self.CGImage; CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage)); CFDataRef m_OutDataRef = CGDataProvid

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

最近在稍微做一些整理,翻起这部分的代码,发现是两个多月前的了. 这里讨论的是基于RGBA模型下的图像处理,即将变换作用在每个像素上. 代码是以UIImage的category形式存在的: typedef struct _singleRGBA { unsigned char red; unsigned char green; unsigned char blue; unsigned char alpha; } RGBA; @interface UIImage (ImageFilter) 首先,我们

正则表达式在IOS中的应用及IOS中三种正则表达式的使用与比较_正则表达式

正则表达式在ios中应用 一.什么是正则表达式 正则表达式,又称正规表示法,是对字符串操作的一种逻辑公式.正则表达式可以检测给定的字符串是否符合我们定义的逻辑,也可以从字符串中获取我们想要的特定部分.它可以迅速地用极简单的方式达到字符串的复杂控制. 二.正则表达式的语法 看一个过滤纯数字的例子 - (BOOL)validateNumber:(NSString *) textString { NSString* number=@"^[0-9]+$"; NSPredicate *numbe

Python中实现三目运算的方法

  这篇文章主要介绍了Python中实现三目运算的方法,本文用and/or 运算符模拟实现三目运算,需要的朋友可以参考下 C语言中三目运算符 代码如下: expression ?expr1:expr2; //expression 为真则取表达式expr1的值,否则取expr2的值 python三目实现方法: (1) expr=判断表达式 and expr1 or expr2 判断表达式为真,此时如果expr1为真则expr=expr1,为假则变成False or expr2,expr=expr2

iOS中CoreData数据管理系列二——CoreData框架中三个重要的类

iOS中CoreData数据管理系列二--CoreData框架中三个重要的类 一.引言     在上一篇博客中,介绍了iOS中使用CoreData框架设计数据模型的相关步骤.CoreData框架中通过相关的类将数据--数据模型--开发者无缝的衔接起来.NSManagedObjectModel对应数据模型,即上篇博客中我们创建的.xcdatamodeld文件:NSPersistentStoreCoordinator相当于数据库与数据模型之间的桥接器,通过NSPersistentStoreCoord

iOS中CoreData数据管理系列三——添加与查询数据

iOS中CoreData数据管理系列三--添加与查询数据 一.引言     在前两篇博客中,分别介绍了iOS中CoreData框架创建数据模型和CoreData框架中的三个核心类.博客地址如下: iOS中CoreData框架简介:http://my.oschina.net/u/2340880/blog/610488. CoreData框架中三个核心的类:http://my.oschina.net/u/2340880/blog/610948. 本篇博客将综合使用三个核心的类,进行数据创建和查询的操

在IOS中为什么使用多线程及多线程实现的三种方法_IOS

多线程是一个比较轻量级的方法来实现单个应用程序内多个代码执行路径. 在系统级别内,程序并排执行,程序分配到每个程序的执行时间是基于该程序的所需时间和其他程序的所需时间来决定的. 然而,在每个程序内部,存在一个或者多个执行线程,它同时或在一个几乎同时发生的方式里执行不同的任务. 概要提示: iPhone中的线程应用并不是无节制的,官方给出的资料显示,iPhone OS下的主线程的堆栈大小是1M,第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI

Javascript中三目运算用法例子

在JavaScript中,除了 if ... else 和 switch 语句,还有一个唯一的三目运算符 ? ... : ,也可用于简单的选择结构. 语法: conditions ? statementA : statementB ; 上述语句,首先判断条件condition,若结果为真则执行语句statementA,否则执行语句statementB. 值得注意的是,由于 JavaScript 脚本解释器将分号" ; "作为语句的结束符,statementA 和 statementB