System.Drawing DrawLines - c#

xPanel.Save(ms, System.Drawing.Imaging.ImageFormat.Png); should save in Memory stream, ms, each line that is drawn showing 9 ellipses. Is below there is no output png just a objGraphicPanel.FillRectangle screen.
Missing is the "F" in PointF x1, y1, x2 and y2 are single floats.
protected void Page_Load(object sender, EventArgs e)
{
...
using (Bitmap xPanel = new Bitmap(500, 500))
{
using (Graphics objGraphicPanel = Graphics.FromImage(xPanel))
{
//Background White
SolidBrush whiteBrush = new SolidBrush(Color.White);
objGraphicPanel.FillRectangle(whiteBrush, 0, 0, 200, 200);
Pen colorPen = new Pen(Color.Black, 2);
MemoryStream ms = new MemoryStream();
for (k = 1; k <= 9; k++)
{
for (int nn = 2; nn <= n; nn++)
{
float x1 = Convert.ToSingle(XYecl[k, nn - 1]);
float y1 = Convert.ToSingle(ZYecl[k, nn - 1]);
float x2 = Convert.ToSingle(XYecl[k, nn]);
float y2 = Convert.ToSingle(ZYecl[k, nn]);
PointF[] ptf =
{
new PointF(x1, y1),
new PointF(x2, y2)
};
objGraphicPanel.DrawLines(colorPen, ptf);
xPanel.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
}
}
string Imgbase64 = Convert.ToBase64String(ms.ToArray());
MyImage.Src = "data:image/png;base64," + Imgbase64;
objGraphicPanel.Dispose();
}
xPanel.Dispose();
}
<img ID="MyImage" runat="server" />

Related

System.Drawing DrawLines with Variables

In System.Drawing there is a command called DrawLines.
https://msdn.microsoft.com/en-us/library/83k7w0zx(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
I need arrays X and Y to be plotted as a PointF in "Single Format" but with a "F" at the end of each X and Y point.
protected void Page_Load(object sender, EventArgs e)
{
double[] X = new double[]{10,15,20,25,30};
double[] Y = new double[]{100,150,200,250,300};
using (Bitmap xPanel = new Bitmap(500, 500))
{
using (Graphics objGraphicPanel = Graphics.FromImage(xPanel))
{
for (int nn = 2; nn <= 5; nn++)
{
float x1 = Convert.ToSingle(X[nn - 1]);
float y1 = Convert.ToSingle(Y[nn - 1]);
float x2 = Convert.ToSingle(X[nn]);
float y2 = Convert.ToSingle(Y[nn]);
PointF[] ptf =
{
new PointF(x1, y1),
new PointF(x2, y2)
};
objGraphicPanel.DrawLines(colorPen, ptf);
xPanel.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
}
string Imgbase64 = Convert.ToBase64String(ms.ToArray());
MyImage.Src = "data:image/png;base64," + Imgbase64;
objGraphicPanel.Dispose();
}
xPanel.Dispose();
This does not work because it must be in the format:
PointF[] ptf =
{
new PointF(10.56F, 25.78654F),
new PointF(500.123456F, 234.567F)
};
PointF requires the "float single" format but I also need the "F" at the end of each array point to get the PointF and DrawLines to work.
How do I get that "F" after or the code equivalent?
This is only an example my arrays are much larger.
The place
PointF[] ptf =
{
new PointF(x1, y1),
new PointF(x2, y2)
};
is not a problem. PointF accepts only float arguments. When you put 'F' in the end of the number you just tell the compiller that your number is float (not double). In your code values x1, x2, y1, y2 are already float, because you define them as
float x1 = ...
float y1 = ...
The problem is, that you iterate your array from 2 to 5. In C# numeration in arrays is from 0 to N-1 (N is length of the array). So you should write
for (int nn = 1; nn < 5; nn++)
or, and this is better
for (int nn = 1; nn < X.Length; nn++)
Also you save your image at each iteration. I think
xPanel.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
should be outside the cycle for.
Also when you write
using (...)
{
...
}
you don't need to dispose the item you create inside the brackets ( and ). The dispose is called automatically in the end of the using operator.
So the lines
objGraphicPanel.Dispose();
and
xPanel.Dispose();
are redundant.
Also, it is not necessary to create array ptf for drawing a single line. You can use DrawLine method:
objGraphicPanel.DrawLine(colorPen, x1, y1, x2, y2);
So, the folowing code shoud work fine
protected void Page_Load(object sender, EventArgs e)
{
double[] X = new double[]{10,15,20,25,30};
double[] Y = new double[]{100,150,200,250,300};
using (Bitmap xPanel = new Bitmap(500, 500))
{
using (Graphics objGraphicPanel = Graphics.FromImage(xPanel))
{
for (int nn = 1; nn < X.Length; nn++)
{
float x1 = Convert.ToSingle(X[nn - 1]);
float y1 = Convert.ToSingle(Y[nn - 1]);
float x2 = Convert.ToSingle(X[nn]);
float y2 = Convert.ToSingle(Y[nn]);
objGraphicPanel.DrawLine(colorPen, x1, y1, x2, y2);
}
}
xPanel.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
}

How to use drawImage()

I'm having a problem using this function to divide an image into multiple pieces and moving them a little bit.
The problem is that in the result the height of the rectangles is different from the "node_height" variable.
here is a testing image: measure.jpg
and the result: measured.jpg
in this image I used "node_height = 100". It was supposed to cut all the circles.
the code:
private void button2_Click(object sender, EventArgs e)
{
bmp = new Bitmap(source.Width, source.Height);
bmp.SetResolution(source.HorizontalResolution, source.VerticalResolution);
int node_height = trackBar1.Value;
int shift = trackBar2.Value;
int image_width = bmp.Width;
int image_height = bmp.Height;
double division = image_height / node_height;
int nodes = Convert.ToInt32(division);
Graphics g = Graphics.FromImage(bmp);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
g.PageScale = 1;
g.PageUnit = GraphicsUnit.Pixel;
g.Clear(Color.Transparent);
for(var i = 0; i < nodes; i++) {
int new_shift = RandomNumber(0,shift);
int x = 0;
int y = node_height * i;
int w = image_width;
int h = node_height;
Rectangle source_rect = new Rectangle(x, y, w, h);
Rectangle dest_rect = new Rectangle(new_shift, y, w, h);
g.DrawImage(source, dest_rect, source_rect, GraphicsUnit.Pixel);
}
MessageBox.Show("Done!");
pictureBox1.Image = bmp;
}
I managed to solve it. I was getting equal numbers in random sequences. Here is a link to the solution in my case Problem in generating random number

Can't draw on a form that was created by the code

I have faced a new and strange issue , i want to draw a simple eclipse in a form that is being created in the code that is called IM. The code for drawing it is here :
System.Drawing.Graphics graphicsObj;
graphicsObj = IM.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Green, 5);
Rectangle myRectangle = new Rectangle(0, 0, 10, 10);
graphicsObj.DrawEllipse(myPen, myRectangle);
IM.Show();
This doesn't draw anything but when I change IM.CreateGraphics() to this.CreateGraphics() it draws it on the original form perfectly. what am I missing ?
The code for creating the form IM :
Form IM = new Form();
IM.FormBorderStyle = FormBorderStyle.FixedSingle;
IM.Width = 500;
IM.Height = 500;
Full code :
private void button5_Click(object sender, EventArgs e)
{
int maxx = 0, maxy = 0;
int minx = 1000000000, miny = 1000000000;
int[] xts = new int[1000];
int[] yts = new int[1000];
int[] xps = new int[1000];
int[] yps = new int[1000];
int countert = -1;
int counterp = -1;
Form IM = new Form();
IM.FormBorderStyle = FormBorderStyle.FixedSingle;
System.IO.StreamReader file1 =
new System.IO.StreamReader("./MainProgram/Target.txt");
while (file1.Peek() >= 0)
{
countert++;
string line = file1.ReadLine();
string[] words = line.Split();
xts[countert] = Convert.ToInt32(words[0]);
if (xts[countert] > maxx) maxx = xts[countert];
if (xts[countert] < minx) minx = xts[countert];
yts[countert] = Convert.ToInt32(words[1]);
if (yts[countert] > maxy) maxy = yts[countert];
if (yts[countert] < miny) miny = yts[countert];
}
System.IO.StreamReader file2 =
new System.IO.StreamReader("./MainProgram/Pagepos.txt");
while (file2.Peek() >= 0)
{
counterp++;
string line = file2.ReadLine();
string[] words = line.Split();
xps[counterp] = Convert.ToInt32(words[0]);
if (xps[counterp] > maxx) maxx = xps[counterp];
if (xps[counterp] < minx) minx = xps[counterp];
yps[counterp] = Convert.ToInt32(words[1]);
if (yps[counterp] > maxy) maxy = yps[counterp];
if (yps[counterp] < miny) miny = yps[counterp];
}
int sizex = maxx - minx;
int sizey = maxy - miny;
int meghyas=1;
while ((sizey / meghyas > 500) || (sizex / meghyas > 500))
{
meghyas++;
}
IM.Width = (int) (sizex/meghyas);
IM.Height = (int) (sizey/meghyas);
//Start Of drawing
IM.Show();
System.Drawing.Graphics graphicsObj;
graphicsObj = IM.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Green, 5);
Rectangle myRectangle = new Rectangle(0, 0, 10, 10);
graphicsObj.DrawEllipse(myPen, myRectangle);
}
You have to show form IM first:
Form IM = new Form();
IM.FormBorderStyle = FormBorderStyle.FixedSingle;
IM.Width = 500;
IM.Height = 500;
IM.Show();
System.Drawing.Graphics graphicsObj;
graphicsObj = IM.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Green, 5);
Rectangle myRectangle = new Rectangle(0, 0, 10, 10);
graphicsObj.DrawEllipse(myPen, myRectangle);

Draw wave file using picturebox

I want to know the error in the following code.I want to draw the values of array that contains wave file samples.in the form i put panel and inside it picturebox.
private void button1_Click(object sender, EventArgs e)
{
string ss = "test.wav";
double[] xxwav = prepare(ss);
int xmin = 300; int ymin = 250; int xmax = 1024; int ymax = 450;
int xpmin = 0; int xpmax = xxwav.Length; int ypmin = 32767; int ypmax = -32768;
double a = (double)((xmax - xmin)) /(double) (xpmax - xpmin);
double b = (double)(xpmin - (a * xmin));
double c = (double)((ymax - ymin) /(double) (ypmax - ypmin));
double d = (double)(ypmin - (c * ymin));
double xp1,yp1,xp2,yp2;
Pen redPen = new Pen(Color.Red, 1);
Bitmap bmp = new Bitmap(40000, 500);
Graphics g = Graphics.FromImage(bmp);
PointF p1;
PointF p2;
for (int i = 1; i < xxwav.Length; i++)
{
xp1 = a * (i-1) + b;
yp1 = c * xxwav[i-1] + d;
xp2=a * i + b;
yp2=c * xxwav[i] + d;
p1 =new PointF ((float)xp1,(float)yp1);
p2 =new PointF ((float)xp2,(float)yp2);
g.DrawLine(redPen, p1, p2);
}
pictureBox1.Image = bmp;
MessageBox.Show("complete");
}
public static Double[] prepare(String wavePath)
{
Double[] data;
byte[] wave;
byte[] sR = new byte[4];
System.IO.FileStream WaveFile = System.IO.File.OpenRead(wavePath);
wave = new byte[WaveFile.Length];
data = new Double[(wave.Length - 44) / 4];//shifting the headers out of the PCM data;
WaveFile.Read(wave, 0, Convert.ToInt32(WaveFile.Length));//read the wave file into the wave variable
/***********Converting and PCM accounting***************/
for (int i = 0; i < data.Length; i++)
{
data[i] = BitConverter.ToInt16(wave, i * 2) / 32768.0;
}
//65536.0.0=2^n, n=bits per sample;
return data;
}
Your code worked for me only after I fiddled with your transformations and scaling parameters.
I have replaced your code with the scaling and transformation methods available in the System.Drawing namespace. This did gave me a view of one of my wav files. You only have to replace the private void button1_Click(object sender, EventArgs e) implementation.
var xxwav = prepare(wavFile);
// determine max and min
var max = (from v in xxwav
select v).Max();
var min = (from v in xxwav
select v).Min();
// what is our Y-axis scale
var mid = (max - min);
Pen redPen = new Pen(Color.Red, 1);
Bitmap bmp = new Bitmap(this.pictureBox1.Size.Width, this.pictureBox1.Size.Height);
Graphics g = Graphics.FromImage(bmp);
// x / y position (y-axis to the middle)
g.TranslateTransform(
0
, this.pictureBox1.Size.Height / 2);
// scaling according to picturebox size
g.ScaleTransform(
(float)this.pictureBox1.Size.Width / (float)xxwav.Length
, (float)this.pictureBox1.Size.Height / ((float)mid));
//first point
var prev = new PointF(0, (float)xxwav[0]);
// iterate over next points
for (int i = 1; i < xxwav.Length; i++)
{
var next = new PointF((float) i , (float) xxwav[i] );
g.DrawLine(redPen, prev, next);
prev = next;
}
pictureBox1.Image = bmp;

Getting cell co ordinates on Honeycomb pattern

I have to draw a honeycomb pattern and recognize each cell(row,column) on mousemove.
this is how i am generating the graph.
protected override void GenerateGridBitmap()
{
if (_circleGrid != null)
{
_circleGrid.Dispose();
_circleGrid = null;
}
Bitmap _texture = new Bitmap(circleSize, circleSize);
using (Graphics g = Graphics.FromImage(_texture))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
Rectangle r = new Rectangle(0, 0, circleSize, circleSize);
g.DrawEllipse(Pens.Black, r);
}
Bitmap rowBlock = new Bitmap(CanvasSize.Width - (circleSize/ 2), circleSize);
using (Brush b = new TextureBrush(_texture))
{
using (Graphics g = Graphics.FromImage(rowBlock))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.FillRectangle(b, new Rectangle(new Point(0, 0), rowBlock.Size));
}
}
//rowBlock.Save("rowblock.bmp");
_circleGrid = new Bitmap(CanvasSize.Width, CanvasSize.Height);
using (Graphics g = Graphics.FromImage(_circleGrid))
{
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
int x, y;
for (int i = 0; i < rows; i++)
{
x = 0;
if (i % 2 != 0)
x = (circleSize/ 2);
y = (i * circleSize);
if (i != 0)
{
y -= (VERTICAL_PIXEL_OFFSET * i);
}
g.DrawImage(rowBlock, x, y);
//g.DrawImage(DrawCodedCrystal(i,rowBlock), x, y);
Console.WriteLine(i);
}
}
_circleGrid.Save("grid.bmp");
Console.WriteLine(_circleGrid.Size);
_texture.Dispose();
_texture = null;
rowBlock.Dispose();
rowBlock = null;
}
and this what i am doing to get the coordinates of the graph. but the problem is i am able to get the column perfectly. but for the row i think there is a small difference in calculation. for eg. on the 99 row, for the (1/4) circle it say {row 98} and for the remaining circle it says {row 99}. the deviation increases as the number of rows increases.
protected override CanvasCell GetCanvasCellAt(int x, int y)
{
Rectangle rect = GetImageViewPort();
Point pt = new Point(x, y);
CanvasCell c = new CanvasCell() { Row = -1, Column = -1 };
if (rect.Contains(pt))
{
double zoomedCircleSize = CircleSize * ZoomFactor;
Point p = pt;// PointToClient(new Point(x, y));
p.X -= (int)(rect.X + (AutoScrollPosition.X) );
p.Y -= (int)(rect.Y + (AutoScrollPosition.Y));
int row = (int)((p.Y) / (zoomedCircleSize));
//row = (int)((p.Y + (row * ZoomFactor)) / zoomedCircleSize);
int col;
if (row % 2 != 0)
{
if (p.X >= 0 && p.X < (zoomedCircleSize / 2))
{
col = -1;
}
else
col = (int)((p.X - (zoomedCircleSize / 2)) / zoomedCircleSize);
}
else
{
if (p.X > (zoomedCircleSize * cols))
{
col = -1;
}
else
{
col = (int)((p.X) / zoomedCircleSize);
}
}
//if (!GetRectangle(row, col).ContainsWithInBoundingCircle(p))
//{
// c.Column = -1;
// c.Row = -1;
//}
//else
{
c.Column = col;
c.Row = row;
}
}
//
return c;
}
hope i was clear in explaining my problem.
EDIT:
the VERTICAL_PIXEL_OFFSET is 1 and the circle size is 16
I also posted this on msdn, Stefan Hoffmann was kind enough to post an SSCCE of how to do that. Basically the idea was to precalculate the honeycombs, as #usr suggested in the comments section.
Here is the link to MSDN post.
A quick observation: do you have to use circles - would hexagons simplify the problem?

Categories