I would like to crop and resize my image. Here is my code:
Image image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle.jpg");
// Crop and resize the image.
Rectangle destination = new Rectangle(0, 0, 200, 120);
Graphics graphic = Graphics.FromImage(image);
graphic.DrawImage(image, destination, int.Parse(X1.Value), int.Parse(Y1.Value), int.Parse(Width.Value), int.Parse(Height.Value), GraphicsUnit.Pixel);
Now I assume that my resulting cropped/resized image is stored in the graphics object. The question is - how do I save it to a file?
Rectangle destination = new Rectangle(0, 0, 200, 120); Graphics graphic = Graphics. FromImage(image); graphic. DrawImage(image, destination, int.
The Graphics object represents a GDI+ drawing surface, and is the object that is used to create graphical images. There are two steps in working with graphics: Creating a Graphics object. Using the Graphics object to draw lines and shapes, render text, or display and manipulate images.
Save(String, ImageFormat) Saves this Image to the specified file in the specified format.
The Graphics
object that you get from Graphics.FromImage
is a drawing surface for the image. So you can simply save the image object when you are done.
string fileName = AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle.jpg");
using (Image image = Image.FromFile(fileName)
{
using (Graphics graphic = Graphics.FromImage(image))
{
// Crop and resize the image.
Rectangle destination = new Rectangle(0, 0, 200, 120);
graphic.DrawImage(image, destination, int.Parse(X1.Value), int.Parse(Y1.Value), int.Parse(Width.Value), int.Parse(Height.Value), GraphicsUnit.Pixel);
}
image.Save(fileName);
}
Beware though that doing this repeatedly on a jpg image may not be a good thing; the image is re-encoded each time and since jpg uses a destructive compression method you will lose some image quality each time. I wouldn't worry about that if this is a once-per-image operation though.
No, the Graphics
object doesn't contain any image data, it's used to draw on a canvas, which usually is the screen or a Bitmap
object.
So, you need to create a Bitmap
object with the correct size to draw on, and create the Graphics
object for that bitmap. Then you can save it. Remember that object implementing IDisposable
should be disposed, for example using the using
clause:
using (Image image = Image.FromFile(AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle.jpg")) {
// Create bitmap
using (Bitmap newImage = new Bitmap(200, 120)) {
// Crop and resize the image.
Rectangle destination = new Rectangle(0, 0, 200, 120);
using (Graphics graphic = Graphics.FromImage(newImage)) {
graphic.DrawImage(image, destination, int.Parse(X1.Value), int.Parse(Y1.Value), int.Parse(Width.Value), int.Parse(Height.Value), GraphicsUnit.Pixel);
}
newImage.Save(AppDomain.CurrentDomain.BaseDirectory + "Cropper/tests/castle_icon.jpg", ImageFormat.Jpeg);
}
}
This is not a direct answer to the OP's question, but it is an often-overlooked tool that can allow you to approach things in a different way, should that prove necessary.
It is often said that it's not possible to get at the content of a Graphics object. This is not true at all. With the right approach you can access data on a canvas using HDC and BitBlt. Here is one way to do it using C#:
enum TernaryRasterOperations : uint
{
/// <summary>dest = source</summary>
SRCCOPY = 0x00CC0020,
/// <summary>dest = source OR dest</summary>
SRCPAINT = 0x00EE0086,
/// <summary>dest = source AND dest</summary>
SRCAND = 0x008800C6,
/// <summary>dest = source XOR dest</summary>
SRCINVERT = 0x00660046,
/// <summary>dest = source AND (NOT dest)</summary>
SRCERASE = 0x00440328,
/// <summary>dest = (NOT source)</summary>
NOTSRCCOPY = 0x00330008,
/// <summary>dest = (NOT src) AND (NOT dest)</summary>
NOTSRCERASE = 0x001100A6,
/// <summary>dest = (source AND pattern)</summary>
MERGECOPY = 0x00C000CA,
/// <summary>dest = (NOT source) OR dest</summary>
MERGEPAINT = 0x00BB0226,
/// <summary>dest = pattern</summary>
PATCOPY = 0x00F00021,
/// <summary>dest = DPSnoo</summary>
PATPAINT = 0x00FB0A09,
/// <summary>dest = pattern XOR dest</summary>
PATINVERT = 0x005A0049,
/// <summary>dest = (NOT dest)</summary>
DSTINVERT = 0x00550009,
/// <summary>dest = BLACK</summary>
BLACKNESS = 0x00000042,
/// <summary>dest = WHITE</summary>
WHITENESS = 0x00FF0062,
/// <summary>
/// Capture window as seen on screen. This includes layered windows
/// such as WPF windows with AllowsTransparency="true"
/// </summary>
CAPTUREBLT = 0x40000000
}
[DllImport("gdi32.dll", EntryPoint = "BitBlt", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool BitBlt([In] IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, [In] IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
public static Bitmap CopyGraphicsContent(Graphics source, Rectangle rect)
{
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
using (Graphics dest = Graphics.FromImage(bmp))
{
IntPtr hdcSource = source.GetHdc();
IntPtr hdcDest = dest.GetHdc();
BitBlt(hdcDest, 0, 0, rect.Width, rect.Height, hdcSource, rect.X, rect.Y, TernaryRasterOperations.SRCCOPY);
source.ReleaseHdc(hdcSource);
dest.ReleaseHdc(hdcDest);
}
return bmp;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With