I try to do double buffer using BufferedGraphics. When i use BufferedGraphics.Render method background of my image changes to black. Here the simple code, that illustrate my issue
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e) {
Paint += new PaintEventHandler(Form1_Paint);
}
private void print(Bitmap image, PaintEventArgs e) {
Graphics graphicsObj = e.Graphics;
graphicsObj.DrawImage(image, 60, 10);
graphicsObj.Dispose();
}
private void Form1_Paint(object sender, PaintEventArgs e) {
Rectangle rect = Screen.PrimaryScreen.Bounds;
PixelFormat pf;
pf = PixelFormat.Format32bppArgb;
Bitmap image = new Bitmap(rect.Width, rect.Height, pf);
Graphics g = Graphics.FromImage(image);
g.Clear(Color.Orange);
BufferedGraphicsContext context = new BufferedGraphicsContext();
BufferedGraphics buffer = context.Allocate(g, new Rectangle(0, 0, rect.Width + 20, rect.Height + 20));
buffer.Render(g);
print(image, e);
}
}
I expect to see orange rectangle on my screen, but it's black. I can't understand why this happen. Help me please :)
buffer.Render(g) renders the contents of the buffer to the graphics object. This means that the orange color is being overwritten by the empty buffer.
You'll have to choose between using BufferedGraphicsContext or creating a buffer yourself (the image).
The following would fix your issue using just the image:
...
Bitmap image = new Bitmap(rect.Width, rect.Height, pf);
using (Graphics g = Graphics.FromImage(image))
{
g.Clear(Color.Orange);
}
print(image, e);
You could also still use BufferedGraphicsContext, but you'd have to write the image to its Graphics property:
print(image, buffer.Graphics); // render your image to the buffer
buffer.Render(e.Graphics); // render the buffer to the paint event graphics
By the way, don't Dispose the graphics object provided by Form1_Paint (you currently do that in the print() method.
As a response to your comment, BufferedGraphicsContext seems to not support transparency when rendering it to the "main" graphics object, but you can draw transparent images to it correctly. The following example shows how the buffer is filled with a red color, and then a transparent image with a blue line is drawn to it:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (BufferedGraphicsContext context = new BufferedGraphicsContext())
using (BufferedGraphics buffer = context.Allocate(e.Graphics, new Rectangle(0, 0, 120, 120)))
{
// Create a bitmap with just a blue line on it
Bitmap bmp = new Bitmap(100, 100, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawLine(Pens.Blue, 0, 0, 100, 100);
}
// Fill a red square
buffer.Graphics.FillRectangle(Brushes.Red, 5, 5, 110, 110);
// Draw the blue-line image over the red square area
buffer.Graphics.DrawImage(bmp, 10, 10);
// Render the buffer to the underlying graphics
buffer.Render(e.Graphics);
}
}
In the result you can clearly see the blue line from the image over the red color in the background buffer (the red background is not overwritten) and there's a black border around the red rectangle where no background pixels where drawn.
Related
I need to save picturebox loaded png file with picturebox backgroud colour.
I've try with these.
But result is showing as a blank image.
help me..
private void bunifuThinButton24_Click(object sender, EventArgs e)
{
Bitmap bmp1 = new Bitmap(pictureBox1.Width, pictureBox1.Height, pictureBox1.CreateGraphics());
bmp1.Save(#"C:\Users\...\New folder4\ xx.jpg");
}
Bitmap bmp1 = new Bitmap(pictureBox1.Width, pictureBox1.Height, pictureBox1.CreateGraphics()); creates a new blank bitmap image with the resolution of pictureBox1's graphics object. you need to draw your picturebox in this bitmap. You can do this using the picturebox's DrawToBitmap function.
void bunifuThinButton24_Click(object sender, EventArgs e)
{
Bitmap bmp1 = new Bitmap(pictureBox1.Width, pictureBox1.Height, pictureBox1.CreateGraphics());
// fill in bitmap with the picturebox's backcolor
using (Graphics g = Graphics.FromImage(bmp1))
{
using (Brush drawBrush = new SolidBrush(pictureBox1.BackColor))
{
g.FillRectangle(drawBrush, new Rectangle(0, 0, bmp1.Width, bmp1.Height));
}
}
// draw picturebox on bitmap
pictureBox1.DrawToBitmap(bmp1, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
bmp1.Save(#"C:\Users\...\New folder4\ xx.jpg");
}
There is only one picturebox in my form and I want to drawcircle with a method on this picturebox but I cant do that and not working.The method is:
private Bitmap Circle()
{
Bitmap bmp;
Graphics gfx;
SolidBrush firca_dis=new SolidBrush(Color.FromArgb(192,0,192));
bmp = new Bitmap(40, 40);
gfx = Graphics.FromImage(bmp);
gfx.FillRectangle(firca_dis, 0, 0, 40, 40);
return bmp;
}
Picturebox
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
Graphics gfx= Graphics.FromImage(Circle());
gfx=e.Graphics;
}
You need to decide what you want to do:
Draw into the Image or
draw onto the Control?
Your code is a mix of both, which is why it doesn't work.
Here is how to draw onto the Control:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawEllipse(Pens.Red, new Rectangle(3, 4, 44, 44));
..
}
Here is how to draw into the Image of the PictureBox:
void drawIntoImage()
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
G.DrawEllipse(Pens.Orange, new Rectangle(13, 14, 44, 44));
..
}
// when done with all drawing you can enforce the display update by calling:
pictureBox1.Refresh();
}
Both ways to draw are persistent. The latter changes to pixels of the Image, the former doesn't.
So if the pixels are drawn into the Image and you zoom, stretch or shift the Image the pixel will go with it. Pixels drawn onto the Top of the PictureBox control won't do that!
Of course for both ways to draw, you can alter all the usual parts like the drawing command, maybe add a FillEllipse before the DrawEllipse, the Pens and Brushes with their Brush type and Colors and the dimensions.
private static void DrawCircle(Graphics gfx)
{
SolidBrush firca_dis = new SolidBrush(Color.FromArgb(192, 0, 192));
Rectangle rec = new Rectangle(0, 0, 40, 40); //Size and location of the Circle
gfx.FillEllipse(firca_dis, rec); //Draw a Circle and fill it
gfx.DrawEllipse(new Pen(firca_dis), rec); //draw a the border of the cicle your choice
}
I am trying to figure out which color the Pixel has which I drew before in red.
So as I read its not possible to do that directly, transformed my Graphics object to a Bitmap, which has the function GetPIxel and same width/height as my graphics object. Otherwise i think it would not function.
But it always returns me: Color [A=0, R=0, G=0, B=0]
Which i guess means White.
Here is my Code:
namespace GDi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(400, 400);
this.Text = "Display At Startup";
this.BackColor = Color.White;
}
private void Form1_Load(object sender, EventArgs e)
{
Graphics dc = this.CreateGraphics();
this.Show();
Pen BluePen = new Pen(Color.Blue, 3);
dc.DrawRectangle(BluePen, 0, 0, 50, 50);
Pen RedPen = new Pen(Color.Red, 2);
dc.DrawEllipse(RedPen, 20, 70, 80, 0);
dc.DrawEllipse(RedPen, 2, 88, 300, 0);
Bitmap myBitmap = new Bitmap(400, 400, dc);
string test = myBitmap.GetPixel(2, 88).ToString();
MessageBox.Show(test);
}
}
}
Any idea why it doesent works?
It doesn't work because the Bitmap constructor simply creates a new empty bitmap with no relation to your previous drawing.
You should probably use a different approach:
Create a Bitmap object like you've done
Create a Graphics object to draw in this bitmap using Graphics.FromImage method
Draw into this new Graphics
When needed, read the pixel color you need from your bitmap
When the drawing is done, copy the bitmap to the form
Dispose your new Graphics and Bitmap objects. Alternatively, you may hold the Bitmap for a long time, but Graphics should better be created on each redraw.
There is only one picturebox in my form and I want to drawcircle with a method on this picturebox but I cant do that and not working.The method is:
private Bitmap Circle()
{
Bitmap bmp;
Graphics gfx;
SolidBrush firca_dis=new SolidBrush(Color.FromArgb(192,0,192));
bmp = new Bitmap(40, 40);
gfx = Graphics.FromImage(bmp);
gfx.FillRectangle(firca_dis, 0, 0, 40, 40);
return bmp;
}
Picturebox
private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
Graphics gfx= Graphics.FromImage(Circle());
gfx=e.Graphics;
}
You need to decide what you want to do:
Draw into the Image or
draw onto the Control?
Your code is a mix of both, which is why it doesn't work.
Here is how to draw onto the Control:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawEllipse(Pens.Red, new Rectangle(3, 4, 44, 44));
..
}
Here is how to draw into the Image of the PictureBox:
void drawIntoImage()
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
G.DrawEllipse(Pens.Orange, new Rectangle(13, 14, 44, 44));
..
}
// when done with all drawing you can enforce the display update by calling:
pictureBox1.Refresh();
}
Both ways to draw are persistent. The latter changes to pixels of the Image, the former doesn't.
So if the pixels are drawn into the Image and you zoom, stretch or shift the Image the pixel will go with it. Pixels drawn onto the Top of the PictureBox control won't do that!
Of course for both ways to draw, you can alter all the usual parts like the drawing command, maybe add a FillEllipse before the DrawEllipse, the Pens and Brushes with their Brush type and Colors and the dimensions.
private static void DrawCircle(Graphics gfx)
{
SolidBrush firca_dis = new SolidBrush(Color.FromArgb(192, 0, 192));
Rectangle rec = new Rectangle(0, 0, 40, 40); //Size and location of the Circle
gfx.FillEllipse(firca_dis, rec); //Draw a Circle and fill it
gfx.DrawEllipse(new Pen(firca_dis), rec); //draw a the border of the cicle your choice
}
i have one picture showing of the human body and i want to use shapes to locate the injuries of the patient. all the shapes will shows off when the user click button. right now im testing with only one shape.
here is my code.
private void button7_Click_4(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
Image img = Image.FromFile("C:\\Users\\HDAdmin\\Pictures\\humanbody\\effect2.png");
g.DrawImage(img, 0, 0, img.Height, img.Width);
g.Dispose();
}
right now, the shape appear at the back of the image. so how i want to make the shape appear in front of the picture?
Couple of issues.
1) Painting should happen in a paint event. Do not use CreateGraphics since that will only be a temporary drawing.
2) Your DrawImage width and height arguments are reversed.
3) It doesn't look like you are painting the PictureBox control that you have on the form:
private Image img;
public Form1() {
InitializeComponent();
button1.Click += button1_Click;
pictureBox1.Paint += pictureBox1_Paint;
}
void button1_Click(object sender, EventArgs e) {
img = = Image.FromFile("C:\\Users\\HDAdmin\\Pictures\\humanbody\\effect2.png");
pictureBox1.Invalidate();
}
void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(pictureBox1.BackColor);
if (img != null) {
e.Graphics.DrawImage(img, 0, 0, img.Width, img.Height);
//Draw test shape:
e.Graphics.DrawRectangle(Pens.Red, new Rectangle(10, 10, 20, 60));
}
}
I think you should first get graphics of human image and then draw shape image on it. Some thing like that :
Image img = Image.FromFile("C:\\Users\\HDAdmin\\Pictures\\humanbody\\effect2.png");
Graphics g = Graphics.FromImage ( img );
g.DrawImage(ShapeImage, 0, 0, 30, 30); // you can set your required x,y,width,height