Crop an image in imagebox control and save it - c#

What I am doing is making a program that designs a card and displays the image real-time. I have finished that part and it works perfectly fine. Now i need to crop the image and save as the way its saving atm which has 2 white bars at the top and bottom. This is the code that I am using now for saving.
private void SaveCardbtn_Click(object sender, EventArgs e)
{
//Open the saveFileDialog
if (saveWork.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
CardImg.Image.Save(saveWork.FileName, ImageFormat.Jpeg);
}
}
thanks.

I have already posted this answer in asp .net forum.
Please try this one -
The following crop function will accept 4 parameters:
Width: This will be the width of cropped image.
Height: This will be the height of cropped image.
Source Image File Path: This will be the full path of the source image file.
Save Cropped Image File Path: This will be the full path of the save cropped image file.
public static void CropImage(int Width, int Height, string sourceFilePath, string saveFilePath) {
// variable for percentage resize
float percentageResize = 0;
float percentageResizeW = 0;
float percentageResizeH = 0;
// variables for the dimension of source and cropped image
int sourceX = 0;
int sourceY = 0;
int destX = 0;
int destY = 0;
// Create a bitmap object file from source file
Bitmap sourceImage = new Bitmap(sourceFilePath);
// Set the source dimension to the variables
int sourceWidth = sourceImage.Width;
int sourceHeight = sourceImage.Height;
// Calculate the percentage resize
percentageResizeW = ((float)Width / (float)sourceWidth);
percentageResizeH = ((float)Height / (float)sourceHeight);
// Checking the resize percentage
if (percentageResizeH < percentageResizeW) {
percentageResize = percentageResizeW;
destY = System.Convert.ToInt16((Height - (sourceHeight * percentageResize)) / 2);
} else {
percentageResize = percentageResizeH;
destX = System.Convert.ToInt16((Width - (sourceWidth * percentageResize)) / 2);
}
// Set the new cropped percentage image
int destWidth = (int)Math.Round(sourceWidth * percentageResize);
int destHeight = (int)Math.Round(sourceHeight * percentageResize);
// Create the image object
using (Bitmap objBitmap = new Bitmap(Width, Height)) {
objBitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
using (Graphics objGraphics = Graphics.FromImage(objBitmap)) {
// Set the graphic format for better result cropping
objGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
objGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
objGraphics.DrawImage(sourceImage, new Rectangle(destX, destY, destWidth, destHeight), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel);
// Save the file path, note we use png format to support png file
objBitmap.Save(saveFilePath, ImageFormat.Png);
}
}
}
Call the above CropImage method by using following code:
CropImage(100, 100, "c://destinationimage.jpg", "c://newcroppedimage.jpg");
Hope this will help you!

