Clone jpg without losing quality in C# - c#

Im trying to take an input from a webcam and only want the centre of the image (to passport size image).
I have a Picturebox with the webcam stream which I have set SizeMode to CentreImage. I then have a second picturebox which when I click the second picturebox i then need a cropped image i then save later (currently i get the whole original image when saving).
I have code to crop this image into the 2nd picturebox which works however it loses loads of quality. Is there a way to make this crop lossless?
private void pictureBox1_Click(object sender, EventArgs e)
{
//picPhoto.Image = pic.Image;
using (Bitmap bmp = new Bitmap(pic.Image))
{
var newImg = bmp.Clone(
new Rectangle { X = ((pic.Image.Width/2)-(350/2)), Y = ((pic.Image.Height / 2) - (450 / 2)), Width = 350, Height = 450 },
bmp.PixelFormat);
picPhoto.Image = newImg;
}
}

Related

Reveal portions of an image behind another image

I have a PictureBox where I display an image (Let's call it Image1). There's a second image (Image2) which needs to be revealed as the user hovers the Image1 with the mouse. I only need to reveal part of Image2 (a 10X10 pixel size box), not the whole image as the mouse moves.
Both images are BMP.
How can I accomplish this task? I would think using overlays?
I display the Image1 in the picturebox and then I load the Image2 in memory, now I just need to display the portions of the Image2 over Image1 as the mouse moves.
Thank you,
Here is an example:
public Form1()
{
InitializeComponent();
pictureBox1.Image = Bitmap.FromFile(your1stImage);
bmp = (Bitmap)Bitmap.FromFile(your2ndImage);
pb2.Parent = pictureBox1;
pb2.Size = new Size(10,10);
/* this is for fun only: It restricts the overlay to a circle:
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(pb2.ClientRectangle);
pb2.Region = new Region(gp);
*/
}
Bitmap bmp;
PictureBox pb2 = new PictureBox();
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
Rectangle rDest= pb2.ClientRectangle;
Point tLocation = new Point(e.Location.X - rDest.Width - 5,
e.Location.Y - rDest.Height - 5);
Rectangle rSrc= new Rectangle(tLocation, pb2.ClientSize);
using (Graphics G = pb2.CreateGraphics() )
{
G.DrawImage(bmp, rDest, rSrc, GraphicsUnit.Pixel);
}
pb2.Location = tLocation;
}
It uses offsets the overly to the top left of the Cursor adding a little for smooth movement..

drawing on image of a picturebox c#

