How to multiple cut one picture in c#? - c#

I want to multiple cut one picture in c# code.the following image is my c # forum and I can select an area and cut it.
I want to multiple cut one picture in c# code
I want to repeat this process
private void btnKes_Click(object sender, EventArgs e)
{
int tiklanma = 0;
if (true)
{
tiklanma++;
}
pictureBox2.Refresh();
pictureBox2.Refresh();
Bitmap sourceBitmap = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
Graphics g = pictureBox2.CreateGraphics();
int x1, x2, y1, y2;
Int32.TryParse(txtX1.Text, out x1);
Int32.TryParse(txtX2.Text, out x2);
Int32.TryParse(txtY1.Text, out y1);
Int32.TryParse(txtY2.Text, out y2);
if ((x1 < x2 && y1 < y2))
{
rectCropArea = new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
else if (x2 < x1 && y2 > y1)
{
rectCropArea = new Rectangle(x2, y1, x1 - x2, y2 - y1);
}
else if (x2 > x1 && y2 < y1)
{
rectCropArea = new Rectangle(x1, y2, x2 - x1, y1 - y2);
}
else
{
rectCropArea = new Rectangle(x2, y2, x1 - x2, y1 - y2);
}
pictureBox1.Refresh(); // This repositions the dashed box to new location as per coordinates entered.
int sayac = 40;
for (int i = 0; i < tiklanma; i++)
{
PictureBox pcBx = new PictureBox();
Size size = new Size(100, 100);
pcBx.Location();
pcBx.Size = size;
g.DrawImage(sourceBitmap, new Rectangle(0, 0, rectCropArea.Width, rectCropArea.Height), rectCropArea, GraphicsUnit.Pixel);
}
sourceBitmap.Dispose();
}
I want to select the fields more than once in the second picture and save the fields. How can I do this?

Use a FlowLayoutPanel, and every time you draw a new segment on the main image add a new PictureBox control to the layout panel.
Eventually you'll want to do other things with these picture segments, and so I also recommend immediately going a for a custom/user control here that includes a PictureBox as one part. That will make it much easier later to use buttons or context with each picture.
The specifics for all of this are out of scope for this type of question. We'd need to see more of your code to be able to use appropriate context with our answer, and the results are more than can fit well in the simple Q&A format. So go, try what you can, and then come back and ask new questions when you run into more specific problems.

Related

Recursively draw rectangles in WinForms

I'm currently coding a Sierpinski Carpet. Now i have the problen, that it works per iteration only once and not at every square on my whole screen.
This is the code i use:
private void Carpet(Graphics g, SolidBrush brush, Single
x, Single y, Single width, Single height, int iteration)
{
if (iteration == 0) {}
else
{
for (int i = 0; i < iteration + 1; i++)
{
width = Convert.ToSingle(Width / Math.Pow(3,i-1));
height = Convert.ToSingle(Height / Math.Pow(3, i-1));
Single x1 = x + width/3;
Single x2 = x1 + width;
Single x3 = x2 + width;
Single y1 = y + height/3;
Single y2 = y1 + height;
Single y3 = y2 + height;
g.FillRectangle(brush, x1, y1, width / 3, height / 3);
g.FillRectangle(brush, x1, y2, width / 3, height / 3);
g.FillRectangle(brush, x1, y3, width / 3, height / 3);
g.FillRectangle(brush, x2, y1, width / 3, height / 3);
g.FillRectangle(brush, x2, y3, width / 3, height / 3);
g.FillRectangle(brush, x3, y1, width / 3, height / 3);
g.FillRectangle(brush, x3, y2, width / 3, height / 3);
g.FillRectangle(brush, x3, y3, width / 3, height / 3);
}
}
}
How can i enhance my code, so it recursively draws Rectangles everywhere and not just on the first part of my Screen.
You draw only the smallest rectangles and nothing else. But to find the position of all of them you have to have a recursive function. So, determine coordinates and call itself recursively in all iterations except the last one. If it's the last iteration then draw just one rectangle that fills the whole area given with (x, y, width, height).
Instead of the for loop you have to have eight recursive calls. And in case of the last iteration you call only one g.FillRectangle. But now the problem is how to determine which iteration is the last one? When you call Carpet recursively call it with iteration - 1, and the last iteration is then the one with value zero.

Random Walker loop issue for C#

I am working on a simple Random Walker program that should draw a 10p long line, then choose a random cardinal direction to draw another line (also 10p long) until a certain number of lines have been reached.
I am using four coordinates to draw the line (two coordinates for X and two for Y). The Y coordinates are pushed into a Stack after every line is drawn and they are popped out as the X coordinates. This should ensure that the starting point of every second line is the end-point of the previous line.
The program draws on a Windows Form after pushing a Button controller. As of now, the output is something like this:
This here is my event handler code block for the button:
// Graphics and Pen classes instantiated
Graphics graphics;
graphics = this.CreateGraphics();
Pen pen = new Pen(Color.Black);
pen.Width = 1;
// lineLength is 10 pixels
// gridLength and gridWidth are needed to keep the Random Path inside a 600×600 field (this is not yet implemented in the code)
// lineCount is for maximizing the number of lines to be drawn and to control the loop
int lineLength = 10;
int gridWidth = 600;
int gridLength = 600;
int lineCount = 0;
// Starting line drawn with the following coordinates:
int x1 = 20;
int x2 = 20;
int y1 = 20;
int y2 = 30;
graphics.DrawLine(pen, x1, y1, x2, y2);
lineCount++;
// Stack initialized to store "y" coordinates
// "y" coordinates should be passed on as "x" coordinates for every consecutive lines
// so that the ending point's coordinate of a line
Stack<int> stackY = new Stack<int>();
stackY.Push(y2);
stackY.Push(y1);
for (lineCount = 1; lineCount <= 64; lineCount++)
{
// X pops current Y coordinates from stack
x1 = stackY.Pop();
x2 = stackY.Pop();
// Initializing the random number (between 1 and 4) generator to choose from the cardinal directions
Random rnd = new Random();
int dir = rnd.Next(1, 5);
switch (dir)
{
// up
case 1:
y1 = y1 + lineLength; // y1 plus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2); //drawing the line
stackY.Push(y2); // pushing the current y coordinates into the stack
stackY.Push(y1);
break;
// right
case 2:
y1 = y2 + lineLength; // y2 plus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2);
stackY.Push(y2);
stackY.Push(y1);
break;
// down
case 3:
y1 = y1 - lineLength; // y1 minus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2);
stackY.Push(y2);
stackY.Push(y1);
break;
// left
case 4:
y2 = y2 - lineLength; // y2 minus lineLength
graphics.DrawLine(pen, x1, y1, x2, y2);
stackY.Push(y2);
stackY.Push(y1);
break;
} //switch
} //for
} //event handler
I am not really sure what went wrong - I appreciate any heads-up and advices! Thank you!
You are making this far more complicated than you need to. Also you are mixing the x and y coordinates in a way that doesn't make sense.
You don't need a stack, just store the most recent points. Something like this.
int x = 20, y = 20;
int new_x = x, new_y = y;
Random rnd = new Random();
for (int i = 0; i < numLines; i++)
{
int dir = rnd.Next(1, 5);
if (dir == 1) new_x += lineLength;
if (dir == 2) new_x -= lineLength;
if (dir == 3) new_y += lineLength;
if (dir == 4) new_y -= lineLength;
graphics.DrawLine(pen, x, y, new_x, new_y);
x = new_x;
y = new_y;
}
Also you don't need to redeclare the Random object every time, just once before the loop.

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

