如何使用画笔绘制位图 - C#/。NET

时间:2013-10-18 15:10:07

标签: c# winforms bitmap paint

这似乎应该很简单,但我似乎无法找到任何办法。我有一个自定义的WinForms控件,它有一个重写的绘制方法,可以进行一些自定义绘制。

我在内存中有一个Bitmap,而我想做的就是使用HashBrush绘制整个内容,但保留alpha通道,这样位图的透明部分就不会被绘制。

内存中的位图不是简单的形状,因此将其定义为一组路径或任何东西是不可行的。

编辑:为了回应显示代码,paint例程中有很多代码,所以我只包含一个相关的代码片段,这是有问题的方法。从主绘制覆盖中调用此方法。它接受一个黑色透明蒙版图像列表并将它们组合成一个,然后使用ColorMatrix更改它创建的组合图像的颜色,使其可以叠加在背景上。我想要完成的只是能够在其上绘制哈希标记。

    private void PaintSurface(PaintEventArgs e, Image imgParent, List<Image> surfImgs, Rectangle destRect, ToothSurfaceMaterial material)
    {
        using (Bitmap bmp = new Bitmap(imgParent.Width, imgParent.Height,
                       System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
        {

            using (Graphics g = Graphics.FromImage(bmp))
            {
                foreach (Image img in surfImgs)
                {
                    g.DrawImage(img, System.Drawing.Point.Empty);
                }
            }

            ColorMatrix matrix = new ColorMatrix(
                new float[][] {
                    new float[] { 0, 0, 0, 0, 0},
                    new float[] { 0, 0, 0, 0, 0},
                    new float[] { 0, 0, 0, 0, 0},
                    new float[] { 0, 0, 0, 0.7f, 0},
                    new float[] { material.R / 255.0f,
                                  material.G / 255.0f,
                                  material.B / 255.0f,
                                  0, 1}
                  });

            ImageAttributes imageAttr = new ImageAttributes();
            imageAttr.SetColorMatrix(matrix);

            Rectangle r = GetSizedRect(imgParent, destRect);
            e.Graphics.DrawImage(bmp,
                                 r,
                                 0,
                                 0,
                                 bmp.Width,
                                 bmp.Height,
                                 GraphicsUnit.Pixel, imageAttr);
        }
    }

2 个答案:

答案 0 :(得分:0)

我认为您不需要{em> overkill 的任何ColorMatrix,您只需要一个ColorMap,这里的代码可能不符合您的要求,但应该给出你的想法。那是因为我可能不太了解你的问题,如果你有任何问题,请留下一些评论,我会尽力改善答案:

ImageAttributes imgA = new ImageAttributes();
ColorMap cm = new ColorMap();
cm.OldColor = Color.Black
cm.NewColor = Color.FromArgb((byte)(0.7*255), Color.Green);
imgA.SetRemapTable(new ColorMap[] {cm });         
GraphicsUnit gu = GraphicsUnit.Pixel;   
g.DrawImage(imageToDraw,new Point[]{Point.Empty, 
                                    new Point(backImage.Width/2,0), 
                                    new Point(0,backImage.Height/2)},
                        Rectangle.Round(imageToDraw.GetBounds(ref gu)), 
                        GraphicsUnit.Pixel, imgA);

new Point[]是一个3 Points的数组,用于定位目标Rectangle。 上面的代码用于imageToDraw 之上绘制backImage,并使用{{将Black的颜色转换为颜色Green 1}}。这就是你想要实现你的代码。

更新

这可能是你想要的,实际上你的代码没有显示你想要的东西,它只显示你现在所拥有的没有实现任何与你的问题有关的东西。我从您问题中的第一个描述中推断出这一点。输入是具有背景颜色的图像(稍后将部分透明)为Opacity = 70%。现在您想要的输出是一个图像,其中所有非黑色区域都涂有Black。然后将处理此输出以将HatchBrush背景变为Black背景。

partially transparent

答案 1 :(得分:0)

我最终使用的解决方案是以下方法。首先,我将各个蒙版合并为一个,然后创建一个新的Bitmap并使用HatchBrush绘制整个内容,最后遍历蒙版并根据蒙版在新生成的位图上设置alpha值。

    private Bitmap GenerateSurface(Image imgParent, List<Image> surfImgs, ToothSurfaceMaterial material)
    {
        Bitmap mask = new Bitmap(imgParent.Width, imgParent.Height,
                       System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

        using (Graphics g = Graphics.FromImage(mask))
        {
            foreach (Image img in surfImgs)
            {
                g.DrawImage(img, System.Drawing.Point.Empty);
            }
        }

        Bitmap output = new Bitmap(mask.Width, mask.Height,
                       System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

        using (Graphics g = Graphics.FromImage(output))
        {
            if (material.HatchStyle != null)
            {
                HatchBrush hb = new HatchBrush((HatchStyle)material.HatchStyle, material.FgColor, material.BgColor);
                g.FillRectangle(hb, new Rectangle(0, 0, output.Width, output.Height));
            }
            else
            {
                SolidBrush sb = new SolidBrush(material.FgColor);
                g.FillRectangle(sb, new Rectangle(0, 0, output.Width, output.Height));
            }

        }

        var rect = new Rectangle(0, 0, output.Width, output.Height);
        var bitsMask = mask.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        var bitsOutput = output.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        unsafe
        {
            int offset = 0;
            for (int y = 0; y < mask.Height; y++)
            {
                byte* ptrMask = (byte*)bitsMask.Scan0 + y * bitsMask.Stride;
                byte* ptrOutput = (byte*)bitsOutput.Scan0 + y * bitsOutput.Stride;
                for (int x = 0; x < mask.Width; x++)
                {
                    offset = 4 * x + 3;
                    ptrOutput[offset] = (byte)(ptrMask[offset] * 0.7);
                }
            }
        }
        mask.UnlockBits(bitsMask);
        output.UnlockBits(bitsOutput);

        return output;

    }