如何覆盖两个图像(作为字节数组)

时间:2010-02-06 04:23:24

标签: c# algorithm image bitmap

人们,我确信这很容易,但谷歌没有帮助......

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

要清除,我正在寻找这样的代码:

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

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

谢谢你的答案。

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

2 个答案:

答案 0 :(得分:7)

假设您实际上正在使用位图,您可能会发现让图书馆为您执行此操作更容易。

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

有关详细信息,请参阅MSDN: How to Use Compositing Mode to Control Alpha Blending

如果你只想要原始数学,alpha混合非常简单。对于介于0.0和1.0之间的alpha值 a ,结果应为:

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

其中oldValue是叠加前的前一个值,newValue是您要叠加的内容,aOldaNew分别是旧的和新的Alpha值。你显然需要分别对R,G和B值进行计算。

另请参阅:Alpha Compositing(wiki链接)以获得更全面的解释。


更新:我认为应该很容易弄清楚如何使其适应OP中的代码,但我想不是每个人都是数学家。

我将假设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 :(得分:0)

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

  1. 平均值 - 一种常用的组合方式
  2. 最小
  3. 最大
  4. 按位替换
  5. XOR
  6. 添加
  7. 减去
  8. 将图像1的值乘以(图像2缩放为0到1)。这将使更多的图像1放在图像2的明亮位置而不是在黑暗的地方。尝试一下,看看你最喜欢什么,或者更好,让用户选择。
  9. 您可以添加或者透明度字节,并对三种颜色中的每一种使用其他操作之一。