如何将HSB彩色滤镜应用于UIImage

我一直在为UIImage着色项目奋斗几天。 这个想法是应用程序将开始一组图像,我将不得不使用从Web服务检索的值着色。 如果你愿意,可以使用某种主题。

我工作的设计师给了我一个关于他所有Photoshop值的背景图片。

第一个问题是Photoshop使用HSL而iOS使用HSB。 因此,第一个挑战是从Photoshop翻译值。

Photoshop HSL:-28(范围-180 => +180),100(范围-100 => +100),25(范围-100 => +100)。

幸运的是我在网上找到了一些代码, 现在就是这样 。

//adapted from https://gist.github.com/peteroupc/4085710 - (void)convertLightnessToBrightness:(CGFloat)lightness withSaturation:(CGFloat)saturation completion:(void (^)(CGFloat, CGFloat))completion { if (!completion) return; //What's the point of calling this method without a completion block! CGFloat brightness = 0.0f; CGFloat saturationOut = 0.0f; if (lightness > 0.0f) { CGFloat lumScale = (1.0f - MAX((lightness - 0.5f), 0.0f) * 2.0f); lumScale = ((lumScale == 0) ? 0 : (1.0f / lumScale)); CGFloat lumStart = MAX(0.0f, (lumScale - 0.5f)); CGFloat lumDiv = (lumScale - lumStart); lumDiv = (lumStart + (saturation * lumDiv)); saturationOut = ((lumDiv == 0) ? 0.0f : (saturation / lumDiv)); brightness = (lightness + (1.0f - lightness) * saturation); } NSLog(@"saturation: %0.2f - brightness: %0.2f", saturationOut, brightness); completion(saturationOut, brightness); } 

使用在线转换器我validation了此方法返回了良好的值。
我需要改变范围(H:0-> 360,S:0-> 100,L:0-> 100)

彩色转换器

因此HSL 152,100,62给出HSB 152,76,100。并且该方法返回75用于饱和,100用于亮度,因此我们是好的。

接下来我需要将这些值应用于图像,所以这里是要更改的代码……

HUE:

 #define DEGREES_TO_RADIANS(angle) ((angle) / 180.0f * M_PI) - (void)colorize:(UIImage *)input hue:(CGFloat)hueDegrees completion:(void(^)(UIImage *outputHue))completion { if (!completion) return; //What's the point of calling this method without a completion block! CGFloat hue = DEGREES_TO_RADIANS(hueDegrees); NSLog(@"degress: %0.2f | radian: %0.2f", hueDegrees, hue); CIImage *inputImage = [CIImage imageWithCGImage:input.CGImage]; //--- CIFilter *hueFilter = [CIFilter filterWithName:@"CIHueAdjust" keysAndValues:kCIInputImageKey, inputImage, nil]; [hueFilter setDefaults]; [hueFilter setValue:[NSNumber numberWithFloat:hue] forKey:kCIInputAngleKey]; //--- CIImage *outputImage = [hueFilter outputImage]; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]]; UIImage *outputUIImage = [UIImage imageWithCGImage:cgimg]; CGImageRelease(cgimg); completion(outputUIImage); } 

饱和度:

 - (void)colorize:(UIImage *)input saturation:(CGFloat)saturation completion:(void(^)(UIImage *outputSaturation))completion { if (!completion) return; //What's the point of calling this method without a completion block! NSLog(@"saturation: %0.2f", saturation); CIImage *inputImage = [CIImage imageWithCGImage:input.CGImage]; //--- CIFilter *saturationFilter = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, inputImage, nil]; [saturationFilter setDefaults]; [saturationFilter setValue:[NSNumber numberWithFloat:saturation] forKey:@"inputSaturation"]; //--- CIImage *outputImage = [saturationFilter outputImage]; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]]; UIImage *outputUIImage = [UIImage imageWithCGImage:cgimg]; CGImageRelease(cgimg); completion(outputUIImage); } 

亮度:

 - (void)colorize:(UIImage *)input brightness:(CGFloat)brightness completion:(void(^)(UIImage *outputBrightness))completion { if (!completion) return; //What's the point of calling this method without a completion block! NSLog(@"brightness: %0.2f", brightness); CIImage *inputImage = [CIImage imageWithCGImage:input.CGImage]; //--- CIFilter *brightnessFilter = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, inputImage, nil]; [brightnessFilter setDefaults]; [brightnessFilter setValue:[NSNumber numberWithFloat:brightness] forKey:@"inputBrightness"]; //--- CIImage *outputImage = [brightnessFilter outputImage]; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]]; UIImage *outputUIImage = [UIImage imageWithCGImage:cgimg]; CGImageRelease(cgimg); completion(outputUIImage); } 

一切都放在一起:

 CGFloat hue = -28.0f; //152 in 360° range (180 - 28 = 152) CGFloat saturation = 1.0f; //((100 + 100.0f) / 200.0f) CGFloat lightness = 0.625f; //((25 + 100.0f) / 200.0f) [self convertLightnessToBrightness:ligthness withSaturation:saturation completion:^(CGFloat saturationOut, CGFloat brightness) { //saturarationOut = 0.75f and brigthness = 1.0f [self colorize:input hue:hue completion:^(UIImage *outputHue) { [self colorize:outputHue saturation:saturationOut completion:^(UIImage *outputSaturation) { [self colorize:outputSaturation brightness:brightness completion:completion]; }]; }]; }]; 

最后一个完成块只是将输出图像应用于图像视图。 现在结果如下:

基本形象

基本形象

着色(仅限色调)

只有色调

着色(色调和饱和度)

色调和饱和度

着色(色调,饱和度和亮度)

色调,饱和度和亮度

预期结果

预期结果

如您所见,最终图像是完全白色的(亮度为100%)。

我完全迷失在这里,我尝试了很多组合(在每个顺序中应用H,S和B),我尝试过其他libs,如iOS-Image-Filters ,但没有任何成功。 我也在Stack Overflow上阅读了很多问题。

链接:

  • 核心图像filter参考
  • CIHueAdjust核心图像filter设置
  • 如何以编程方式更改UIImage的色调?
  • iOS:Photoshop中CIFilter(Hue)的值

有没有人成功将HSL / HSB值应用于UIImages?

最后,我们决定改变技术。 我现在使用半透明图像来应用具有所需颜色的混合模式。

在这篇文章之后,我在UIImage上做了一个类别。

 - (UIImage *)tintedBackgroundImageWithColor:(UIColor *)tintColor { UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f); [tintColor setFill]; CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height); UIRectFill(bounds); [self drawInRect:bounds blendMode:kCGBlendModeSourceAtop alpha:1.0f]; UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return tintedImage; }