i use this code to do image cropping. Please note that pbOriginalImage is your picture box that has the image.
private void pbOriginalImage_MouseDown(object sender, MouseEventArgs e)
{
try
{
// Starting point of the selection:
if (e.Button == MouseButtons.Left)
{
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
catch (Exception ex)
{
ApplicationExceptions.HandleAppExc(ex);
}
}
private void pbOriginalImage_MouseMove(object sender, MouseEventArgs e)
{
try
{
// Update the actual size of the selection:
if (_selecting)
{
_selection.Width = e.X - _selection.X;
_selection.Height = e.Y - _selection.Y;
// Redraw the picturebox:
pbOriginalImage.Refresh();
}
}
catch (Exception ex)
{
ApplicationExceptions.HandleAppExc(ex);
}
}
private void pbOriginalImage_MouseUp(object sender, MouseEventArgs e)
{
try
{
if (pbOriginalImage.Image == null)
return;
if (e.Button == MouseButtons.Left && _selecting)
{
// check selection rectangle has non-zero Height and Width
if (!ValidateSelection(_selection))
{
_selecting = false;
return;
}
// Check that selection rectangle does extend outside of image boundaries
ValidateRectangleSize();
// Create cropped image:
Image tempImage = pbOriginalImage.Image.Clone() as Image;
Image img = tempImage.Crop(_selection);
// Fit image to the picturebox:
profileImage.Image = img.Fit2PictureBox(profileImage);
_selecting = false;
}
}
catch (Exception ex)
{
ApplicationExceptions.HandleAppExc(ex);
}
}
private void pbOriginalImage_Paint(object sender, PaintEventArgs e)
{
try
{
if (_selecting)
{
// Draw a rectangle displaying the current selection
Pen pen = Pens.GreenYellow;
e.Graphics.DrawRectangle(pen, _selection);
}
}
catch (Exception ex)
{
ApplicationExceptions.HandleAppExc(ex);
throw;
}
}
private void commandBrowse_Click(object sender, EventArgs e)
{
try
{
using (OpenFileDialog dlg = new OpenFileDialog())
{
dlg.Filter = "JPG Files (*.jpg)|*.jpg|JPEG Files (*.jpeg)|*.jpeg|bmp Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png|GIF Files (*.gif)|*.gif";
if (dlg.ShowDialog() == DialogResult.OK)
{
FileInfo file = new FileInfo(dlg.FileName);
if (file.Length == 0)
{
MessageBoxEx.Show("Invalid image. Please select valid image.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
else if (file.Length > 2097152)
{
MessageBoxEx.Show("Image size cannot exceed 2MB.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
textProfileImagePath.Text = dlg.FileName;
pbOriginalImage.Image = Image.FromFile(dlg.FileName).Fit2PictureBox(pbOriginalImage);
profileImage.Image = Image.FromFile(dlg.FileName).Fit2PictureBox(profileImage);
}
}
}
catch (Exception ex)
{
if (ex.Message.Contains("Out of memory"))
{
MessageBoxEx.Show("Invalid image. Please select valid image.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
ApplicationExceptions.HandleAppExc(ex);
}
}
// Check that selection rectangle does extend outside of image boundaries
private void ValidateRectangleSize()
{
Size imgSize = this.pbOriginalImage.Image.Size;
int selectionWidth;
int selectionHeight;
// check width
if (_selection.X < 0)
{
_selection.X = 0;
}
selectionWidth = _selection.Width + _selection.X;
if (selectionWidth > imgSize.Width)
{
_selection.Width = imgSize.Width - _selection.X - 1;
}
// check height
if (_selection.Y < 0)
{
_selection.Y = 0;
}
selectionHeight = _selection.Height + _selection.Y;
if (selectionHeight > imgSize.Height)
{
_selection.Height = imgSize.Height - _selection.Y - 1;
}
}
// check selection rectangle has non-zero Height and Width
private bool ValidateSelection(Rectangle selection)
{
// routine to validate the selection
if (selection.Width <= 0 || selection.Height <= 0)
{
// if you get here a good rectangle was not created
return false;
}
else
{
return true;
}
}
and this is the extension class i use.
public static class ImageExtension
{
/// <summary>
/// Crops an image according to a selection rectangel
/// </summary>
/// <param name="image">
/// the image to be cropped
/// </param>
/// <param name="selection">
/// the selection
/// </param>
/// <returns>
/// cropped image
/// </returns>
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("Not a valid image (Bitmap)");
// Crop the image:
Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
// Release the resources:
image.Dispose();
return cropBmp;
}
//---------------------------------------------------------------------
/// <summary>
/// Fits an image to the size of a picturebox
/// </summary>
/// <param name="image">
/// image to be fit
/// </param>
/// <param name="picBox">
/// picturebox in that the image should fit
/// </param>
/// <returns>
/// fitted image
/// </returns>
/// <remarks>
/// Although the picturebox has the SizeMode-property that offers
/// the same functionality an OutOfMemory-Exception is thrown
/// when assigning images to a picturebox several times.
///
/// AFAIK the SizeMode is designed for assigning an image to
/// picturebox only once.
/// </remarks>
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;
}
}

Related

C# Bitmap Draw Image is Scaling

My setup takes .png images (with transparency) and stacks these images as layers on top of each other to form one image. The first batch I did worked perfectly. This second batch for some reason is scaling all of the images.
All of the images are 2000px x 2000px (I have individually checked each one and I can also see that Windows Explorer recognizes all of their dimensions.
All images are *.png files with transparent backgrounds.
In the Merge() function: I checked to see what the output width and height (and same of the image object) were and every single time they all came out to be 2000 (which is what it should be).
Below is a screen shot of the actual output vs what it should be. Again, I did this with different images (all 2000px x 2000px) and it worked perfectly. I'm not sure what is going on here.
public static Bitmap TestIt()
{
List<string> list = new List<string>
{
Path.Combine(dir, "body1.png"),
Path.Combine(dir, "head5.png"),
Path.Combine(dir, "legs2.png"),
Path.Combine(dir, "background2.png")
};
//Get List of Bitmaps from URLs
List<Bitmap> bitmaps = ConvertUrlsToBitmaps(list);
if (bitmaps.Any())
{
return Merge(bitmaps);
}
else
{
return null;
}
}
private static Bitmap Merge(List<Bitmap> images)
{
Bitmap bitmap = null;
var width = 0;
var height = 0;
try
{
// Get max width and height of the image
foreach (var image in images)
{
width = image.Width > width ? image.Width : width;
height = image.Height > height ? image.Height : height;
}
// merge images
bitmap = new Bitmap(width, height);
using (var g = Graphics.FromImage(bitmap))
{
foreach (var image in images)
{
g.DrawImage(image, 0, 0);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return bitmap;
}
private static List<Bitmap> ConvertUrlsToBitmaps(List<string> imageUrls)
{
List<Bitmap> bitmapList = new List<Bitmap>();
try
{
foreach (string imgUrl in imageUrls)
{
Bitmap bmp = (Bitmap)Image.FromFile(imgUrl);
bitmapList.Add(bmp);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return bitmapList;
}
Alright...I solved it.
I added a Rectangle object that will identify both position and size.
Then I forced the drawImage function to draw according to position and size
Here's the update
private static Bitmap Merge(List<Bitmap> images)
{
Bitmap bitmap = null;
var width = 0;
var height = 0;
try
{
// Get max width and height of the image
foreach (var image in images)
{
width = image.Width > width ? image.Width : width;
height = image.Height > height ? image.Height : height;
}
// merge images
bitmap = new Bitmap(width, height);
//*** Added a Rectangle object that will identify starting position and size
Rectangle rect = new Rectangle(new Point(0, 0), new Size(width, height));
using (var g = Graphics.FromImage(bitmap))
{
foreach (var image in images)
{
//*** Force the system to draw the image at location AND size
g.DrawImage(image, rect);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return bitmap;
}

Compress image from web url in asp.net using c#

I'm trying to minify image from url, my code is this
public static string GetBreaker(string fileName)
{
string cacheBreaker = null;
try
{
if (fileName.StartsWith("~"))
{
fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName.Remove(0));
}
cacheBreaker = File.GetLastWriteTime(fileName).ToFileTime().ToString();
}
catch { }
return string.IsNullOrEmpty(cacheBreaker) ? string.Empty : string.Format("?cachebreaker={0}", cacheBreaker);
}
public static void SaveJpeg(string path, System.Drawing.Image img, int quality)
{
if (quality < 0 || quality > 100)
throw new ArgumentOutOfRangeException("quality must be between 0 and 100.");
EncoderParameter qualityParam =
new EncoderParameter(Encoder.Quality, quality);
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
img.Save(path, jpegCodec, encoderParams);
}
private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
for (int i = 0; i < codecs.Length; i++)
if (codecs[i].MimeType == mimeType)
return codecs[i];
return null;
}
protected void Button1_Click(object sender, EventArgs e)
{
System.Drawing.Image myImage = System.Drawing.Image.FromFile(ImageUrltxt.Text.ToString());
SaveJpeg(#"~/mintemp/demo.jpg", myImage, 50);
}
I'm getting error like this:
URI formats are not supported.
in
System.Drawing.Image myImage = System.Drawing.Image.FromFile(ImageUrltxt.Text.ToString());
Can anyone help me to solve out this problem. I'm very new to programming. Thanks in advance, sorry for my bad English.
1. First you have to check out your uri path is correct or not eg:
string uriPath = "file:\\C:\\Users\\john\\documents\\visual studio 2010\\Projects\\proj";
or
string localPath = new Uri(uriPath).LocalPath;
2. You have to add the uri of the image as correct Please check your uri path of image is correct.
SaveJpeg(#"~/mintemp/demo.jpg", myImage, 50);
3. This is coded in c# (for reference) resizing and compressing of image in c#
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
private Boolean CheckFileType(String fileName)
{
String ext = Path.GetExtension(fileName) ;
switch (ext.ToLower())
{
case ".gif":
return true;
case ".png":
return true;
case ".jpg":
return true;
case ".jpeg":
return true;
case ".bmp":
return true;
default:
return false;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
const int bmpW = 300;// //New image target width
const int bmpH = 226;// //New Image target height
if (FileUpload1.HasFile)
{
//Clear the error label text
lblError.Text = "";
//Check to make sure the file to upload has a picture file format extention
//and set the target width and height
if (this.CheckFileType(FileUpload1.FileName))
{
Int32 newWidth = bmpW;
Int32 newHeight = bmpH;
//Use the uploaded filename for saving without the "." extension
String upName = FileUpload1.FileName.Substring(0, FileUpload1.FileName.IndexOf("."));
//Mid(FileUpload1.FileName, 1, (InStr(FileUpload1.FileName, ".") - 1)) ;
//Set the save path of the resized image, you will need this directory already created in your web site
String filePath = "~/Upload/" + upName + ".jpg";
//Create a new Bitmap using the uploaded picture as a Stream
//Set the new bitmap resolution to 72 pixels per inch
Bitmap upBmp = (Bitmap)Bitmap.FromStream(FileUpload1.PostedFile.InputStream);
Bitmap newBmp = new Bitmap(newWidth, newHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
newBmp.SetResolution(72, 72);
//Get the uploaded image width and height
Int32 upWidth = upBmp.Width;
Int32 upHeight = upBmp.Height;
Int32 newX = 0; //Set the new top left drawing position on the image canvas
Int32 newY = 0;
Decimal reDuce;
//Keep the aspect ratio of image the same if not 4:3 and work out the newX and newY positions
//to ensure the image is always in the centre of the canvas vertically and horizontally
if (upWidth > upHeight)
{
//Landscape picture
reDuce = newWidth / upWidth;
//calculate the width percentage reduction as decimal
newHeight = ((Int32)(upHeight * reDuce));
//reduce the uploaded image height by the reduce amount
newY = ((Int32)((bmpH - newHeight) / 2));
//Position the image centrally down the canvas
newX = 0; //Picture will be full width
}
else
{
if (upWidth < upHeight)
{
//Portrait picture
reDuce = newHeight / upHeight;
//calculate the height percentage reduction as decimal
newWidth = ((Int32)(upWidth * reDuce));
//reduce the uploaded image height by the reduce amount
newX = ((Int32)((bmpW - newWidth) / 2));
//Position the image centrally across the canvas
newY = 0; //Picture will be full hieght
}
else
{
if (upWidth == upHeight)
{
//square picture
reDuce = newHeight / upHeight;
//calculate the height percentage reduction as decimal
newWidth = ((Int32)((upWidth * reDuce)));
//reduce the uploaded image height by the reduce amount
newX = ((Int32)(((bmpW - newWidth) / 2))); //Position the image centrally across the canvas
newY = ((Int32)(((bmpH - newHeight) / 2))); //Position the image centrally down the canvas
}
}
}
//Create a new image from the uploaded picture using the Graphics class
//Clear the graphic and set the background colour to white
//Use Antialias and High Quality Bicubic to maintain a good quality picture
//Save the new bitmap image using //Png// picture format and the calculated canvas positioning
Graphics newGraphic = Graphics.FromImage(newBmp);
try
{
newGraphic.Clear(Color.White);
newGraphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
newGraphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
newGraphic.DrawImage(upBmp, newX, newY, newWidth, newHeight);
newBmp.Save(MapPath(filePath), System.Drawing.Imaging.ImageFormat.Jpeg);
//Show the uploaded resized picture in the image control
Image1.ImageUrl = filePath;
Image1.Visible = true;
}
catch (Exception ex)
{
lblError.Text = ex.ToString();
throw ex;
}
finally
{
upBmp.Dispose();
newBmp.Dispose();
newGraphic.Dispose();
}
}
else
{
lblError.Text = "Please select a picture with a file format extension of either Bmp, Jpg, Jpeg, Gif or Png.";
}
}
}
}

C# - Forcing Rectangle to be in a fixed size/ratio

Similar to Photoshop, where you can type in a ratio or in my case a certain dimention such as 800x600, I want to be able to force a Rectangle to be a fixed ratio/size when dragging the mouse..
At the moment I have this:
Which will crop an image using the Rectangle created from clicking and dragging on the PictureBox. The bounding box selects the area without any constraints. I want to be able to force the rectangle to be a certain ratio (prefereably from a set resolution) similar to the way Photoshop's cropping tool works.
My source if anyone needs more detail:
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CropResize
{
public partial class Form1 : Form
{
private static string path;
public Form1(string filePath)
{
InitializeComponent();
path = filePath;
}
private Image _originalImage;
private Image _newImage;
private bool _selecting;
private Rectangle _selection;
private void Form1_Load(object sender, System.EventArgs e)
{
pictureBox1.Image = Image.FromFile(path);
if (pictureBox1.Image.Height > Screen.PrimaryScreen.Bounds.Height - 50 || pictureBox1.Image.Width > Screen.PrimaryScreen.Bounds.Width - 50)
{
if (pictureBox1.Image.Height > Screen.PrimaryScreen.Bounds.Height - 50)
{
Height = Screen.PrimaryScreen.Bounds.Height - 50;
panel1.Height = Size.Height - statusStrip1.Height - buttonSave.Height - 60;
}
if (pictureBox1.Image.Width > Screen.PrimaryScreen.Bounds.Width - 50)
{
Size = new Size(Screen.PrimaryScreen.Bounds.Width - 50, Screen.PrimaryScreen.Bounds.Height - 50);
panel1.Width = Size.Width - statusStrip1.Height - buttonSave.Height - 60;
}
pictureBox1.Image = pictureBox1.Image.Fit2PictureBox(pictureBox1);
panel1.Size = new Size(pictureBox1.Image.Width, pictureBox1.Image.Height);
}
Size = new Size(panel1.Size.Width + 50, panel1.Size.Height + buttonSave.Height + statusStrip1.Height + 80);
// Create a copy of the original image for later use
_originalImage = pictureBox1.Image.Clone() as Image;
_newImage = pictureBox1.Image.Clone() as Image;
}
private void buttonOrig_Click(object sender, System.EventArgs e)
{
pictureBox1.Image = _originalImage.Clone() as Image;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// Starting point of the selection:
if (e.Button == MouseButtons.Left)
{
pictureBox1.Image.Dispose();
pictureBox1.Image = _originalImage.Clone() as Image;
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
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);
//int nGCD = GetGreatestCommonDivisor(1920, 1080);
//_selection.Width = _selection.Width / nGCD;
//_selection.Height = _selection.Height / nGCD;
int widthRatio = 16;
int heightRatio = 9;
if (_selection.Height * widthRatio <= _selection.Width)
{
_selection.Width = _selection.Height * widthRatio;
}
else if (_selection.Width * heightRatio <= _selection.Width)
{
_selection.Height = _selection.Width * heightRatio;
}
// Redraw the picturebox:
pictureBox1.Refresh();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (_selecting && _selection.Height != 0)
{
// Draw a rectangle displaying the current selection
e.Graphics.DrawRectangle(Pens.WhiteSmoke, _selection);
//e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(50, Color.Gray)), 0, pictureBox1.Height - pictureBox1.Image.Height, pictureBox1.Image.Width, pictureBox1.Image.Height);
e.Graphics.SetClip(_selection, CombineMode.Exclude);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100, Color.Black)), 0, 0, pictureBox1.Width, pictureBox1.Height);
int nGCD = GetGreatestCommonDivisor(_selection.Width, _selection.Height);
string str = string.Format("{0}:{1}", _selection.Width / nGCD, _selection.Height / nGCD);
toolStripStatusLabel1.Text = "Image Size: " + _selection.Width + "x" + _selection.Height + "px. Aspect Ratio: " + str;
}
}
public static int GetGreatestCommonDivisor(int height, int width)
{
return width == 0 ? height : GetGreatestCommonDivisor(width, height % width);
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left &&
_selecting &&
_selection.Size != new Size())
{
// Create cropped image:
_newImage = pictureBox1.Image.Crop(_selection);
_selecting = false;
try
{
// Set new image to the picturebox:
//pictureBox1.Image = _newImage.Fit2PictureBox(pictureBox1);
pictureBox1.Image = _newImage;
//toolStripStatusLabel1.Text = "Image Cropped.";
}
catch (Exception)
{ }
}
else
{
_selecting = false;
}
}
private void buttonResize_Click(object sender, EventArgs e)
{
pictureBox1.Image = ResizeImage(pictureBox1.Image, new Size(800, 600));
int nGCD = GetGreatestCommonDivisor(pictureBox1.Image.Width, pictureBox1.Image.Height);
string str = string.Format("{0}:{1}", pictureBox1.Image.Width / nGCD, pictureBox1.Image.Height / nGCD);
toolStripStatusLabel1.Text = "Image Resized to " + pictureBox1.Image.Width + "x" + pictureBox1.Image.Height + "px. Aspect Ratio: " + str;
}
public static Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true)
{
int newWidth;
int newHeight;
if (preserveAspectRatio)
{
int originalWidth = image.Width;
int originalHeight = image.Height;
float percentWidth = size.Width / originalWidth;
float percentHeight = size.Height / originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
newWidth = (int)(originalWidth * percent);
newHeight = (int)(originalHeight * percent);
}
else
{
newWidth = size.Width;
newHeight = size.Height;
}
Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
}
return newImage;
}
private void buttonSave_Click(object sender, EventArgs e)
{
string filename = path.Substring(path.LastIndexOf("\\") + 1);
string newPath = path.Substring(0, path.LastIndexOf(".") - 1) + "NEW.png";
toolStripStatusLabel1.Text = "Saving " + filename + " to " + newPath;
pictureBox1.Image.Save(newPath, ImageFormat.Png);
toolStripStatusLabel1.Text = filename + " saved to " + newPath;
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CropResize
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args[0]));
}
public static Image SetImageWithinResolution(this Image image, PictureBox pictureBox)
{
//Bitmap bitmap = null;
if (image.Height > Screen.PrimaryScreen.Bounds.Height)
{
//ActiveForm.Size = new Size(100, 100);
Form.ActiveForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
image = image.Fit2PictureBox(pictureBox);
//Bitmap bitmap = new Bitmap(image, );
}
if (image.Width > Screen.PrimaryScreen.Bounds.Width)
{
//ActiveForm.Size = new Size(100, 100);
Form.ActiveForm.Size = new Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
image = image.Fit2PictureBox(pictureBox);
//Bitmap bitmap = new Bitmap();
}
return image;
}
public static Image Crop(this Image image, Rectangle selection)
{
Bitmap bmp = image as Bitmap;
try
{
// Check if it is a bitmap:
if (bmp == null)
throw new ArgumentException("No valid bitmap");
// Crop the image:
Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
// Release the resources:
image.Dispose();
return cropBmp;
}
catch (Exception)
{
return bmp;
}
}
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( // Destination
0, 0,
bmp.Width, bmp.Height),
new Rectangle( // Source
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;
}
}
Maybe this example will help; is shows how to restrict a drawn rectangle to a given ratio:
float ratio = 0.33f;
Rectangle setRect()
{
int x = Math.Min(mDown.X, currPt.X);
int y = Math.Min(mDown.Y, currPt.Y);
int w = Math.Max(mDown.X, currPt.X) - x;
int h = Math.Max(mDown.Y, currPt.Y) - y;
if (ratio > 1) h = (int)(1f * w / ratio);
else w = (int)(1f * h * ratio);
return new Rectangle(x, y, w, h);
}
It uses two Points, one set in the MouseDown and one updated in the MouseMove.
It is up to you to integrate it with you programm; instead of painting all those pixels during MouseMove I would simply draw a rubberband rectangle on the surface of the control using the Paint event..
If you are scaling things you may want to switch to using all floats.

Resizing Images - WIC vs GDI

EDIT: I've since worked out that neither of these implementations are any good for server-side scenarios: they're not supported by Microsoft. So don't go using them!
So I've provided two separate implementations below. I think I've stuffed up the Windows Imaging Component (WIC) implementation.
Some comments:
The GDI implementation seems to be quicker than WIC - WIC # 0.26s/photo, GDI # 0.14s/photo)
The WIC implementation doesn't see any performance gains when multi-threaded, GDI drops to ~0.10s/photo
Only WIC is supported for server-side processing, however if it doesn't mutli-thread then it doesn't scale well
Run on i7, the photo in question was a typical 1.2MB image created by an Olympus digicam
I drew my inspiration from http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx
Can anyone see anything obvious?
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Mrwa.Bms.Common.Imaging
{
/// <summary>
/// Generates JPEG image previews for any supplied .NET image supported files
/// </summary>
/// <remarks>
/// WIC = Windows Imaging Component
/// http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx
/// </remarks>
public class WicImagePreviewGenerator : IImagePreviewGenerator
{
private const int ScreenDpi = 96;
private BitmapFrame _imageFrame;
public WicImagePreviewGenerator(Stream stream)
{
Contract.Requires(stream != null);
try
{
if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin);
var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
_imageFrame = decoder.Frames[0];
}
catch (NotSupportedException ex)
{
throw new ArgumentException("The image is corrupt.", "stream", ex);
}
}
public ImagePreviewGeneratorDto Generate(
int pixelSize, int jpegQuality = 80, int dpi = 72,
ImagePreviewGeneratorResizeQualityEnum resizeQuality = ImagePreviewGeneratorResizeQualityEnum.HighQuality)
{
int previewWidth;
int previewHeight;
CalculateDimensions(pixelSize, out previewWidth, out previewHeight);
// create a new target drawing canvas
var width = (int) (previewWidth*(ScreenDpi/(decimal) dpi));
var height = (int) (previewHeight*(ScreenDpi/(decimal) dpi));
var drawing = new ImageDrawing(
_imageFrame,
new Rect(0, 0, width, height));
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(group, GetScalingMode(resizeQuality));
group.Children.Add(drawing);
// generate the preview image frame
BitmapFrame previewFrame;
var previewVisual = new DrawingVisual();
using (var previewContext = previewVisual.RenderOpen())
{
previewContext.DrawDrawing(group);
previewContext.Close();
var previewBitmap = new RenderTargetBitmap(
previewWidth, previewHeight,
dpi, dpi,
PixelFormats.Default);
previewBitmap.Render(previewVisual);
previewFrame = BitmapFrame.Create(previewBitmap);
}
// generate the result as a JPG
using (var content = new MemoryStream())
{
var previewEncoder = new JpegBitmapEncoder { QualityLevel = jpegQuality };
previewEncoder.Frames.Add(previewFrame);
previewEncoder.Save(content);
content.Flush();
return new ImagePreviewGeneratorDto
{
Preview = content.ToArray(),
Width = previewWidth,
Height = previewHeight
};
}
}
// not used - retained for reference only
public IEnumerable<byte> GenerateOptimised(int pixelSize, int jpegQuality = 80)
{
int previewWidth;
int previewHeight;
CalculateDimensions(pixelSize, out previewWidth, out previewHeight);
var transform = new TransformedBitmap(
_imageFrame, new ScaleTransform(previewWidth, previewHeight, 0, 0));
var previewFrame = BitmapFrame.Create(transform);
// generate the result as a JPG
using (var result = new MemoryStream())
{
var previewEncoder = new JpegBitmapEncoder { QualityLevel = jpegQuality };
previewEncoder.Frames.Add(previewFrame);
previewEncoder.Save(result);
return result.ToArray();
}
}
private static BitmapScalingMode GetScalingMode(ImagePreviewGeneratorResizeQualityEnum previewQuality)
{
switch (previewQuality)
{
case ImagePreviewGeneratorResizeQualityEnum.HighQuality:
return BitmapScalingMode.HighQuality;
case ImagePreviewGeneratorResizeQualityEnum.HighSpeed:
return BitmapScalingMode.LowQuality;
default:
throw new NotSupportedException("Invalid preview quality specified.");
}
}
private void CalculateDimensions(int pixelSize, out int width, out int height)
{
var originalWidth = _imageFrame.PixelWidth;
var originalHeight = _imageFrame.PixelHeight;
// scale: reduce the longest side down to 'X' pixels and maintain the aspect ratio
if (originalWidth <= pixelSize && originalHeight <= pixelSize)
{
width = originalWidth;
height = originalHeight;
}
else if (originalWidth >= originalHeight)
{
width = pixelSize;
height = (int)((pixelSize / (decimal)originalWidth) * originalHeight);
}
else
{
width = (int)((pixelSize / (decimal)originalHeight) * originalWidth);
height = pixelSize;
}
}
#region IDisposable
private bool _disposed;
~WicImagePreviewGenerator()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// free managed resources
_imageFrame = null;
}
// free unmanaged resources
_disposed = true;
}
#endregion
}
}
using System;
using System.Diagnostics.Contracts;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
namespace Mrwa.Bms.Common.Imaging
{
/// <summary>
/// Generates JPEG image previews for any supplied .NET image supported files
/// </summary>
/// <remarks>
/// Feel free to use this Client side. Not officially supported for back-end scenarios.
/// </remarks>
public class GdiPlusImagePreviewGenerator : IImagePreviewGenerator
{
private Image _image;
public GdiPlusImagePreviewGenerator(Stream stream)
{
Contract.Requires(stream != null);
try
{
if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin);
_image = Image.FromStream(stream);
}
catch (ArgumentException ex)
{
throw new ArgumentException("The image is corrupt.", "stream", ex);
}
}
private void CalculateDimensions(int pixelSize, out int width, out int height)
{
var originalWidth = _image.Width;
var originalHeight = _image.Height;
// scale: reduce the longest side down to 'X' pixels and maintain the aspect ratio
if (originalWidth <= pixelSize && originalHeight <= pixelSize)
{
width = originalWidth;
height = originalHeight;
}
else if (originalWidth >= originalHeight)
{
width = pixelSize;
height = (int)((pixelSize / (decimal)originalWidth) * originalHeight);
}
else
{
width = (int)((pixelSize / (decimal)originalHeight) * originalWidth);
height = pixelSize;
}
}
/// <remarks>
/// Not changing the colour depth; apparently the conversion can be quite poor
/// Don't forget to dispose of the stream
/// </remarks>
public ImagePreviewGeneratorDto Generate(
int pixelSize, int jpegQuality = 80, int dpi = 72,
ImagePreviewGeneratorResizeQualityEnum resizeQuality = ImagePreviewGeneratorResizeQualityEnum.HighQuality)
{
int previewWidth;
int previewHeight;
CalculateDimensions(pixelSize, out previewWidth, out previewHeight);
// resize the image (in terms of pixels) and standardise the DPI
using (var previewImage = new Bitmap(previewWidth, previewHeight))
{
previewImage.SetResolution(dpi, dpi);
using (var graphics = Graphics.FromImage(previewImage))
{
switch (resizeQuality)
{
case ImagePreviewGeneratorResizeQualityEnum.HighQuality:
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
break;
case ImagePreviewGeneratorResizeQualityEnum.HighSpeed:
graphics.SmoothingMode = SmoothingMode.HighSpeed;
graphics.InterpolationMode = InterpolationMode.Low;
graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
break;
default:
throw new NotSupportedException("Invalid Preview Quality Enum supplied.");
}
graphics.DrawImage(_image, new Rectangle(0, 0, previewWidth, previewHeight));
}
// convert to a JPG and reduce the quality
using (var content = new MemoryStream())
{
var jpegEncoder = GetEncoder(ImageFormat.Jpeg);
previewImage.Save(content, jpegEncoder,
new EncoderParameters
{
Param = new[] { new EncoderParameter(Encoder.Quality, jpegQuality) },
});
content.Flush();
// return the stream
return new ImagePreviewGeneratorDto
{
Preview = content.ToArray(),
Width = previewWidth,
Height = previewHeight
};
}
}
}
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
var codecs = ImageCodecInfo.GetImageDecoders();
return codecs.FirstOrDefault(codec => codec.FormatID == format.Guid);
}
#region IDisposable
private bool _disposed;
~GdiPlusImagePreviewGenerator()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// free managed resources
if (_image != null)
{
_image.Dispose();
_image = null;
}
}
// free unmanaged resources
_disposed = true;
}
#endregion
}
}
I noticed that BitmapCacheOption.None greatly increases performance when dealing with batch processing.

Load an image from a url into a PictureBox

I want to load an image into a PictureBox. This is the image I want to load: http://www.gravatar.com/avatar/6810d91caff032b202c50701dd3af745?d=identicon&r=PG
How do I do this?
The PictureBox.Load(string url) method "sets the ImageLocation to the specified URL and displays the image indicated."
Try this:
var request = WebRequest.Create("http://www.gravatar.com/avatar/6810d91caff032b202c50701dd3af745?d=identicon&r=PG");
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
pictureBox1.Image = Bitmap.FromStream(stream);
}
yourPictureBox.ImageLocation = "http://www.gravatar.com/avatar/6810d91caff032b202c50701dd3af745?d=identicon&r=PG"
Here's the solution I use. I can't remember why I couldn't just use the PictureBox.Load methods. I'm pretty sure it's because I wanted to properly scale & center the downloaded image into the PictureBox control. If I recall, all the scaling options on PictureBox either stretch the image, or will resize the PictureBox to fit the image. I wanted a properly scaled and centered image in the size I set for PictureBox.
Now, I just need to make a async version...
Here's my methods:
#region Image Utilities
/// <summary>
/// Loads an image from a URL into a Bitmap object.
/// Currently as written if there is an error during downloading of the image, no exception is thrown.
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static Bitmap LoadPicture(string url)
{
System.Net.HttpWebRequest wreq;
System.Net.HttpWebResponse wresp;
Stream mystream;
Bitmap bmp;
bmp = null;
mystream = null;
wresp = null;
try
{
wreq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);
wreq.AllowWriteStreamBuffering = true;
wresp = (System.Net.HttpWebResponse)wreq.GetResponse();
if ((mystream = wresp.GetResponseStream()) != null)
bmp = new Bitmap(mystream);
}
catch
{
// Do nothing...
}
finally
{
if (mystream != null)
mystream.Close();
if (wresp != null)
wresp.Close();
}
return (bmp);
}
/// <summary>
/// Takes in an image, scales it maintaining the proper aspect ratio of the image such it fits in the PictureBox's canvas size and loads the image into picture box.
/// Has an optional param to center the image in the picture box if it's smaller then canvas size.
/// </summary>
/// <param name="image">The Image you want to load, see LoadPicture</param>
/// <param name="canvas">The canvas you want the picture to load into</param>
/// <param name="centerImage"></param>
/// <returns></returns>
public static Image ResizeImage(Image image, PictureBox canvas, bool centerImage )
{
if (image == null || canvas == null)
{
return null;
}
int canvasWidth = canvas.Size.Width;
int canvasHeight = canvas.Size.Height;
int originalWidth = image.Size.Width;
int originalHeight = image.Size.Height;
System.Drawing.Image thumbnail =
new Bitmap(canvasWidth, canvasHeight); // changed parm names
System.Drawing.Graphics graphic =
System.Drawing.Graphics.FromImage(thumbnail);
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;
/* ------------------ new code --------------- */
// Figure out the ratio
double ratioX = (double)canvasWidth / (double)originalWidth;
double ratioY = (double)canvasHeight / (double)originalHeight;
double ratio = ratioX < ratioY ? ratioX : ratioY; // use whichever multiplier is smaller
// now we can get the new height and width
int newHeight = Convert.ToInt32(originalHeight * ratio);
int newWidth = Convert.ToInt32(originalWidth * ratio);
// Now calculate the X,Y position of the upper-left corner
// (one of these will always be zero)
int posX = Convert.ToInt32((canvasWidth - (image.Width * ratio)) / 2);
int posY = Convert.ToInt32((canvasHeight - (image.Height * ratio)) / 2);
if (!centerImage)
{
posX = 0;
posY = 0;
}
graphic.Clear(Color.White); // white padding
graphic.DrawImage(image, posX, posY, newWidth, newHeight);
/* ------------- end new code ---------------- */
System.Drawing.Imaging.ImageCodecInfo[] info =
ImageCodecInfo.GetImageEncoders();
EncoderParameters encoderParameters;
encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality,
100L);
Stream s = new System.IO.MemoryStream();
thumbnail.Save(s, info[1],
encoderParameters);
return Image.FromStream(s);
}
#endregion
Here's the required includes. (Some might be needed by other code, but including all to be safe)
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using System.Drawing;
How I generally use it:
ImageUtil.ResizeImage(ImageUtil.LoadPicture( "http://someurl/img.jpg", pictureBox1, true);
If you are trying to load the image at your form_load, it's a better idea to use the code
pictureBox1.LoadAsync(#"http://google.com/test.png");
not only loading from web but also no lag in your form loading.

Categories