C# 从 System.Drawing.Image 在文件系统上创建一个新图像?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1230090/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 13:58:39  来源:igfitidea点击:

Create a new image on the file system from System.Drawing.Image?

c#asp.netgdi+thumbnailsimage-resizing

提问by onekidney

Ok, I'm sorry, this is probably a noob question but I'm kinda stuck.

好的,对不起,这可能是一个菜鸟问题,但我有点卡住了。

So what I'm doing (on my asp.net application) is loading an image from the file system:

所以我正在做的(在我的 asp.net 应用程序上)是从文件系统加载图像:

System.Drawing.Image tempImage;
tempImage = System.Drawing.Image.FromFile(HttpContext.Server.MapPath(originalPath));

Then I do some resizing:

然后我做一些调整大小:

tempImage = my awesomeResizingFunction(tempImage, newSize);

and intend to save it to the file system in another location using this:

并打算使用以下命令将其保存到另一个位置的文件系统中:

string newPath = "/myAwesomePath/newImageName.jpg";
tempImage.Save(newPath);

and what I get is this error:

我得到的是这个错误:

"A generic error occurred in GDI+."

I know the image is "ok" because I can write it out to the browser and see the resized image, I only get the error when I try to save it. I'm kinda new and stuck, am I doing this totally wrong? (Well, i guess that's obvious but you know what I mean...)

我知道图像“正常”,因为我可以将其写出到浏览器并查看调整后的图像,但只有在尝试保存时才会出现错误。我有点新,卡住了,我这样做是完全错误的吗?(嗯,我想这很明显,但你知道我的意思......)

采纳答案by Muhammad Akhtar

plz try this code...I have used the same code for resizing image and saving. if you get any problem then plz let me know.

请试试这个代码......我使用了相同的代码来调整图像大小和保存。如果您遇到任何问题,请告诉我。

System.Drawing.Bitmap bmpOut = new System.Drawing.Bitmap(NewWidth, NewHeight);
    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmpOut);
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
    g.FillRectangle(System.Drawing.Brushes.White, 0, 0, NewWidth, NewHeight);
    g.DrawImage(new System.Drawing.Bitmap(fupProduct.PostedFile.InputStream), 0, 0, NewWidth, NewHeight);
    MemoryStream stream = new MemoryStream();
    switch (fupProduct.FileName.Substring(fupProduct.FileName.IndexOf('.') + 1).ToLower())
    {
        case "jpg":
            bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            break;
        case "jpeg":
            bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            break;
        case "tiff":
            bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff);
            break;
        case "png":
            bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
            break;
        case "gif":
            bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
            break;
    }
    String saveImagePath = Server.MapPath("../") + "Images/Thumbnail/" + fupProduct.FileName.Substring(fupProduct.FileName.IndexOf('.'));
    bmpOut.Save(saveImagePath);

where fupProduct is fileupload control ID

其中 fupProduct 是文件上传控件 ID

回答by Amy

Is it possible the original stream backing the original image has been closed? If the stream behind a Bitmap has been closed, you start getting GDI+ errors. I ran into this a lot when we added image processing to our website.

支持原始图像的原始流是否可能已关闭?如果位图后面的流已关闭,您将开始收到 GDI+ 错误。当我们向我们的网站添加图像处理时,我经常遇到这种情况。

If you open up the Bitmap object in the Visual Studio debugger, do you see exceptions instead of the values of the properties? If so, it's not a problem with the save operation, but the GDI+ layer has lost the ability to process the object, period.

如果您在 Visual Studio 调试器中打开 Bitmap 对象,您是否看到异常而不是属性值?如果是这样,那不是保存操作的问题,只是 GDI+ 层失去了处理对象的能力,句号。

What I found was I needed to keep track of the MemoryStreams belonging to my Bitmaps and keep them all together. Resizing an image resulted in a new MemoryStream with a new Bitmap image.

我发现我需要跟踪属于我的位图的 MemoryStreams 并将它们保存在一起。调整图像大小会产生带有新位图图像的新 MemoryStream。

I ended up creating this simple class (trimmed some extra properties unneeded here):

我最终创建了这个简单的类(修剪了一些不需要的额外属性):

public class UploadedImage : IDisposable
{
    private Bitmap _img = null;
    private Stream _baseStream = null;


    /// <summary>
    /// The image object.  This must always belong to BaseStream, or weird things can happen.
    /// </summary>
    public Bitmap Img
    {
        [DebuggerStepThrough]
        get { return _img; }
        [DebuggerStepThrough]
        set { _img = value; }
    }

    /// <summary>
    /// The stream that stores the image.  This must ALWAYS belong to Img, or weird things can happen.
    /// </summary>
    public Stream BaseStream
    {
        [DebuggerStepThrough]
        get { return _baseStream; }
        [DebuggerStepThrough]
        set { _baseStream = value; }
    }

    [DebuggerStepThrough]
    public void Dispose()
    {
        if (Img != null)
            Img.Dispose();

        if (BaseStream != null)
            BaseStream.Close();

        _attached = false;
    }
}

Now, I was dealing with images uploaded to our website, and what I found was that when Asp.Net recycled the stream attached to the Request, all the sudden image operations started flipping out. So, my solution, whether this was the best way to do it or not, was to copy the data from the upload stream to my own MemoryStream, load the image from that, and stick both into this container. And wherever I created a new image from an old one, I always kept the stream and the image together.

现在,我正在处理上传到我们网站的图像,我发现当 Asp.Net 回收附加到请求的流时,所有突然的图像操作开始翻转。所以,我的解决方案,无论这是否是最好的方法,都是将数据从上传流复制到我自己的 MemoryStream,从中加载图像,然后将两者都粘贴到这个容器中。无论我在哪里从旧图像创建新图像,我总是将流和图像放在一起。

I hope this helps.

我希望这有帮助。

EDIT: I'm also interested in seeing how you're doing the image resizing. This is a snippet of how I did ours:

编辑:我也有兴趣了解您如何调整图像大小。这是我如何做我们的一个片段:

temp = new Bitmap(newWidth, newHeight, PIXEL_FORMAT);
temp.SetResolution(newHorizontalRes, newVerticalRes);
gr = Graphics.FromImage(temp);

//
// This copies the active frame from 'img' to the new 'temp' bitmap.
// Also resizes it and makes it super shiny.  Sparkle on, mr image dude.
// 
Rectangle rect = new Rectangle(0, 0, newWidth, newHeight);
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.SmoothingMode = SmoothingMode.HighSpeed;
gr.PageUnit = GraphicsUnit.Pixel;
gr.DrawImage(img, rect);

//
// Image copied onto the new bitmap.  Save the bitmap to a fresh memory stream.
//
retval = new UploadedImage();
retval.BaseStream = (Stream)(new MemoryStream());

temp.Save(retval.BaseStream, ImageFormat.Jpeg);
retval.Img = temp;

回答by Thomas Levesque

Are you sure that the originalPath and newPath point to different files ? When you use Image.FromFile, the file remains locked until you call Dispose on the Image, which can lead to the exception you mentioned. You could load the image like that instead :

您确定 originalPath 和 newPath 指向不同的文件吗?当您使用 Image.FromFile 时,该文件将保持锁定状态,直到您对 Image 调用 Dispose,这可能会导致您提到的异常。你可以像这样加载图像:

Image tempImage = null;
using (FileStream fs = new FileStream(originalPath, FileMode.Open, FileAccess.Read))
{
    tempImage = Image.FromStream(fs);
}
...

This approach guarantees that the file is closed at the end of the using block

这种方法保证文件在 using 块结束时关闭