Hello i am in problem with drawing in picturebox. I am trying to draw over a picturebox. picturebox contains an image.I draw a sine wave using drawline method. when the wave reaches the end of the width of picturebox then i use
g.Clear(pictureBox1.BackColor);
this clears the wave over the picturebox.But the problem is it also clears the image of the picturebox.I want draw a wave over a image and then clears it when it reaches the picturebox.width and again starts from the initial position. please help!
Graphics g;
g = pictureBox1.CreateGraphics();
g.DrawLine(System.Drawing.Pens.Crimson, ti, old_gval1, ti + trackBar1.Value, gval1);
usb.SpecifiedDevice.SendData(OUTBuffer);
old_gval1 = gval1;
ti = ti + trackBar1.Value;
if (ti > pictureBox1.Width) {
ti = 0;
g.Clear(pictureBox1.BackColor);
g.DrawLine(System.Drawing.Pens.Gray, 0, ((pictureBox1.Height - 1) - (gnd_val) * ((pictureBox1.Height - 10) / 1023f)), pictureBox1.Width, ((pictureBox1.Height - 1) - (gnd_val) * ((pictureBox1.Height - 10) / 1023f)));
g.DrawLine(System.Drawing.Pens.Gray, pictureBox1.Width / 2, 0, pictureBox1.Width/ 2,pictureBox1.Height);
}
You can use a special feature of the PictureBox:
It has not only the Image everybody is using but also a BackgroundImage usually overlooked.
You can paint freely on the Image and still keep a BackgroundImage untouched.
Obviosly you need to paint on a transparent Bitmap.
Here is some code:
// load the background image:
this.pictureBox1.BackgroundImage = new Bitmap(yourImageFileName);
// prepare the image:
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
using (Graphics g = Graphics.FromImage(bmp) )
{
g.FillRectangle(Brushes.Transparent, new Rectangle(Point.Empty, bmp.Size) );
}
pictureBox1.Image = bmp;
Now paint stuff:
Random R = new Random();
private void button1_Click(object sender, EventArgs e)
{
Image bmp = pictureBox2.Image;
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawEllipse(Pens.Blue, R.Next(33), R.Next(33), R.Next(500), R.Next(500));
g.DrawEllipse(Pens.Red, R.Next(33), R.Next(33), R.Next(500), R.Next(500));
g.DrawEllipse(Pens.White, R.Next(33), R.Next(33), R.Next(500), R.Next(500));
}
pictureBox2.Image = bmp;
}
When your plotting has reached the right edge you would use a call to FillRectangle(Brushes.Transparent,.. to clear the foreground image and reset your x value.
Sounds like the cheapest solution to your problem.
You have two options here.
You could create your graphics from the image using Graphics.FromImage, then assign the image from that to the picture box.
Draw the image into your new Graphics object using Graphics.DrawImage.
It sounds like the latter might be a bit more appropriate for you, since you aren't actually altering the in-memory image. So every time you clear the Graphics instance, just draw in the Image.

boundaries cut the image when rotated

I want to rotate an image in the picture box. Here is my code.
public static Bitmap RotateImage(Image image, PointF offset, float angle)
{
if (image == null)
{
throw new ArgumentNullException("image");
}
var rotatedBmp = new Bitmap(image.Width, image.Height);
rotatedBmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
var g = Graphics.FromImage(rotatedBmp);
g.TranslateTransform(offset.X, offset.Y);
g.RotateTransform(angle);
g.TranslateTransform(-offset.X, -offset.Y);
g.DrawImage(image, new PointF(0, 0));
return rotatedBmp;
}
private void button1_Click(object sender, EventArgs e)
{
Image image = new Bitmap(pictureBox1.Image);
pictureBox1.Image = (Bitmap)image.Clone();
var oldImage = pictureBox1.Image;
var p = new Point(image.Width / 2, image.Height);
pictureBox1.Image = null;
pictureBox1.Image = RotateImage(image, p, 1);
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
pictureBox1.Refresh();
if (oldImage != null)
{
oldImage.Dispose();
}
}
private void button2_Click(object sender, EventArgs e)
{
Image image = new Bitmap(pictureBox1.Image);
pictureBox1.Image = (Bitmap)image.Clone();
var oldImage = pictureBox1.Image;
var p = new Point(image.Width / 2, image.Height);
pictureBox1.Image = null;
pictureBox1.Image = RotateImage(image, p, -1);
pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
pictureBox1.Refresh();
if (oldImage != null)
{
oldImage.Dispose();
}
}
Now the problem is that when I rotate the image it gets cut. Here is the situation.
I have stretched the picture box and changed the colour of form just for clear picture.
My question is when I have used the statement
pictureBox1.Image = RotateImage(image, p, 1);
Then why is the picture not getting right after postion as this is the same statement used for any situation where we have to assign some image to groupbox. Why is not it working here? I have searched it before but the most of the searches seem irrelevant to me because they use filip function which rotate through 90,180,270. But I want to rotate by some degree maximum upto 10 degree.
Rotating Controls is not something supported by default (links talking about this: link1, link2). The reason why the picture gets cut is because, after the rotation, its width is bigger than the pictureBox1 one; thus a quick solution would be updating its size after the rotation:
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize; //Adapts the size automatically
or
pictureBox1.Width = image.Width;
pictureBox1.Height = image.Height;
This should be an acceptable solution (there has to be enough free space to account for the new dimensions of the image after being rotated anyway). The other option would be affecting the PictureBox control directly (by affecting the rectangle defining its boundaries, for example) what would be much more difficult.
Well i have come to know that win Forms are not meant for any transformations and rotations.Changing the mode to AutoSize does not make a difference. The best thing for rotation and transformation is WPF.
WPF has a good transformation classes which rotate and transform objects without affecting the object. The object does not get blurred.
You can use This for rotations and transformations.

Using Graphics to load an image and rotate it into a panel

I am trying to use the graphics object to load an image in and then rotate it (either portrait or landscape) and then display it in a panel (not a picture box).
How would I load the graphics in the panel? Also what would be the simplest way to do a landscape or portrait rotation on the graphics object?
GDI must be used to rotate and work with the image, I need a way to get the Graphics object into the panel.
Use the Paint event of the Panel:
private void panel1_Paint(object sender, PaintEventArgs e)
{
int angle = 90;
Graphics g = e.Graphics;
Image i = new Bitmap(#"C:\Jellyfish.jpg");
g.TranslateTransform((float)i.Width / 2, (float)i.Height / 2);
g.RotateTransform(angle);
g.TranslateTransform(-(float)i.Width / 2, -(float)i.Height / 2);
g.DrawImage(i, new Point(0,0));
}
Since you are talking about a panel and it's C#, I will guess you are referring to WinForms.
You can rotate any Image instance using the RotateFlip method, and you can use an Image as the BackgroundImage of your panel. A working example:
Bitmap bitmap = new Bitmap(#"D:\word.png");
bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
Form form = new Form() { Height = 400, Width = 600 };
Panel p = new Panel() { Height = 400, Width = 600, Left = 0, Top = 0};
form.Controls.Add(p);
p.BackgroundImage = bitmap;
form.Show();

Getting correct coordinates from scaled picture box with Zoom SizeMode

I loaded the jpg to picture box (in SizeMode as Zoom).
I drew a rectangle on the picture box and took the coordinate.
I opened the jpg in paint and observed the coordinate (where I drew the rectangle on the picture box).
When I compared the rectangle coordinates (x and y) with paint coordinates, they were not the same.
I changed the SizeMode to Normal and observed that the coordinates became the same, but the image size was too large so it was display partially, so I want to use Zoom SizeMode property.
Say image with size 2825x3538 and keep the picture box size mode as Normal, the image shows partially in picture box. So I changed picture box mode to Zoom (to fit the System screen resolution), and the coordinates missmatched when comparing it with Normal mode with SizeMode.
How can I achieve the same coordinates?
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFD.FileName = "";
OpenFD.Title = "open image";
OpenFD.InitialDirectory = "C";
OpenFD.Filter = "JPEG|*.jpg|Bmp|*.bmp|All Files|*.*.*";
if (OpenFD.ShowDialog() == DialogResult.OK)
{
file = OpenFD.FileName;
image = Image.FromFile(file);
pictureBox1.Image = image;
svc = Screen.PrimaryScreen;
pictureBox1.Width = svc.Bounds.Width;
pictureBox1.Height = svc.Bounds.Height - 100;
mybitmap1 = new Bitmap(pictureBox1.Image);
mybitmap1.SetResolution(300, 300);
pictureBox1.Image = mybitmap1;
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (mybitmap == null)
{
mybitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
mybitmap.SetResolution(300, 300);
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
using (g = Graphics.FromImage(mybitmap))
{
using (Pen pen = new Pen(Color.Green, m))
{
e.Graphics.DrawRectangle(pen, r);
e.Graphics.DrawString(lab[c].ToString(), new Font(lab[c].ToString(), 8F), new SolidBrush(label1.ForeColor), r);
}
}
}
You can use two scale factors between the actual image and the picture box, one with height and the other with width.

Categories

Resources