在C#中绘制一个新的“图层”

时间:2012-10-03 06:02:12

标签: c# image bitmap layer

构建一个小型绘图程序,并尝试合并图层的概念。

我正在使用PictureBox控件来显示图像,并从PictureBox显示的图像中获取Graphics对象并绘制到该图像。

我的问题是我正在试图弄清楚如何绘制到覆盖在图片框顶部的新图形对象,并且能够获得新绘制的图像而不用原始图像图像被吸收到图形中。

如果我这样做:

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

...我正在编辑图片框中的原始图像。我想要一种方法只捕获作为单独图像绘制的新内容,但仍然将其显示为已经存在的顶部的叠加。

任何人都能指出我正确的方向吗?谢谢!

4 个答案:

答案 0 :(得分:4)

工作正常的示例代码 - 拍摄虚拟图像并将原始图像与自定义文本分层

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();
}

答案 1 :(得分: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顶部,请确保重新排序控件。应在PictureBox控件之前添加图层控件。

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

希望它有所帮助。

答案 2 :(得分:1)

有了它的工作,也许我在原来的问题上不够清楚。

基本上我最终做的是将每个图层存储为一个单独的Image对象,然后只是挂钩到我的控件的OnPaint方法并按顺序手动绘制图形,而不是仅仅绘制到PictureBox.Image。像魅力一样工作!

答案 3 :(得分:0)

.NET绘图库的图形功能很简单。它们的主要目的是直接绘制GUI。如果您想要分层,Alpha透明或高级过滤器,那么您应该使用第三方库或滚动自己的绘图代码。