bmp Image Resizing and Fit to page in c# - c#

I have Image of width 1171 and height 1181. I need that image into print page using printDocument...So Final image size would be width 596 and height 892. So it covers all area of page without any space.
My problem is I am able to resize it but it does not cover the whole space of page...And with different solution it covers the whole page area but image cutted down.
So what I have to do for solving this issue?
My code as per below...
private void btnPrint_Click(object sender, EventArgs e)
{
btnPrint.Enabled = false;
try
{
printDocument1.Print();
this.Close();
}
catch (Exception err)
{
MessageBox.Show("Printing failed :" + err.Message);
btnPrint.Enabled = true;
}
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Image img = ((PictureBox)pictureBox1).Image;
Bitmap bmp = (Bitmap)img;
bmp.Save("abcc");
Bitmap bitmap = new Bitmap(bmp, new Size(892, 596));
// Bitmap b = ResizeBitmap(bmp, 892, 596);
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
e.Graphics.CompositingMode = CompositingMode.SourceCopy;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.Transform.Scale(0, 0);
e.Graphics.DrawImage(bitmap,new Rectangle(0,0,892,596),new Rectangle(0,0,bmp.Width,bmp.Height),GraphicsUnit.Pixel);
}

Related

Crop and Print Image Documents without Distortion In C#

I'm using WinForms. In my form I have a picturebox I use to display image documents. The problem is when I crop the image and then print the document out the image becomes slightly distorted. If I don't crop the image document and print it regularly the image document does not become distorted.
How do I crop and print the image documents without them being distorted?
Or is there a better way to code this so it can crop and print without the image document being distorted? If so, how can i do it?
Notes:
My picturebox is set to Zoom because the images i work with is big:
Example of image document Dimensions: 2500 x 3100
My picturebox does not have a border
int _cropX, _cropY, _cropWidth, _cropHeight;
public Pen _cropPen;
private State _currentState;
private enum State
{
Crop
}
private void Open_btn_Click(object sender, EventArgs e)
{
// open file dialog
OpenFileDialog open = new OpenFileDialog();
if (open.ShowDialog() == DialogResult.OK)
{
// display image in picture box
pictureBox1.Image = new Bitmap(open.FileName);
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
try
{
if (Crop_Checkbox.Checked == true)
{
Cursor = Cursors.Default;
if (_currentState == State.Crop)
{
if (_cropWidth < 1)
{
return;
}
Rectangle rect = new Rectangle(_cropX, _cropY, _cropWidth, _cropHeight);
//First we define a rectangle with the help of already calculated points
Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
//Original image
Bitmap img = new Bitmap(_cropWidth, _cropHeight);
// for cropinf image
Graphics g = Graphics.FromImage(img);
// create graphics
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
//set image attributes
g.DrawImage(originalImage, 0, 0, rect, GraphicsUnit.Pixel);
pictureBox1.Image = img;
pictureBox1.Width = img.Width;
pictureBox1.Height = img.Height;
}
}
else
{
Cursor = Cursors.Default;
}
}
catch (Exception)
{
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (Crop_Checkbox.Checked == true)
{
if (_currentState == State.Crop)
{
Cursor = Cursors.Cross;
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
//X and Y are the coordinates of Crop
pictureBox1.Refresh();
_cropWidth = e.X - _cropX;
_cropHeight = e.Y - _cropY;
pictureBox1.CreateGraphics().DrawRectangle(_cropPen, _cropX, _cropY, _cropWidth, _cropHeight);
}
}
}
else
{
Cursor = Cursors.Default;
}
}
private void Crop_Checkbox_CheckedChanged(object sender, EventArgs e)
{
if (Crop_Checkbox.Checked == true)
{
this.Cursor = Cursors.Cross;
}
}
private void Print_btn_Click(object sender, EventArgs e)
{
System.Drawing.Printing.PrintDocument myPrintDocument1 = new System.Drawing.Printing.PrintDocument();
PrintDialog myPrinDialog1 = new PrintDialog();
myPrintDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(printDocument1_PrintPage);
myPrinDialog1.Document = myPrintDocument1;
if (myPrinDialog1.ShowDialog() == DialogResult.OK)
{
myPrintDocument1.Print();
}
}
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawImage(pictureBox1.Image, 10, 10); //(Standard paper size is 850 x 1100 or 2550 x 3300 pixels)
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (Crop_Checkbox.Checked == true)
{
if (_currentState == State.Crop)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Cursor = Cursors.Cross;
_cropX = e.X;
_cropY = e.Y;
_cropPen = new Pen(Color.FromArgb(153, 180, 209), 3); //2 is Thickness of line
_cropPen.DashStyle = DashStyle.DashDotDot;
pictureBox1.Refresh();
}
}
}
else
{
Cursor = Cursors.Default;
}
}
Test: Slightly Distorted:
Test: Not Distorted:
Test:
The picture above is a test. This is what happened when i took the below code out from pictureBox1_MouseUp:
Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
And edited/replaced (originalImage to pictureBox1.Image):
g.DrawImage(pictureBox1.Image, 0, 0, rect, GraphicsUnit.Pixel);
Bitmap originalImage = new Bitmap(pictureBox1.Image, pictureBox1.Width, pictureBox1.Height);
That is most likely where the problem started. This can cause pictureBox1.Image to be rescaled to force-fit it to the pictureBox1 size. Depends on whether the picturebox has borders and its SizeMode property value. Rescaling causes the image to be resampled, the color of a pixel in the new bitmap is calculated from the values of its neighboring pixels in the original image as directed by the selected InterpolationMode.
This in effect blurs the resulting image. That works well on a photo but this is text that critically depends on anti-aliasing pixels to look decent on a low-resolution monitor. Slight changes to those pixels ruins the effect and they no longer smoothly blend the letter shape against the background anymore. They become more visible, best way to describe it is that the resulting text looks "fat".
I see no obvious reason to do this at all in the posted code. Delete the statement and replace originalImage with pictureBox1.Image.
Also beware that printing this image is likely to be disappointing. Now those anti-aliasing pixels get turned into 6x6 blobs of ink on paper. That only ever looks good when you have long arms. As long as the font size is this small and you have no control over the anti-aliasing choice then there's very little you can do about that. Printed text only ever looks good when you use PrintDocument and Graphics.DrawString().

