我的目标是改变“我!”零件颜色。要么仅为图像的最后3个着色,要么用新颜色替换蓝色。
换色后的预期结果:
不幸的是,这对我没用。要更改特定的颜色,我尝试了这个:LINK,但正如文档所说,这只适用于没有Alpha通道!
然后我尝试了这个:LINK,但这实际上什么也没做,没有色彩或任何东西。
是否有其他方法只为颜色的一部分着色或只是替换特定的颜色?
答案 0 :(得分:4)
事实证明它非常复杂 - 你认为你可以通过CoreGraphics混合模式一次性完成它,但是从相当广泛的实验中我没有发现这样的方法不会破坏alpha通道或者着色。我着手解决的问题是:
这可行的原因是混合模式的组合。你正在做的是创建一个完全不透明的黑白图像(步骤5),然后将它乘以你的最终颜色(步骤8),这将为你提供一个完全不透明的黑色和你的最终彩色图像。然后,您拍摄原始图像,该图像仍然具有其Alpha通道,并使用“目标输入”混合模式绘制它,该模式采用来自黑色和您的彩色图像的颜色以及来自原始图像的Alpha通道。结果是带有原始亮度值和alpha通道的着色图像。
<强>目标C 强>
- (UIImage *)createTintedImageFromImage:(UIImage *)originalImage color:(UIColor *)desiredColor {
CGSize imageSize = originalImage.size;
CGFloat imageScale = originalImage.scale;
CGRect contextBounds = CGRectMake(0, 0, imageSize.width, imageSize.height);
UIGraphicsBeginImageContextWithOptions(imageSize, NO /* not opaque */, imageScale); // 2
[[UIColor blackColor] setFill]; // 3a
UIRectFill(contextBounds); // 3b
[originalImage drawAtPoint:CGPointZero]; // 4
UIImage *imageOverBlack = UIGraphicsGetImageFromCurrentImageContext(); // 5
CGContextClear(UIGraphicsGetCurrentImageContext()); // 6
[desiredColor setFill]; // 7a
UIRectFill(contextBounds); // 7b
[imageOverBlack drawAtPoint:CGPointZero blendMode:kCGBlendModeMultiply alpha:1]; // 8
[originalImage drawAtPoint:CGPointZero blendMode:kCGBlendModeDestinationIn alpha:1]; // 9
finalImage = UIGraphicsGetImageFromCurrentContext(); // 10
UIGraphicsEndImageContext();
return finalImage;
}
Swift 4
func createTintedImageFromImage(originalImage: UIImage, desiredColor: UIColor) -> UIImage {
let imageSize = originalImage.size
let imageScale = originalImage.scale
let contextBounds = CGRect(origin: .zero, size: imageSize)
UIGraphicsBeginImageContextWithOptions(imageSize, false /* not opaque */, imageScale) // 2
defer { UIGraphicsEndImageContext() }
UIColor.black.setFill() // 3a
UIRectFill(contextBounds) // 3b
originalImage.draw(at: .zero) // 4
guard let imageOverBlack = UIGraphicsGetImageFromCurrentImageContext() else { return originalImage } // 5
desiredColor.setFill() // 7a
UIRectFill(contextBounds) // 7b
imageOverBlack.draw(at: .zero, blendMode: .multiply, alpha: 1) // 8
originalImage.draw(at: .zero, blendMode: .destinationIn, alpha: 1) // 9
guard let finalImage = UIGraphicsGetImageFromCurrentImageContext() else { return originalImage } // 10
return finalImage
}
答案 1 :(得分:2)
有很多方法可以做到这一点。
核心图像过滤器是一种很好的方法。由于您要更改的部分是唯一颜色,因此您可以使用Core图像CIHueAdjust过滤器将色调从蓝色移至红色。只有你想要改变的词有任何颜色,所以它会发生变化。
如果您的图像中包含各种颜色但仍想替换所有图像中的颜色,您可以使用CIColorCube将蓝色像素映射为红色而不影响其他颜色。上周在这个板上有一个线程,使用CIColorCube的示例代码强制一种颜色到另一种颜色。在CIColorCube上搜索并查找最新的帖子,您应该能够找到它。
如果您想将更改限制在屏幕的特定区域,您可能会想出一系列核心图像过滤器,这些过滤器会将您的更改限制在目标区域。
您还可以切出要更改的部分,使用各种技术对其进行颜色编辑,然后将其合并在一起。
答案 2 :(得分:0)
另一种方法是使用CoreImage过滤器 - ColorCube。 遇到这个问题时为自己制作类别。它适用于NSImage,但我认为在更新后应该适用于UIImage https://github.com/braginets/NSImage-replace-color