C# 图形对象到图像文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1147156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Graphics object to image file
提问by niaher
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 graphicsobject. The question is - how do I save it to a file?
现在我假设我得到的裁剪/调整大小的图像存储在图形对象中。问题是 - 如何将其保存到文件中?
采纳答案by Fredrik M?rk
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.
Graphics
您从中获得的对象Graphics.FromImage
是图像的绘图表面。因此,您可以在完成后简单地保存图像对象。
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.
请注意,在 jpg 图像上重复执行此操作可能不是一件好事;图像每次都会重新编码,由于 jpg 使用破坏性压缩方法,因此每次都会损失一些图像质量。不过,如果这是每个图像一次的操作,我不会担心。
回答by Guffa
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.
不,Graphics
对象不包含任何图像数据,它用于在画布上绘制,通常是屏幕或Bitmap
对象。
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:
因此,您需要创建一个Bitmap
具有正确大小的对象以供绘制,并Graphics
为该位图创建对象。然后你可以保存它。请记住,IDisposable
应该处理对象实现,例如使用using
子句:
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);
}
}
回答by user1830791
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.
这不是对 OP 问题的直接回答,但它是一个经常被忽视的工具,如果证明有必要,它可以让您以不同的方式处理事情。
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#:
人们常说不可能获得 Graphics 对象的内容。这根本不是真的。通过正确的方法,您可以使用 HDC 和 BitBlt 访问画布上的数据。这是使用 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;
}