如何使用画笔在位图上绘制-C#/.NET

如何使用画笔在位图上绘制-C#/.NET,c#,winforms,bitmap,paint,C#,Winforms,Bitmap,Paint,这似乎应该很简单,但我似乎找不到任何方法来做到这一点。我有一个自定义WinForms控件,它有一个重写的绘制方法,该方法可以进行一些自定义绘制 我在内存中有一个位图,我想做的就是用HashBrush在整个东西上绘制,但是保留alpha通道,这样位图的透明部分就不会被绘制 内存中的位图不是一个简单的形状,因此将其定义为一组路径或任何东西都是不可行的 编辑:为了显示代码,在绘制例程中有很多代码,所以我只包含一个相关的代码片段,这就是所讨论的方法。此方法从主绘制覆盖调用。它接受黑色透明遮罩的图像列表,

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

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

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

编辑:为了显示代码,在绘制例程中有很多代码,所以我只包含一个相关的代码片段,这就是所讨论的方法。此方法从主绘制覆盖调用。它接受黑色透明遮罩的图像列表,并将它们组合成一个,然后使用颜色矩阵更改它创建的组合图像的颜色,使其覆盖在背景之上。我想要完成的就是能够在上面画上hashmarks

    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);
        }
    }
private void PaintSurface(PaintEventArgs e、图像imgParent、列表surfacemgs、矩形析取、齿面材质)
{
使用(位图bmp=新位图(imgParent.Width、imgParent.Height、,
系统.绘图.成像.像素格式.格式32BPPPARGB)
{
使用(Graphics g=Graphics.FromImage(bmp))
{
foreach(MGS中的图像img)
{
g、 DrawImage(img,System.Drawing.Point.Empty);
}
}
ColorMatrix=新的ColorMatrix(
新浮动[][]{
新浮点[]{0,0,0,0,0},
新浮点[]{0,0,0,0,0},
新浮点[]{0,0,0,0,0},
新浮点[]{0,0,0,0.7f,0},
新浮动[]{material.R/255.0f,
材料G/255.0f,
材料B/255.0f,
0, 1}
});
ImageAttributes imageAttr=新的ImageAttributes();
imageAttr.SetColorMatrix(矩阵);
矩形r=GetSizedRect(imgParent,destRect);
e、 Graphics.DrawImage(bmp,
R
0,
0,
bmp.Width,
bmp.高度,
GraphicsUnit.Pixel、imageAttr);
}
}

我认为您不需要任何过度使用的
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);
新点[]
是一个由3个
点组成的数组,用于定位目标矩形。
上面的代码用于
背景图像
上绘制
图像,并将
黑色
的颜色转换为
绿色
,透明度为70%
。这就是您想要实现代码的内容

更新 这可能是您想要的,事实上,您的代码并没有显示您想要的内容,它只是显示了您拥有的内容,而这些内容现在并没有实现与您的问题相关的任何内容。我从你问题中的第一个描述推断出这一点。输入是背景色(稍后将部分透明)为
黑色的图像。现在,您想要的输出是一个图像,其中所有非黑色区域都使用
阴影笔刷绘制。然后处理该输出,将
黑色
背景变成
部分透明
背景

public void PaintHatchBrush(Bitmap input, HatchBrush brush){
   using(Graphics g = Graphics.FromImage(input)){
      g.Clip = GetForegroundRegion(input, Color.Black);
      GraphicsUnit gu = GraphicsUnit.Pixel;
      g.FillRectangle(brush, input.GetBounds(ref gu));
   }
}
//This is implemented using `GetPixel` which is not fast, but it gives you the idea.
public Region GetForegroundRegion(Bitmap input, Color backColor){
  GraphicsPath gp = new GraphicsPath();
      Rectangle rect = Rectangle.Empty;          
      bool jumpedIn = false;
      for (int i = 0; i < bm.Height; i++) {
          for (int j = 0; j < bm.Width; j++) {
             Color c = bm.GetPixel(j, i);
             if (c != backColor&&!jumpedIn) {
                 rect = new Rectangle(j, i, 1, 1);                        
                 jumpedIn = true;
             }
             if (jumpedIn && (c == backColor || j == bm.Width - 1)) {
                 rect.Width = j - rect.Left;
                 gp.AddRectangle(rect);
                 jumpedIn = false;
             }
          }
      }
      return new Region(gp);
}
//Usage
HatchBrush brush = new HatchBrush(HatchStyle.Percent30, Color.Green, Color.Yellow);
PaintHatchBrush(yourImage, brush);
//then yourImage will have HatchBrush painted on the surface leaving the Black background intact.
//This image will be used in the next process to turn the Black background into 70%
//opacity background as you did using ColorMatrix (or more simply using ColorMap as I posted previously)
public void PaintHatchBrush(位图输入,HatchBrush笔刷){
使用(Graphics g=Graphics.FromImage(输入)){
g、 Clip=GetForegroundRegion(输入,颜色为黑色);
GraphicsUnit gu=GraphicsUnit.Pixel;
g、 FillRectangle(画笔,输入.GetBounds(ref-gu));
}
}
//这是使用'GetPixel'实现的,虽然速度不快,但它提供了一种思路。
公共区域GetForegroundRegion(位图输入,颜色背景色){
GraphicsPath gp=新的GraphicsPath();
矩形rect=Rectangle.Empty;
bool jumpedIn=假;
对于(int i=0;i
我最终使用的解决方案是以下方法。首先,我将各个遮罩组合成一个,然后创建一个新位图,并使用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;

    }
专用位图生成表面(图像imgParent、列表surfacemgs、齿面材质)
{
位图掩码=新位图(imgParent.Width、imgParent.Height、,
系统