Compare two images with PictureBox controls

I'm trying to achieve an effect similar to this site. I am basically trying to implement a way to "compare" two similar images (with different colors, etc). I managed to do this in a not so brilliant way using two PictureBox controls (Winforms) one next to the other, and changing their Size and Location attributes on a MouseMove event.
The result works, but it flickers a lot and it's not really the best way to do it.
Is there a better way to do this, maybe with a WPF or by changing the code in any way? Here it is:
private void pbImg1_MouseMove(object sender, MouseEventArgs e)
{
pbImg2.Image = CropImage(array[1], new Rectangle(pbImg1.Size.Width, 0, totalSize.Width - pbImg1.Size.Width, 240));
pbImg1.Size = new Size(e.X, pbImg1.Height);
pbImg2.Location = new Point(pbImg1.Size.Width + pbImg1.Location.X, pbImg2.Location.Y);
pbImg2.Size = new Size(totalSize.Width - pbImg1.Size.Width, 240);
lpbImg1Size.Text = pbImg1.Size.ToString();
lpbImg2Size.Text = pbImg2.Size.ToString();
lpbImg1Location.Text = pbImg1.Location.ToString();
lpbImg2Location.Text = pbImg2.Location.ToString();
}
private void pbImg2_MouseMove(object sender, MouseEventArgs e)
{
pbImg1.Image = CropImage(array[0], new Rectangle(0, 0, totalSize.Width - pbImg2.Size.Width, 240));
pbImg1.Size = new Size(pbImg1.Width + e.X, 240);
lpbImg1Size.Text = pbImg1.Size.ToString();
lpbImg2Size.Text = pbImg2.Size.ToString();
lpbImg1Location.Text = pbImg1.Location.ToString();
lpbImg2Location.Text = pbImg2.Location.ToString();
}
public Bitmap CropImage(Bitmap source, Rectangle section)
{
// An empty bitmap which will hold the cropped image
//TRY CATCH
Bitmap bmp = new Bitmap(section.Width, section.Height);
Graphics g = Graphics.FromImage(bmp);
// Draw the given area (section) of the source image
// at location 0,0 on the empty bitmap (bmp)
g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
return bmp;
}
And here you can see the behavior of the program:
https://gfycat.com/VillainousReadyAmazonparrot
You need two images imageLeft, imageRight with the same size as the picturebox:
private int pos = 0; //x coordinate of mouse in picturebox
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if(pos == 0)
{
e.Graphics.DrawImage(Properties.Resources.imageRight, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
}
else
{
e.Graphics.DrawImage(Properties.Resources.imageLeft, new Rectangle(0, 0, pos, pictureBox1.Height),
new Rectangle(0, 0, pos, pictureBox1.Height), GraphicsUnit.Pixel);
e.Graphics.DrawImage(Properties.Resources.imageRight, new Rectangle(pos, 0, pictureBox1.Width - pos, pictureBox1.Height),
new Rectangle(pos, 0, pictureBox1.Width - pos, pictureBox1.Height), GraphicsUnit.Pixel);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pos = e.X;
pictureBox1.Invalidate();
}

Crop image using a fixed-size draggable picturebox

I'm working on a winforms project that involves cropping an image. My goal is to do this by using a fixed-size draggable picturebox control, allowing the user to select the area they want to preserve.
My problem is when I crop the image; it "works", but the crop area offsets a little. Here's the result I get:
To clarify, I'm not talking about the zooming, that's per design. Notice the orange box is mostly focusing on the eye of the storm, but the cropped image is not.
This is my code for the crop operation:
private void tsbRecortar_Click(object sender, EventArgs e)
{
Rectangle recorte = new Rectangle(pbxSeleccion.Location.X, pbxSeleccion.Location.Y, pbxSeleccion.Width, pbxSeleccion.Height);
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
private Image recortarImagen(Image imagen, Rectangle recuadro)
{
try
{
Bitmap bitmap = new Bitmap(imagen);
Bitmap cropedBitmap = bitmap.Clone(recuadro, bitmap.PixelFormat);
return (Image)(cropedBitmap);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
return null;
}
}
pbxSeleccion is the draggable orange rectangle; its parent is pbxImage (I re-parent it on form's load).
As you can see, I'm using the coordinates of pbxSeleccion to define the starting point of the crop area, but is not working as expected... sometimes, I even get an "Out of Memory" exception.
I think this has to do with how the image loads in the parent picturebox, something about how the margin is handled "under the hood", but nothing I tried fixes it... just changes the magnitude of the offset.
Searching the web and SO has helped me a lot, but for this particular issue, I can't seem to find an answer... please, feel free to point out improvements to my code, I haven't been coding for long and I'm new to C# and .NET
Any help is highly appreciated. Cheers!
Suppose your original image is displayed in a PictureBox. You passed in the wrong location of the orange cropping window. Here is the corrected code for you:
private void tsbRecortar_Click(object sender, EventArgs e){
Point p = yourPictureBox.PointToClient(pbxSelection.PointToScreen(Point.Empty));
Rectangle recorte = new Rectangle(p.X, p.Y, pbxSeleccion.Width, pbxSeleccion.Height);
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
I use PointToClient and PointToScreen here because I think it's the best way to do. You can then change the container of your pictureBox safely without having to modify the code. If you use the code like the following, it's not dynamically enough when you want to place your pictureBox in another container:
Rectangle recorte = new Rectangle(pbxSeleccion.X + yourPictureBox.Left,
pbxSeleccion.Y + yourPictureBox.Top,
pbxSeleccion.Width, pbxSeleccion.Height);
NOTE: you can also use RectangleToClient and RectangleToScreen like this:
private void tsbRecortar_Click(object sender, EventArgs e){
Rectangle recorte = yourPictureBox.RectangleToClient(pbxSeleccion.RectangleToScreen(pbxSeleccion.ClientRectangle));
foto = recortarImagen(foto, recorte);
pbxImagen.Image = foto;
}
Try This Code for Cropping the Image in picturebox
public static Image Fit2PictureBox(this Image image, PictureBox picBox)
{
Bitmap bmp = null;
Graphics g;
// Scale:
double scaleY = (double)image.Width / picBox.Width;
double scaleX = (double)image.Height / picBox.Height;
double scale = scaleY < scaleX ? scaleX : scaleY;
// Create new bitmap:
bmp = new Bitmap(
(int)((double)image.Width / scale),
(int)((double)image.Height / scale));
// Set resolution of the new image:
bmp.SetResolution(
image.HorizontalResolution,
image.VerticalResolution);
// Create graphics:
g = Graphics.FromImage(bmp);
// Set interpolation mode:
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new image:
g.DrawImage(
image,
new Rectangle( // Ziel
0, 0,
bmp.Width, bmp.Height),
new Rectangle( // Quelle
0, 0,
image.Width, image.Height),
GraphicsUnit.Pixel);
// Release the resources of the graphics:
g.Dispose();
// Release the resources of the origin image:
image.Dispose();
return bmp;
}
public static Image Crop(this Image image, Rectangle selection)
{
Bitmap bmp = image as Bitmap;
// Check if it is a bitmap:
if (bmp == null)
throw new ArgumentException("Kein gültiges Bild (Bitmap)");
// Crop the image:
Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
// Release the resources:
image.Dispose();
return cropBmp;
}
Write The Following Code For Mouse Event on PictureBox
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _selecting)
{
// Create cropped image:
try
{
Image img = pictureBox1.Image.Crop(_selection);
// Fit image to the picturebox:
pictureBox1.Image = img.Fit2PictureBox(pictureBox1);
}
catch { }
_selecting = false;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Update the actual size of the selection:
if (_selecting)
{
_selection.Width = e.X - _selection.X;
_selection.Height = e.Y - _selection.Y;
// Redraw the picturebox:
pictureBox1.Refresh();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_selecting)
{
// Draw a rectangle displaying the current selection
Pen pen = Pens.LightSkyBlue;
e.Graphics.DrawRectangle(pen, _selection);
}
}
Output Screen
Before Cropping
After Cropping

How to put image aligned right, bottom in picturebox

i have picturebox1 much larger than image i'd like to load. What i want to do is aligned this image to right side, and bottom of picturebox like on screenshot:
Edit: Working
private void FromCameraPictureBox_Paint(object sender, PaintEventArgs e)
{
if (loadimage == true)
{
var image = new Bitmap(#"image.jpg");
if (image != null)
{
var g = e.Graphics;
// -- Optional -- //
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// -- Optional -- //
g.DrawImage(image,
FromCameraPictureBox.Width - image.Width, // to right
FromCameraPictureBox.Height - image.Height, // to bottom
image.Width,
image.Height);
}
}
loadimage = false;
}
and now i want to fire paintevent from button:
void TestButtonClick(object sender, EventArgs e)
{
loadimage = true;
}
How to do this?
I'm confused why this code works nasty:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImage(pictureBox1.Image, pictureBox1.Width - pictureBox1.Image.Width, pictureBox1.Height - pictureBox1.Image.Height);
}
EDIT:
Ok now it works:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var image = Properties.Resources.SomeImage; //Import via Resource Manager
//Don't use pictureBox1.Image property because it will
//draw the image 2 times.
//Make sure the pictureBox1.Image property is null in Deisgn Mode
if (image != null)
{
var g = e.Graphics;
// -- Optional -- //
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// -- Optional -- //
g.DrawImage(image,
pictureBox1.Width - image.Width, // to right
pictureBox1.Height - image.Height, // to bottom
image.Width,
image.Height);
}
}
UPDATE:
Working :) But is there any possibility to use this code without
PaintEventsArgs ? I was trying to add to my button flag and in paint
(if (flag==true) then execute Your code, but it doesn't do anything -
no drawing on picturebox1
That's because Paint event fires once. We need to make it redraw. The default redraw method for controls is Refresh();
Here you go:
bool flag = false;
Bitmap image = null;
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (flag && image != null)
{
var g = e.Graphics;
// -- Optional -- //
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// -- Optional -- //
g.DrawImage(image,
pictureBox1.Width - image.Width,
pictureBox1.Height - image.Height,
image.Width,
image.Height);
}
}
private void button2_Click(object sender, EventArgs e)
{
image = new Bitmap("someimage.png");
flag = true;
pictureBox1.Refresh(); //Causes it repaint.
}
//If you resize the form (and anchor/dock the picturebox)
//or just resize the picturebox then you will need this:
private void pictureBox1_Resize(object sender, EventArgs e)
{
pictureBox1.Refresh();
}
You can use Bitmap + Graphics objects and copy the portion of your picture to a new bitmap (result) that will be assigned to the picturebox:
Size resultSize = new Size(100, 100);
Bitmap result = new Bitmap(resultSize.Width, resultSize.Height);
float left = yourbitmap.Width - resultSize.Width;
float top = yourbitmap.Height - resultSize.Height;
using (Graphics g = Graphics.FromImage(result))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(yourbitmap, left, top, resultSize.Width, resultSize.Height);
g.Save();
}

