建立一个小的画图程序,我试图结合层的概念。
我使用PictureBox控件来显示图像,并且获取图形从图象对象由在PictureBox正在显示和绘图了这一点。
我的问题是,我试图找出如何绘制到一个新的图形对象,它是在图片框的顶部重叠,并能够获得新绘制的图像,而不吸收到图形的原始图像。
如果我这样做:
Graphics gr = Graphics.FromImage(myPictureBox.image);
gr.DrawRectangle(blah blah)
......我在编辑图片框的原始图像。 我想一个办法只能捕捉新的东西被描绘成一个单独的图像,但仍然有它显示了什么已经在那里之上的覆盖。
任何人都可以点我在正确的方向? 谢谢!
其做工精细的示例代码 - 以虚拟形象和分层与自定义文本原始图像
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();
}
我将估计使用透明控制,并做一些修改,因此可以被用作图像层:
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);
希望它帮助。
得到它的工作,也许我是不是在我原来的问题不够清楚。
基本上我落得这样做存储每个层为单独的图像对象,那么就钩入我的控制OnPaint方法和手动绘制图形在顺序,而不是只绘制PictureBox.Image。 奇迹般有效!
.NET绘图库的图形处理能力非常简单。 他们的主要目的是GUI的直接绘制。 如果你想有层次感,Alpha透明度或先进的过滤器,那么应该使用第三方库或推出自己的绘制代码。