混合模式 kCGBlendModeMultiply 未正确地将图像与颜色相乘

Posted

技术标签:

【中文标题】混合模式 kCGBlendModeMultiply 未正确地将图像与颜色相乘【英文标题】:Blend mode kCGBlendModeMultiply is not correctly multiplying an image with a color 【发布时间】:2015-03-06 11:35:45 【问题描述】:

目标:通过将图像与颜色相乘来为图像着色。

假设:根据 Apple 的 documentation,混合模式 kCGBlendModeMultiply“将源图像样本与背景图像样本相乘”。我从中了解到的是:R = S * D 代表 R、G、B 和 A。因此,如果乘法中的 2 个像素之一的 RED 值为 0.0,则生成的像素的 RED 将为 0.0。

结果:当颜色具有 alpha 时,它不会这样做。如果我使用 alpha 为 0.5 的黑色颜色,我希望图像的 alpha 为 1.0 的所有像素的结果都是黑色,alpha 为 0.5。

注意:颜色 alpha 为 1.0 时似乎可以正常工作。如果我使用 alpha 为 1.0 的黑色,则生成的图像是纯黑色图像,但这不是我在这里要问的。

预期结果

    图像的 alpha 应该是 0.5,因为这是颜色的 alpha,但是您看不到任何红色背景色透过图像,除了角落,因为我使用图像作为剪贴蒙版。 图像应该是完全灰色的,因为颜色的 R、G 和 B 值为 0.0。当您乘以 0 时,结果应该是 0。

下面的代码是我在操场上所做的复制/过去,所附图像显示了原始图像色调颜色图像视图中的结果图像红色背景的图像视图(检查透明度)按此顺序。

import UIKit

// Get the image, its size, blend mode and tint color
var image = UIImage(named: "outlook-checkmark");
var size = image!.size;
var blendMode = kCGBlendModeMultiply;
var tintColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.5);

// Create the graphic context, a frame with the image size
// and get the CGImage.
UIGraphicsBeginImageContextWithOptions(size, false, 0.0);
var context : CGContextRef = UIGraphicsGetCurrentContext();
var aRect = CGRectMake(0, 0, size.width, size.height);
var cgImage = image!.CGImage;

// Converting a UIImage to a CGImage flips the image,
// so apply an upside-down translation
CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextSetBlendMode(context, blendMode);
CGContextDrawImage(context, aRect, cgImage);

// Set the mask to only tint non-transparent pixels
CGContextClipToMask(context, aRect, cgImage);

CGContextSetFillColorWithColor(context, tintColor.CGColor);
CGContextFillRect(context, aRect);

var returnImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

var imageView = UIImageView(frame: CGRectMake(0, 0, 100, 100));
imageView.image = returnImage;
imageView.backgroundColor = UIColor.redColor();

【问题讨论】:

【参考方案1】:

我认为您对多重混合模式和生成的 Alpha 分量的期望完全不正确。我不希望混合到不透明的图像上会使其透明。

混合模式文档向您推荐 PDF spec 以了解非 Porter-Duff 模式的行为。它相当密集,但在我看来,结果 alpha 根本不受混合模式的影响。如果背景是不透明的,则结果是不透明的。

规范的第 7.2.7 节对合成计算进行了总结。出于我们的目的,我们不关心“形状”,所以所有的 ƒ 变量都是 1.0 并且 alpha 等于不透明度 (α = ?)。规范说 α? = α??−(α?×α? )。在您的情况下,背景 alpha (α?) 为 1.0,因此:

α? = α??−(α?×α?) α? = 1.0+α?−(1.0×α?) α? = 1.0+α?−α? α? = 1.0

【讨论】:

感谢您浏览低级别文档。我想你在技术上是正确的。但是,我很惊讶它会这样工作。我不是图像处理方面的专家,但我希望乘法模式可以进行逐个组件的乘法。特别是因为这就是 android 文档所说的:[Sa * Da, Sc * Dc]。 developer.android.com/reference/android/graphics/…。我们的 Android 团队在我们之前实现了图像着色 (ios),因此我们将它们用作参考。【参考方案2】:

看起来这篇博文展示了一种为图像着色的方法:https://robots.thoughtbot.com/designing-for-ios-blending-modes

【讨论】:

谢谢。我以前看过这篇文章。我试图实现的是像 Android 那样的乘法模式,其结果是每个 RGBA 组件的精确乘法。根据文档:[Sa * Da, Sc * Dc]。 (a = alpha,c = 颜色,S = 源,D = 目标/背景)developer.android.com/reference/android/graphics/… 我们的 Android 团队在我们之前实现了图像着色(iOS),使用该模式为我们的图像设置样式。从描述中您可以看到它非常直观,它允许您使用具有“白色”阴影的图像并应用您想要的任何颜色。 啊。也许您可以使用 CoreImage 和自定义着色器来完成您想要的像素操作。

以上是关于混合模式 kCGBlendModeMultiply 未正确地将图像与颜色相乘的主要内容,如果未能解决你的问题,请参考以下文章

CSS3混合模式

Photoshop的混合模式

css 颜色混合模式 mix-blend-mode

Chrome 中的混合模式问题

UE4材质混合模式bate0117

如何在颤振中使用混合混合模式?