绘制到一个新的“层”在C#(Drawing to a new “layer” in C#)

2019-09-23 09:41发布

建立一个小的画图程序,我试图结合层的概念。

我使用PictureBox控件来显示图像,并且获取图形从图象对象由在PictureBox正在显示和绘图了这一点。

我的问题是,我试图找出如何绘制到一个新的图形对象,它是在图片框的顶部重叠,并能够获得新绘制的图像,而不吸收到图形的原始图像。

如果我这样做:

Graphics gr = Graphics.FromImage(myPictureBox.image);
gr.DrawRectangle(blah blah)

......我在编辑图片框的原始图像。 我想一个办法只能捕捉新的东西被描绘成一个单独的图像,但仍然有它显示了什么已经在那里之上的覆盖。

任何人都可以点我在正确的方向? 谢谢!

Answer 1:

其做工精细的示例代码 - 以虚拟形象和分层与自定义文本原始图像

public void LayerImage(System.Drawing.Image Current, int LayerOpacity)
{
    Bitmap bitmap = new Bitmap(Current);        
    int h = bitmap.Height;
    int w = bitmap.Width;
    Bitmap backg = new Bitmap(w, h + 20);
    Graphics g = null;
    try
    {
        g = Graphics.FromImage(backg);
        g.Clear(Color.White);
        Font font = new Font("Arial", 12, FontStyle.Bold, GraphicsUnit.Pixel);
        RectangleF rectf = new RectangleF(70, 90, 90, 50);
        Color color = Color.FromArgb(255, 128, 128, 128);
        Point atpoint = new Point(backg.Width / 2, backg.Height - 10);
        SolidBrush brush = new SolidBrush(color);
        StringFormat sf = new StringFormat();
        sf.Alignment = StringAlignment.Center;
        sf.LineAlignment = StringAlignment.Center;
        g.DrawString("BRAND AMBASSADOR", font, brush, atpoint, sf);
        g.Dispose();
        MemoryStream m = new MemoryStream();
        backg.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);
    }
    catch { }

    Color pixel = new Color();

    for (int x = 0; x < bitmap.Width; x++)
    {
        for (int y = 0; y < bitmap.Height; y++)
        {
            pixel = bitmap.GetPixel(x, y);
            backg.SetPixel(x, y, Color.FromArgb(LayerOpacity, pixel));
        }
    }
    MemoryStream m1 = new MemoryStream();
    backg.Save(m1, System.Drawing.Imaging.ImageFormat.Jpeg);
    m1.WriteTo(Response.OutputStream);
    m1.Dispose();
    base.Dispose();
}


Answer 2:

我将估计使用透明控制,并做一些修改,因此可以被用作图像层:

http://www.codeproject.com/Articles/26878/Making-Transparent-Controls-No-Flickering

也许这样的事情(做任何修改的必要)。

class LayerControl : UserControl
{
    private Image image;
    private Graphics graphics;

    public LayerControl(int width, int height)
    {
        this.Width = width;
        this.Height = height;

        image = new Bitmap(width, height);

        graphics = Graphics.FromImage(image);

        // Set style for control
        SetStyle(ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.UserPaint, true);
    }

    // this function will draw your image
    protected override void OnPaint(PaintEventArgs e)
    {
        var bitMap = new Bitmap(image);
        // by default the background color for bitmap is white
        // you can modify this to follow your image background 
        // or create a new Property so it can dynamically assigned
        bitMap.MakeTransparent(Color.White);

        image = bitMap;

        Graphics g = e.Graphics;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
        g.CompositingQuality = CompositingQuality.GammaCorrected;

        float[][] mtxItens = {
            new float[] {1,0,0,0,0},
            new float[] {0,1,0,0,0},
            new float[] {0,0,1,0,0},
            new float[] {0,0,0,1,0},
            new float[] {0,0,0,0,1}};

        ColorMatrix colorMatrix = new ColorMatrix(mtxItens);

        ImageAttributes imgAtb = new ImageAttributes();
        imgAtb.SetColorMatrix(
            colorMatrix,
            ColorMatrixFlag.Default,
            ColorAdjustType.Bitmap);

        g.DrawImage(image,
                    ClientRectangle,
                    0.0f,
                    0.0f,
                    image.Width,
                    image.Height,
                    GraphicsUnit.Pixel,
                    imgAtb);
    }

    // this function will grab the background image to the control it self
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        base.OnPaintBackground(e);
        Graphics g = e.Graphics;

        if (Parent != null)
        {
            BackColor = Color.Transparent;
            int index = Parent.Controls.GetChildIndex(this);

            for (int i = Parent.Controls.Count - 1; i > index; i--)
            {
                Control c = Parent.Controls[i];
                if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
                {
                    Bitmap bmp = new Bitmap(c.Width, c.Height, g);
                    c.DrawToBitmap(bmp, c.ClientRectangle);

                    g.TranslateTransform(c.Left - Left, c.Top - Top);
                    g.DrawImageUnscaled(bmp, Point.Empty);
                    g.TranslateTransform(Left - c.Left, Top - c.Top);
                    bmp.Dispose();
                }
            }
        }
        else
        {
            g.Clear(Parent.BackColor);
            g.FillRectangle(new SolidBrush(Color.FromArgb(255, Color.Transparent)), this.ClientRectangle);
        }
    }

    // simple drawing circle function
    public void DrawCircles()
    {
        using (Brush b = new SolidBrush(Color.Red))
        {
            using (Pen p = new Pen(Color.Green, 3))
            {
                this.graphics.DrawEllipse(p, 25, 25, 20, 20);
            }
        }
    }

    // simple drawing rectable function
    public void DrawRectangle()
    {
        using (Brush b = new SolidBrush(Color.Red))
        {
            using (Pen p = new Pen(Color.Red, 3))
            {
                this.graphics.DrawRectangle(p, 50, 50, 40, 40);
            }
        }
    }

    // Layer control image property
    public Image Image
    {
        get
        {
            return image;
        }
        set
        {
            image = value;
            // this will make the control to be redrawn
            this.Invalidate();
        }
    }
}

例如如何使用它:

LayerControl lc = new LayerControl(100, 100);
lc.Location = new Point(0, 0);
lc.DrawRectangle();

LayerControl lc2 = new LayerControl(100, 100);
lc2.Location = new Point(0, 0);
lc2.DrawCircles();

LayerControl lc3 = new LayerControl(100, 100);
lc3.Location = new Point(0, 0);
lc3.Image = new Bitmap(@"<Image Path>");

// adding control
this.Controls.Add(dc);
this.Controls.Add(dc2);
this.Controls.Add(dc3);

使用这种方法,你可以有一个可以把相互重叠(由于透明功能有)多层。

如果你想将其添加到您的图片框的顶部一定要重新排序的控制。 图层控制应该将PictureBox控件之前加入。

// adding control
this.Controls.Clear();
this.Controls.Add(dc);
this.Controls.Add(dc2);
this.Controls.Add(dc3);
this.Controls.Add(PictureBox1);

希望它帮助。



Answer 3:

得到它的工作,也许我是不是在我原来的问题不够清楚。

基本上我落得这样做存储每个层为单独的图像对象,那么就钩入我的控制OnPaint方法和手动绘制图形在顺序,而不是只绘制PictureBox.Image。 奇迹般有效!



Answer 4:

.NET绘图库的图形处理能力非常简单。 他们的主要目的是GUI的直接绘制。 如果你想有层次感,Alpha透明度或先进的过滤器,那么应​​该使用第三方库或推出自己的绘制代码。



文章来源: Drawing to a new “layer” in C#