- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
为了一个关于 UIImage 着色的项目,我折腾了几天。这个想法是,该应用程序将启动一组图像,我必须使用从网络服务检索到的值对其进行着色。如果您愿意,可以选择某种主题。
与我合作的设计师给了我一张关于他所有 Photoshop 值的背景图片。
第一个问题是Photoshop用的是HSL,iOS用的是HSB。因此,第一个挑战是从 Photoshop 转换值。
Photoshop HSL:-28(范围 -180 => +180)、100(范围 -100 => +100)、25(范围 -100 => +100)。
幸运的是我在网上找到了一些代码,here it is .
//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);
}
使用 online converter我验证了此方法返回了良好的值。
我需要更改范围(H:0->360,S:0->100,L:0->100)
因此 HSL 152、100、62 给出 HSB 152、76、100。该方法返回 75 的饱和度和 100 的亮度,所以我们很好。
接下来我需要将这些值应用于图像,所以这里是要更改的代码...
色调:
#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];
}];
}];
}];
最后一个完成 block 简单地将输出图像应用到 ImageView 。现在这里是结果:
基础图片
着色(仅色调)
着色(色调和饱和度)
着色(色调、饱和度和亮度)
预期结果
如您所见,最终图像是全白的(亮度为 100%)。
我完全迷失在这里,我尝试了很多组合(在每个顺序中应用 H、S 和 B),我尝试了其他库,例如 iOS-Image-Filters , 没有任何成功。我还在 Stack Overflow 上阅读了很多问题。
链接:
有人成功地将 HSL/HSB 值应用于 UIImages 吗?
最佳答案
最后,我们决定改变技术。我现在使用半透明图像来应用具有所需颜色的混合模式。
正在关注 this post我在 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;
}
关于ios - 如何将 HSB 滤色器应用到 UIImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22168297/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!