Crop a picture using a rectangle

I want to crop an image in c#. As in most photo editing software I want to use the rectangle box which can be resized and repositioned via a mouse. In addition, I would like to know how to highlight the cropped area, as show in this photo.
Your image link is no longer available.
So assuming that in a panel you have your picturebox with the image to crop.
First you need to create event handlers for mouse actions to be able to draw a rectangular region which you wish to crop :
private void picBox_MouseDown(object sender, MouseEventArgs e)
{
Cursor = Cursors.Default;
if (Makeselection)
{
try
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Cursor = Cursors.Cross;
cropX = e.X;
cropY = e.Y;
cropPen = new Pen(Color.Crimson, 1);
cropPen.DashStyle = DashStyle.Solid;
}
picBox.Refresh();
}
catch (Exception ex)
{
}
}
}
private void picBox_MouseUp(object sender, MouseEventArgs e)
{
if (Makeselection)
{
Cursor = Cursors.Default;
}
}
private void picBox_MouseMove(object sender, MouseEventArgs e)
{
Cursor = Cursors.Default;
if (Makeselection)
{
picBox.Cursor = Cursors.Cross;
try
{
if (picBox.Image == null)
return;
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
picBox.Refresh();
cropWidth = e.X - cropX;
cropHeight = e.Y - cropY;
picBox.CreateGraphics().DrawRectangle(cropPen, cropX, cropY, cropWidth, cropHeight);
}
}
catch (Exception ex)
{
}
}
}
private void picBox_MouseLeave(object sender, EventArgs e)
{
tabControl.Focus();
}
private void picBox_MouseEnter(object sender, EventArgs e)
{
picBox.Focus();
}
Now, comes the button click function for cropping the image :
private void btnCrop_Click_1(object sender, EventArgs e)
{
Cursor = Cursors.Default;
try
{
if (cropWidth < 1)
{
return;
}
Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
//First we define a rectangle with the help of already calculated points
Bitmap OriginalImage = new Bitmap(picBoxScreenshot.Image, picBoxScreenshot.Width, picBoxScreenshot.Height);
//Original image
Bitmap _img = new Bitmap(cropWidth, cropHeight);
// for cropinfo image
Graphics g = Graphics.FromImage(_img);
// create graphics
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
//set image attributes
g.DrawImage(OriginalImage, 0, 0, rect, GraphicsUnit.Pixel);
picBox.Image = _img;
picBox.Width = _img.Width;
picBox.Height = _img.Height;
PictureBoxLocation();
cropWidth = 0;
}
catch (Exception ex){}
}
private void PictureBoxLocation()
{
int _x = 0;
int _y = 0;
if (panel1.Width > picBox.Width)
{
_x = (panel1.Width - picBox.Width) / 2;
}
if (panel1.Height > picBox.Height)
{
_y = (panel1.Height - picBox.Height) / 2;
}
picBox.Location = new Point(_x, _y);
picBox.Refresh();
}
In order to draw a picture lighter or darker (or alter the colors in any way) you use a ColorMatrix, like this.
The outside of the selection box seems to have a black image laid over it with a alpha of about 30%. To do this you would just take each pixel outside of the content area and draw a black pixel with a 30% alpha on top of it. This would give the desired dimmed out effect.
As for how you can get a rectangle to be dynamically seizable in C#.

Categories

Resources