Zooming in on quadratic curve line in c#

I am relatively new to c# and i am trying to draw the quadratic curve with an X and Y graph to scale with. The i drew curve although appears at the upper left corner of the screen which is very small and barely noticeable. Is there possible way to enlarge my curve line and align it to the middle so it can be shown properly?
protected override void OnPaint(PaintEventArgs e)
{
float a = 1, b = -3, c = -4;
double x1, x2, x3, y1, y2, y3, delta;
delta = (b * b) - (4 * a * c);
x1 = ((b * (-1)) + Math.Sqrt(delta)) / (2 * a);
y1 = a * (x1 * x1) + b * (x1) + c;
x2 = x1 + 1;
y2 = a * (x2 * x2) + b * (x2) + c;
x3 = x1 - 3;
y3 = a * (x3 * x3) + b * (x3) + c;
int cx1 = Convert.ToInt32(x1);
int cx2 = Convert.ToInt32(x2);
int cx3 = Convert.ToInt32(x3);
int cy1 = Convert.ToInt32(y1);
int cy2 = Convert.ToInt32(y2);
int cy3 = Convert.ToInt32(y3);
Graphics g = e.Graphics;
Pen aPen = new Pen(Color.Blue, 1);
Point point1 = new Point(cx1, cy1);
Point point2 = new Point(cx2, cy2);
Point point3 = new Point(cx3, cy3);
Point[] Points = { point1, point2, point3 };
g.DrawCurve(aPen, Points);
Yes it is possible and even rather simple to both move (Translate) and enlarge (Scale) the Graphics results by using Graphics.TranslateTransform and Matrix and Graphics.MultiplyTransform:
using System.Drawing.Drawing2D;
//..
int deltaX = 100;
int deltaY = 100;
g.TranslateTransform(deltaX, deltaY);
float factor = 2.5f;
Matrix m = new Matrix();
m.Scale(factor, factor);
g.MultiplyTransform(m);
Note that the scaling works like a lens and will enlarge the pixels. So you may want to scale down the Pen.Width when you scale up the Graphics..
Using one before..
g.DrawEllipse(Pens.Blue, 11, 11, 55, 55);
..and two after the transformations..
g.DrawEllipse(Pens.Red, 11, 11, 55, 55);
using (Pen pen = new Pen(Color.Green, 1/factor))
g.DrawEllipse(pen, 11, 11, 44, 44);
..these calls result in this image:
(I have changed the green circle's radius to avoid complete overlaying..)
It will be up to you to find the desired numbers for the moving and scaling; this will probably involve finding the minimum and maximum values for points involved..
I would suggest that you look into Microsoft Chart controls, it has a lots of interesting features regarding how to do this kind of curves with the ability to parameterize them.
A link to a more recent version of it: here

Blending/smooth-shading material

I'm creating and drawing a triangle mesh in wpf c# using GeometryModel3D. I've been trying to figure out how to create a smooth shading over the triangles, like the classic openGL smooth shaded triangle.
I would like to define a colour for each vertex, and then having the colours interpolated over the face, like this, assuming the three colour where red, green and blue.
I assumed I would need to use a brush, but I haven't been able to figure out how.
So any help would be appreciated, or any pointer to a guide that shows me how to achieve this.
EDIT:
I've looked at Triangular Gradient in WPF3D, which seems to answer the question partly, just using xaml.
Unfortunatly it seems like it need equilateral triangles.
2nd EDIT
The answer above, uses the RadialGradientBrush. Is the RadiusXand RadiusY used to make it elliptic instead of circular?
3rd EDIT
Okay, I'm fairly sure I can use the RadialGradientBrush. What I think I can do is, find the center of the circumcircle of the triangles, and create a RadialGradientBrush with RadiusX and RadiusY equal to the radius if the circumcircle. I would then move the focal point of the RadialGradientBrush to the vertices with GradientOrigin.
GradientOrigin takes two doubles X,Y as the center, with both of them being in the interval [0,1]. From what I can read is X = 0.0 is the left side and X = 1.0 is the right side and Y = 0.0 is the top and Y = 1.0 is the bottom. What I can't figure out, is this mapping [0,1]x[0,1] to a circle, or is it a square? The mapping from the vertices of the triangle to [0,1]x[0,1], depends on what shape this interval represents.
Have you heard of Helix 3D Toolkit for WPF ?
I didn't go as far as you'd like but I guess it is possible by looking at the Surface Demo example :
There are surely libraries for that, but to give some simple way, searching through some google,http://www.geeksforgeeks.org/check-whether-a-given-point-lies-inside-a-triangle-or-not/
computing the distance from corners, gives info about the smooth color. Checking if point is in triangle.
float area(int x1, int y1, int x2, int y2, int x3, int y3)
{
return (float)Math.Abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) / 2.0);
}
bool isInside(int x1, int y1, int x2, int y2, int x3, int y3, int x, int y)
{
/* Calculate area of triangle ABC */
float A = area(x1, y1, x2, y2, x3, y3);
/* Calculate area of triangle PBC */
float A1 = area(x, y, x2, y2, x3, y3);
/* Calculate area of triangle PAC */
float A2 = area(x1, y1, x, y, x3, y3);
/* Calculate area of triangle PAB */
float A3 = area(x1, y1, x2, y2, x, y);
/* Check if sum of A1, A2 and A3 is same as A */
return (A == A1 + A2 + A3);
}
for (int ii = 5; ii < 100; ii++)
{
for (int jj = 5; jj < 100; jj++)
{
int distanceRed =0, distanceGreen =0,distanceBlue =0;
if (isInside(30, 50, 30, 90, 20, 70, ii, jj))
{
distanceRed = (int)Math.Sqrt(((ii - 30) * (ii - 30) + (jj - 50) * (jj - 50)));
distanceGreen = (int)Math.Sqrt(((ii - 30) * (ii - 30) + (jj - 90) * (jj - 90)));
distanceBlue = (int)Math.Sqrt(((ii - 20) * (ii - 20) + (jj - 70) * (jj - 70)));
}
else
{
distanceRed = 0; distanceGreen = 0; distanceBlue = 0;
}
ptr[(((int)jj) * 3) + ((int)ii) * stride] = (byte)(distanceRed % 256);
ptr[(((int)jj) * 3) + ((int)ii) * stride + 1] = (byte)(distanceGreen % 256);
ptr[(((int)jj) * 3) + ((int)ii) * stride + 2] = (byte)(distanceBlue % 256);
}
}
gives the result:
Couldnt fit the red. Maybe the modulo is wrong here.
Also the sqrt is inefficient.

Categories