How to center the drawn pie in the middle of the pictureBox? - c#

for now i did it all manually , i set the variable Point myPieLocation location and the Size myPieSize variable and i added 3 lines for helping to see the middle point.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Doppler_Radar
{
public partial class Form1 : Form
{
int myPiePercent = 15;
public Form1()
{
InitializeComponent();
pictureBox1.Image = Image.FromFile(#"D:\New folder (4)\Weather Radar\WithClouds.bmp");
timer1.Enabled = true;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawRectangle(Pens.Green, 0, 0, pictureBox1.Width - 1, pictureBox1.Height - 1);
Pen p = new Pen(Color.Red);
e.Graphics.DrawLine(p, 256, 0, 256, 512);
e.Graphics.DrawLine(p, 0, 256, 512, 256);
DrawPieOnPicturebox(e.Graphics);
}
public void DrawPieOnPicturebox(Graphics myPieGraphic)
{
Color myPieColors = Color.FromArgb(150, Color.LightGreen);
Point myPieLocation = new Point(180, 180);
Size myPieSize = new Size(150, 150);
DrawMyPie(myPiePercent, myPieColors, myPieGraphic, myPieLocation, myPieSize);
}
public void DrawMyPie(int myPiePerecent, Color myPieColor, Graphics myPieGraphic, Point
myPieLocation, Size myPieSize)
{
using (SolidBrush brush = new SolidBrush(myPieColor))
{
myPieGraphic.FillPie(brush, new Rectangle(myPieLocation, myPieSize), Convert.ToSingle(myPiePerecent * 360 / 100), Convert.ToSingle(15 * 360 / 100));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
myPiePercent++;
pictureBox1.Invalidate();
}
}
}
The result is the pie is in the middle of the picturebox :
but if for example i change the pie size to 200,200 now the pie is not in the middle :
Size myPieSize = new Size(200, 200);
what i want to do is that no matter if i change the size of the pie keep the pie to be drawn in the middle of the pictureBox.
i tried instead 180, 108
Point myPieLocation = new Point(180, 180);
also
Point myPieLocation = new Point(pictureBox1.Width / 2,
pictureBox1.Height / 2);
but it's far away from the pictureBox1 middle :
i tried also clientsize and size in the myPieLocation but it's never in the middle.

Related

DrawImage drawing Incorrect for scaled image

I am capturing desktop screen and drawing on picturebox.
Below is a sample code for testing.Basically i am updating small portion of images on picture box coming from socket. so for performance prospective i am not invalidate whole image always, instead of just invalidate area which need to repaint considering scaling.
On paint event using below DrawImage overload to draw only specific region of picture box
if you try to run below code it not drawing properly.
Text areas are not readable.What is wrong i am doing here.I search extensively but did not got any solution.
Here is my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
private Bitmap initial = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
private Rectangle GetViewRect() { return pictureBox1.ClientRectangle; }
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
initial = CaptureDesktop();
Rectangle imageRect = new Rectangle(0, 0, initial.Width, initial.Height);
var viewRect = GetViewRect();
var scaleX = (float)viewRect.Width / initial.Width;
var scaleY = (float)viewRect.Height / initial.Height;
// Make sure the target rectangle includes the new block
var targetRect = Rectangle.FromLTRB(
(int)Math.Truncate(imageRect.X * scaleX),
(int)Math.Truncate(imageRect.Y * scaleY),
(int)Math.Ceiling(imageRect.Right * scaleX),
(int)Math.Ceiling(imageRect.Bottom * scaleY));
pictureBox1.Invalidate(targetRect);
pictureBox1.Update();
}
private Bitmap CaptureDesktop()
{
var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height,
PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
// Take the screenshot from the upper left corner to the right bottom corner.
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y,
0,
0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
return bmpScreenshot;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
lock (initial)
{
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
var viewRect = GetViewRect();
var scaleX = (float)initial.Width / viewRect.Width;
var scaleY = (float)initial.Height / viewRect.Height;
var targetRect = e.ClipRectangle;
var imageRect = new RectangleF(targetRect.X * scaleX, targetRect.Y * scaleY, targetRect.Width * scaleX, targetRect.Height * scaleY);
e.Graphics.DrawImage(initial, targetRect, imageRect, GraphicsUnit.Pixel);
}
}
}
}
`
Edit : if i change to below code. it works fine.
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
e.Graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High
;

Scroll a stretched image

I have a picturebox in my c# windows forms application, and i've made some code so that I can alter the height and width of the picturebox, essentially zooming in. However, this only focuses on the top right area and I would like the user to be able to scroll the map to the area they need to using the scrollbar.
Whenever I zoom in, then use the scrollbar, my image goes to its default size, and then only scrolls in that size.
How can I move the entire image so that the user can pan the picturebox map?
Here's my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mapping_Application
{
public partial class Form1 : Form
{
//Declare zoom variable counter
int zoom;
//Main Void
public Form1()
{
InitializeComponent();
}
//Zoom In
private void button1_Click(object sender, EventArgs e)
{
if(zoom != 3)
{
pictureBox1.Height = pictureBox1.Height * 2;
pictureBox1.Width = pictureBox1.Width * 2;
zoom = zoom + 1;
}
}
//Zoom out
private void button2_Click(object sender, EventArgs e)
{
if (zoom != 0)
{
pictureBox1.Height = pictureBox1.Height / 2;
pictureBox1.Width = pictureBox1.Width / 2;
zoom = zoom -= 1;
}
}
//The horizontal scrollbar
private void horizontal_Scroll(object sender, ScrollEventArgs e)
{
//Create a graphics object and draw a portion of the image in the PictureBox.
Graphics g = pictureBox1.CreateGraphics();
int x;
int y;
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
x = e.NewValue * 19;
y = vertical.Value * 19;
}
else //e.ScrollOrientation == ScrollOrientation.VerticalScroll
{
y = e.NewValue * 19;
x = horizontal.Value * 19;
}
g.Clear(Color.White);
g.DrawImage(pictureBox1.Image,
new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Width), //where to draw the image
new Rectangle(x, y, pictureBox1.Width, pictureBox1.Width), //the portion of the image to draw
GraphicsUnit.Pixel);
pictureBox1.Update();
}
//The vertical scrollbar
private void vertical_Scroll(object sender, ScrollEventArgs e)
{
//Create a graphics object and draw a portion of the image in the PictureBox.
Graphics g = pictureBox1.CreateGraphics();
int x;
int y;
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
x = e.NewValue * 19;
y = vertical.Value * 19;
}
else //e.ScrollOrientation == ScrollOrientation.VerticalScroll
{
y = e.NewValue * 19;
x = horizontal.Value * 19;
}
g.Clear(Color.White);
g.DrawImage(pictureBox1.Image,
new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Width), //where to draw the image
new Rectangle(x, y, pictureBox1.Width, pictureBox1.Width), //the
portion of the image to draw
GraphicsUnit.Pixel);
pictureBox1.Update();
}
}
}
The scroll currently seems to work, but for no zoom in only. There is no zoom negative feature and i'm using a var named zoom to store which level zoom the program is at. Can't zoom to -2x , hence the if (zoom!=0)

Draw a border around an oval picturebox

I've an oval picturebox (Code below). I want to add a border around the picturebox. I allready tried to add a second rect but this only made my region smaller. Is there any way to make a border?
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class OvalPictureBox : PictureBox
{
public OvalPictureBox()
{
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
using (var gp = new GraphicsPath())
{
gp.AddEllipse(new Rectangle(0, 0, this.Width - 1, this.Height - 1));
this.Region = new Region(gp);
}
}
private void InitializeComponent()
{
((System.ComponentModel.ISupportInitialize)(this)).BeginInit();
this.SuspendLayout();
//
// OvalPictureBox
//
((System.ComponentModel.ISupportInitialize)(this)).EndInit();
this.ResumeLayout(false);
}
}
EDIT
I figured it out. I just draw an ellipse in the picturebox.
float penWidth = 5F;
Pen myPen = new Pen(Color.FromArgb(242, 141, 1), penWidth);
e.Graphics.DrawEllipse(myPen, new RectangleF(new PointF(0, 0), new
SizeF((float)(portraitPicture.Width - 1), portraitPicture.Height - 1)));
myPen.Dispose();
Is there a cleaner or better way? Or is this the best way?
Just draw ellipse that is bigger than the one you already have. But this ellipse should be drawn first, otherwise it would cover the other ellipse.
How much should it be bigger? Border width :)

Is it possible to get a scaled/translated graphics object?

I'm using WinForms to write a visualizer for a simulation. The visualization involves various objects moving around a grid.
So far, I'm using a custom control that extends Panel and doing the custom drawing with the Graphics class during Paint events. However, one irritation is that I'm constantly having to scale things from grid coordinates to the control.DisplayRectangle coordinates (in other words, an object that takes up 2 cells in the grid would take up 2 * (control.DisplayRectangle.Width / horizontalGridWidth) pixels when drawn).
I'm wondering, is there a way to get the Graphics object to do these translations for me so that I can express my drawing in grid coordinates and have it automatically be mapped to the physical coordinates?
It turns out that Matrix was indeed the key (see accepted answer). Here's the code that got it working:
public SimulationPanel() {
this.DoubleBuffered = true;
this.SizeChanged += (o, e) => this.Invalidate();
this.Paint += this.PaintPanel;
}
private void Paint(object sender, PaintEventArgs e) {
e.Graphics.Clear(Color.Black);
var fromRectangle = GetSimulationWorldCoordinates();
var toRectangle = ScaleToFit(fromRectangle, this.DisplayRectangle);
using (var matrix = new Matrix(
fromRectangle,
new[] {
toRectangle.Location,
new Point(toRectangle.Right, toRectangle.Top),
new Point(toRectangle.Left, toRectangle.Bottom),
}))
{
// draw the simulation stuff here using simulation coordinates
e.Graphics.Transform = matrix;
e.Graphics.FillRectangle(Brushes.LightBlue, toRectangle);
e.Graphics.DrawLine(Pens.Red, toRectangle.Location, new Point(toRectangle.Right, toRectangle.Bottom));
}
}
How about this code ?
I use Labels instead of grids because I cannot know your grids.
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
GraphicsPath path = new GraphicsPath();
RectangleF pathRect;
public Form1()
{
InitializeComponent();
Location = new Point(0, 0);
Size = new System.Drawing.Size(500, 500);
Label lbl1 = new Label();
lbl1.Location = new Point(100, 100);
lbl1.Size = new System.Drawing.Size(200, 100);
lbl1.BorderStyle = BorderStyle.FixedSingle;
lbl1.Paint += new PaintEventHandler(lbl_Paint);
Label lbl2 = new Label();
lbl2.Location = new Point(300, 200);
lbl2.Size = new System.Drawing.Size(100, 200);
lbl2.BorderStyle = BorderStyle.FixedSingle;
lbl2.Paint += new PaintEventHandler(lbl_Paint);
Controls.Add(lbl1);
Controls.Add(lbl2);
path.AddRectangle(new Rectangle(50, 50, 150, 150));
path.AddEllipse(new Rectangle(25, 50, 25, 50));
pathRect = path.GetBounds();
}
void lbl_Paint(object sender, PaintEventArgs e)
{
var rect = ((Control)sender).DisplayRectangle;
PointF[] plgpts = new PointF[] {
new PointF(rect.Left, rect.Top),
new PointF(rect.Right - 1, rect.Top),
new PointF(rect.Left, rect.Bottom - 1),
};
Graphics g = e.Graphics;
g.Clear(SystemColors.Control);
using (Matrix matrix = new Matrix(path.GetBounds(), plgpts))
{
g.Transform = matrix;
g.DrawPath(Pens.Red, path);
}
}
}
}

Resize image 2x2 pixels to say 4x4 pixels keeping colours the same

Please imagine I have a very simple chequerboard image.
Here I represent the image with letters as pixels: black pixel 'B', white pixel 'W'
Here is the starting 2x2 pixel image:
BW
WB
I want to resize the image, lets say by scale of 2x to give me :
BBWW
BBWW
WWBB
WWBB
or scale 4x
BBBBWWWW
BBBBWWWW
WWWWBBBB
WWWWBBBB
So that the pixel colours are not dithered in any way at all.
I have tried this in C# but the image is a mess, all dithered, I need to learn how to do this without dithering/color change.
Here is my code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
namespace PageTwine
{
public partial class RandonGiff : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// create 2x2 chequerboard:
Bitmap oBitmap = new Bitmap(2, 2);
Graphics oGraphic = Graphics.FromImage(oBitmap);
// color black pixels (i think the default is black but this helps to explain)
SolidBrush oBrush = new SolidBrush(Color.FromArgb(255, 255, 255));
oGraphic.FillRectangle(oBrush, 0, 0, 1, 1);
oGraphic.FillRectangle(oBrush, 1, 1, 1, 1);
//color white pixels
oBrush = new SolidBrush(Color.FromArgb(0, 0, 0));
oGraphic.FillRectangle(oBrush, 0, 1, 1, 1);
oGraphic.FillRectangle(oBrush, 1, 0, 1, 1);
// expand to 4x4
Bitmap result = new Bitmap(4, 4);
using (Graphics graphics = Graphics.FromImage(result))
{
// I don't know what these settings should be :
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
//draw the image into the target bitmap
graphics.DrawImage(oBitmap, 0, 0, result.Width, result.Height);
}
//send image directly to the browser
Response.ContentType = "image/gif";
result.Save(Response.OutputStream, ImageFormat.Gif);
}
}
}
The result is a dithered image, but I need a clean crisp chequerboard effect.
Please can you help me.
EDIT:07/02/12
Thanks for the suggestions so far but I am still searching without finding a solution.
I have created a demo page so you can see the results for yourself.
The URL for the demo is :
http://www.leansoftware.net/servicedesk/publicadhoc/randomgif.aspx?columns=3&rows=3
The demo will create a chequerboard with initial columns x rows as pixels, then enlarge to a gif image 300x300 px.
You will see that colours are distorted/bitty - this I am trying to solve.
Here is the source code for the demo:
using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Linq;
public partial class RandomGif : System.Web.UI.Page
{
public class Coordinates
{
public int x { get; set; }
public int y { get; set; }
}
static Random rand = new Random();
protected void Page_Load(object sender, EventArgs e)
{
// Output type gif
int iwidth;
int iheight;
int bits;
Response.ContentType = "image/gif";
// Get parameters
if (Request.QueryString["count"] != null)
{
bits = Convert.ToInt32(Request.QueryString["count"]);
int square = Convert.ToInt32(Math.Ceiling(Math.Sqrt(bits + Math.Floor(bits / 4.0))));
iwidth = square;
iheight = square;
bits = (square * square)-1;
}
else
if (Request.QueryString["rows"] != null && Request.QueryString["columns"] != null)
{
iwidth = Convert.ToInt32(Request.QueryString["columns"]);
iheight = Convert.ToInt32(Request.QueryString["rows"]);
bits = (iwidth * iheight);
}
else {
return;
}
if (bits > 1000){
Response.Write("Please specify a grid <= 1000 pixels");
return;
}
int plotCount = 0;
//web safe colors : 00, 33, 66, 99, CC, FF;
List<int> webSafeColor = new List<int>();
webSafeColor.Add(0); //00
webSafeColor.Add(51);//33
webSafeColor.Add(102);//66
webSafeColor.Add(153);//99
webSafeColor.Add(204);//CC
webSafeColor.Add(255);//FF
// Create a structure to hold all possible coordinates
var Grid = new List<Coordinates>();
for (int xi = 1; xi <= iwidth; xi++)
{
for (int yi = 1; yi <= iheight; yi++)
{
Grid.Add(new Coordinates { x = xi, y = yi });
plotCount++;
}
}
//create a new Bitmap object
Bitmap oBitmap = new Bitmap(iwidth, iheight);
//create a new Graphics object, which will allow us to draw on our bitmap:
Graphics oGraphic = Graphics.FromImage(oBitmap);
//fill the image rectangle with n bits
for (int i = 1; i <= bits; i++)
{
//Random rand = new Random();
int row = rand.Next(Grid.Count());
// random red
int ircolor = webSafeColor[rand.Next(5)];
// random green
int igcolor = webSafeColor[rand.Next(5)];
// random blue
int ibcolor = webSafeColor[rand.Next(5)];
Color randomColor = Color.FromArgb(ircolor, igcolor, ibcolor);
SolidBrush oBrush = new SolidBrush(randomColor);
oGraphic.FillRectangle(oBrush, Grid[row].x - 1, Grid[row].y - 1, 1, 1);
// Delete this coordinate#
Grid.Remove(Grid[row]);
}
// resize image
Bitmap result = new Bitmap(300, 300);
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.AssumeLinear;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
//draw the image into the target bitmap
graphics.DrawImage(oBitmap, 0, 0, result.Width, result.Height);
}
//send image directly to the browser
Response.ContentType = "image/gif";
result.Save(Response.OutputStream, ImageFormat.Gif);
}
}
If you can suggest modifications we can try them out and see if it fixes the problem.
Thanks Richard
This is a possible duplicate of c# Draw Image (Scaled) to Graphics, does not interpolate correctly. Fixes?
You need to add:
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
Alternately, you could use
graphics.DrawImage(oBitmap, 0, 0, result.Width * 2, result.Height * 2);
to achieve a similar effect of forcing the brush to fill without warping at the right-bottom image edges.
Update:
Adding link for creating indexed images with a custom color palette.
http://support.microsoft.com/kb/319061
Use:
System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;

Categories