如何叠加两张图片(作为字节数组)

3

大家好,我相信这很容易,但谷歌并没有帮助到我...

这是任务 - 我有两个字节数组(作为ARGB),代表我的图像。它们具有相同的大小。 我应该执行什么操作(逐字节)来将一个图像覆盖到另一个图像上? 第二个图像具有一定的透明度,必须加以考虑。

为了清楚起见,我正在寻找像这样的代码:

          bytes[] result = new bytes[first.Length];
          for(i = 0; i< first.Lenght;i++)
          {
               result[i] = first[i] !!%SOMETHING%!! second[i];
          }

简单的猜测,比如按位或(我知道 - 那很愚蠢;))不起作用。

感谢您的回答。

编辑:由于安全问题(所有这些奇怪的操作发生在Silverlight上),我无法使用标准库。


没有问题)但是语言在这里并不重要——答案更多是数学而不是代码... - ALOR
2个回答

7

假设你正在使用位图,那么你可能会发现让库来帮助你处理更容易。

System.Drawing.Graphics类有一个CompositingMode属性,可以设置为SourceCopy(默认值-覆盖背景颜色)或SourceOver(与背景颜色混合)。

详见MSDN:如何使用混合模式控制Alpha混合

如果你只想要原始的数学公式,Alpha混合很简单。对于0.0到1.0之间的Alpha值a,结果应该为:

(aOld * oldValue) + ((1 - aOld) * aNew * newValue)

其中oldValue是覆盖前的先前值,newValue是您想进行覆盖的值,aOldaNew分别是旧的和新的alpha值。显然,您需要分别对R、G和B值进行此计算。

另请参阅:Alpha Compositing(维基链接)以获取更详细的说明。


更新:我认为适应原始代码应该很容易,但我猜并不是每个人都精通数学。
我将假设byte[]是A,R,G,B值的重复序列(因此Length将是4的倍数)。 如果不是这种情况,则您必须根据自己使用的存储格式调整此代码。
bytes[] result = new bytes[first.Length];
for(i = 0; i < first.Length; i += 4)
{
    byte a1 = first[i];
    byte a2 = second[i];
    byte r1 = first[i+1];
    byte r2 = second[i+1];
    byte g1 = first[i+2];
    byte g2 = second[i+2];
    byte b1 = first[i+3];
    byte b2 = second[i+3];

    byte a = a1 + (255 - a1) * a2 / 255;
    byte r = r1 * a1 / 255 + r2 * (255 - a1) * a2 / 65025;
    byte g = g1 * a1 / 255 + g2 * (255 - a1) * a2 / 65025;
    byte b = b1 * a1 / 255 + b2 * (255 - a1) * a2 / 65025;

    result[i] = a;
    result[i+1] = r;
    result[i+2] = g;
    result[i+3] = b;
}

1
抱歉,我没有完全解释清楚...我需要按照我写的方式做某事。请查看编辑。 - ALOR
@ALOR:对我来说,很难按照你写的格式给你一个解决方案,因为简单的字节数组并不能告诉我颜色信息实际上是如何存储的。完整的ARGB值是4个字节(或int)。你有4个字节数组,每个通道一个吗?数组是否重复,即A,然后R,然后G,然后B,再次A?有任何头文件吗?那个数组里面是什么? - Aaronaught

0

我认为你的想法是正确的。你使用的操作取决于你想要的输出结果。以下是一些有用的操作:

  1. 平均值 - 一种常见的组合方式
  2. 最小值
  3. 最大值
  4. 按位替换
  5. xor
  6. 将图像1的值乘以(图像2缩放为0到1)。这将使更多的图像1出现在图像2的亮处,而不是暗处。尝试它们并看看哪个最好,或者更好的是,让用户选择。

你可以可能添加或或透明度字节,并对三种颜色中的每一种使用其他操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接