【问题标题】:C# Copy bitmap's pixels in the alpha channel on another bitmapC# 在另一个位图的 alpha 通道中复制位图的像素
【发布时间】:2014-06-25 14:15:48
【问题描述】:

我有两张位图,一张包含“正常”图片,另一张包含灰度图像。

我的目标只是将灰度图像放在第一位图的 alpha 通道中,以便像蒙版一样使用灰度图像。

我已经看到了一些使用 SetPixel 的解决方案,但它非常慢,并且由于内存分配错误,会在最终图像上产生一些奇怪的伪影。

因此,可能的一种方法是浏览原始位图中的所有像素,并从 alpha 通道中的灰度位图中为其分配相应的像素。也许使用 LockBits 像素数组?

所以我的问题是如何做到这一点?我特别难以找到如何在 alpha 通道中分配一个像素以及如何在灰度位图中获取相应的像素。

【问题讨论】:

  • 也许,你有什么问题?有代码吗?
  • 回答你的问题:是的,使用 LockBits
  • 谢谢你的回答,我试过看LockBits,但我不知道如何在alpha通道中分配一个像素以及如何在灰度位图中获取相应的像素。

标签: c# image bitmap


【解决方案1】:

这还没有使用 LockBits,但它足以让你看看它是否能满足你的需求:

public Bitmap getGrayOverlay(Bitmap bmpColor, Bitmap bmpGray)
{
    Size s1 = bmpColor.Size;
    Size s2 = bmpGray.Size;
    if (s1 != s2) return null;

    Bitmap bmpResult= new Bitmap(s1.Width, s1.Height);

    for (int y = 0; y < s1.Height; y++)
        for (int x = 0; x < s1.Width; x++)
        {
            Color c1 = bmpColor.GetPixel(x, y);
            Color c2 = bmpGray.GetPixel(x, y);
            bmpResult.SetPixel(x, y, Color.FromArgb((int)(255 * c2.GetBrightness()), c1 ) );
        }
    return bmpResult;
}

使用完所有三个位图后,请丢弃它们!

这里是LockBit版本,稍微长一点,但基本一样。大约快10倍.. 我假设输入文件是 24bppRGB 或 32bppARGB,否则它们返回 null..:

public Bitmap getGrayOverlayLBA(Bitmap bmp1, Bitmap bmp2)
{
    Size s1 = bmp1.Size;
    Size s2 = bmp2.Size;
    if (s1 != s2) return null;

    PixelFormat fmt1 = bmp1.PixelFormat;
    PixelFormat fmt2 = bmp2.PixelFormat;

    PixelFormat fmt = new PixelFormat();
    fmt = PixelFormat.Format32bppArgb;
    Bitmap bmp3 = new Bitmap(s1.Width, s1.Height, fmt);

    Rectangle rect = new Rectangle(0, 0, s1.Width, s1.Height);

    BitmapData bmp1Data = bmp1.LockBits(rect, ImageLockMode.ReadOnly, fmt1);
    BitmapData bmp2Data = bmp2.LockBits(rect, ImageLockMode.ReadOnly, fmt2);
    BitmapData bmp3Data = bmp3.LockBits(rect, ImageLockMode.ReadWrite, fmt);

    byte bpp1 = 4;
    byte bpp2 = 4;
    byte bpp3 = 4;

    if (fmt1 == PixelFormat.Format24bppRgb) bpp1 = 3;
    else if (fmt1 == PixelFormat.Format32bppArgb) bpp1 = 4; else return null;
    if (fmt2 == PixelFormat.Format24bppRgb) bpp2 = 3;
    else if (fmt2 == PixelFormat.Format32bppArgb) bpp2 = 4; else return null;

    int size1 = bmp1Data.Stride * bmp1Data.Height;
    int size2 = bmp2Data.Stride * bmp2Data.Height;
    int size3 = bmp3Data.Stride * bmp3Data.Height;
    byte[] data1 = new byte[size1];
    byte[] data2 = new byte[size2];
    byte[] data3 = new byte[size3];
    System.Runtime.InteropServices.Marshal.Copy(bmp1Data.Scan0, data1, 0, size1);
    System.Runtime.InteropServices.Marshal.Copy(bmp2Data.Scan0, data2, 0, size2);
    System.Runtime.InteropServices.Marshal.Copy(bmp3Data.Scan0, data3, 0, size3);

    for (int y = 0; y < s1.Height; y++)
    {
        for (int x = 0; x < s1.Width; x++)
        {
            int index1 = y * bmp1Data.Stride + x * bpp1;
            int index2 = y * bmp2Data.Stride + x * bpp2;
            int index3 = y * bmp3Data.Stride + x * bpp3;
            Color c1, c2;

            if (bpp1 == 4)
                c1 = Color.FromArgb(data1[index1 + 3], data1[index1 + 2], data1[index1 + 1], data1[index1 + 0]);
            else c1 = Color.FromArgb(255, data1[index1 + 2], data1[index1 + 1], data1[index1 + 0]);
            if (bpp2 == 4)
                c2 = Color.FromArgb(data2[index2 + 3], data2[index2 + 2], data2[index2 + 1], data2[index2 + 0]);
            else c2 = Color.FromArgb(255, data2[index2 + 2], data2[index2 + 1], data2[index2 + 0]);

            byte A = (byte)(255 * c2.GetBrightness());
            data3[index3 + 0] = c1.B;
            data3[index3 + 1] = c1.G;
            data3[index3 + 2] = c1.R;
            data3[index3 + 3] = A;
        }
    }

    System.Runtime.InteropServices.Marshal.Copy(data3, 0, bmp3Data.Scan0, data3.Length);
    bmp1.UnlockBits(bmp1Data);
    bmp2.UnlockBits(bmp2Data);
    bmp3.UnlockBits(bmp3Data);
    return bmp3;
}

编辑:我修改了代码以允许 24bpp 图像作为源。

【讨论】:

  • 感谢 LockBit 代码,但不幸的是,我在 Color c1 = Color.FromArgb(data1[index + 3], data1[index + 2], data1[index + 1],数据1[索引 + 0]);
  • 该代码假定两个输入图像都是 32bpp,尽管它看起来有点不同。如果您的第一张图片只有 24bbp,您将不得不进行一些更改。是这样吗?
  • 是的,我的输入图像是 24bbp
  • 谢谢,只有diffColor变量没有赋值
  • 这就像一个魅力,非常感谢你:)
猜你喜欢
  • 2022-05-21
  • 2010-09-23
  • 2011-02-06
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
相关资源
最近更新 更多