GDI +如何使用图像的字节数组?

时间:2017-03-15 19:12:56

标签: c# drawing gdi+

我希望更好地了解当我告诉图形对象绘制内容时会发生什么。更具体地说,GDI +如何设置像素'图像的颜色。

我搜索了源代码,但显然它还没有发布(我发现.dll会在这里搜索答案之后处理实际绘图:https://referencesource.microsoft.com)。

这一点的全部意义在于我能够在绘制时定义我自己的方式来改变像素的颜色。

我不确定我是否正确使用此代码:

 public unsafe Bitmap enlargeImg(Bitmap source, int newWidth, int newHeight)
    {
        int resMod = (int)Math.Min(newWidth / source.Width, newHeight / source.Height);
        Bitmap res = new Bitmap(source.Width * resMod, source.Height * resMod, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
        Graphics larGfx = Graphics.FromImage(res);
        SolidBrush br;
        int pxsz = 4;//for 32 bits per pixel
        System.Drawing.Imaging.BitmapData btd = source.LockBits(
            new Rectangle(0, 0, source.Width, source.Height),
            System.Drawing.Imaging.ImageLockMode.ReadOnly, source.PixelFormat);
        for (int r = 0; r < source.Height; r++)
        {
            byte* bfrw = (byte*)btd.Scan0 + r * btd.Stride;
            for (int c = 0; c < source.Width; c++)
            {
                byte B = bfrw[c * pxsz + 0];
                byte G = bfrw[c * pxsz + 1];
                byte R = bfrw[c * pxsz + 2];
                byte A = bfrw[c * pxsz + 3];
                br = new SolidBrush(Color.FromArgb(A, R, G, B));
                larGfx.FillRectangle(br, c * resMod, r * resMod, resMod, resMod);
            }
        }
        source.UnlockBits(btd);
        return res;
    }

在这里,我尝试扫描图像并绘制一个新图像,其中每个像素都变大。但是,这比仅使用Graphics.DrawImage调整图像大小要慢得多。是的,我确实试过了SetPixel,但它的速度要慢一些。

请注意,我正在为2D游戏引擎做这一切(因此我有一个游戏周期),所以事情必须尽可能快。

那么,GDI +如何处理图像的字节数组?

1 个答案:

答案 0 :(得分:0)

以下方法会快得多:

  • 首先更改原始尺寸相同的位图上的颜色(这样您只需为每种颜色更改一个像素) - 或者如果允许则更改原始颜色。要更改颜色,请直接在第二个(或原始)位图的缓冲区上工作(就像您现在正在读取原始位图中的字节一样) - 即将这些B G R A bytes直接写入图像缓冲区。 / p>

  • 然后使用StretchBlt将带有更新颜色的位图复制到更大的位图。这会使像素更大。

这样你也可以避免内循环中昂贵的new SolidBrush()

此外,为了只改变位图的颜色,您可以在所有像素上使用单个循环(即将位图视为一个大的1D阵列)。这样你也可以消除内部循环中的乘法(只是从头到尾循环遍历字节)。