从System.Drawing.Image创建一个新的文件系统图像?

4

好的,我很抱歉,这可能是一个初学者的问题,但我有点困惑。

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

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

然后我进行一些调整大小的操作:

tempImage = my awesomeResizingFunction(tempImage, newSize);

我打算使用以下代码将其保存到文件系统的其他位置:

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

我得到的错误是:

"A generic error occurred in GDI+."

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

3个回答

8

尝试使用以下代码... 我已经使用相同的代码来调整图像大小并保存。

    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);

其中fupProduct是文件上传控件的ID。


1
你可以使用Path.GetExtension来改进它,而不是使用IndexOf('.'),不过你需要稍微修改一下switch语句 http://msdn.microsoft.com/en-us/library/system.io.path.getextension.aspx - RichardOD
1
请注意(http://msdn.microsoft.com/en-us/library/system.drawing.aspx) > System.Drawing命名空间中的类不支持在Windows或ASP.NET服务中使用。 - Marc Gravell

6

您确定原始路径和新路径指向不同的文件吗?当您使用Image.FromFile时,文件会保持锁定状态,直到您在Image上调用Dispose,这可能导致您提到的异常。您可以改为以下方式加载图像:

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

这种方法确保文件在使用块结束时关闭。

0

原始图像后面的流是否已关闭?如果Bitmap后面的流已关闭,则会出现GDI+错误。当我们将图像处理添加到网站时,我经常遇到这种情况。

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

我发现我需要跟踪属于我的位图的MemoryStreams并将它们全部保持在一起。调整图像大小会导致具有新Bitmap图像的新MemoryStream。

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

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;
    }
}

现在,我正在处理上传到我们网站的图像,我发现当Asp.Net回收与请求相关联的流时,突然所有的图像操作都开始出现问题。因此,我的解决方案,无论这是否是最好的方法,都是将上传流中的数据复制到自己的MemoryStream中,从中加载图像,并将两者都放入此容器中。无论我从旧图像创建新图像的地方,在哪里,我总是保持流和图像在一起。

希望这有所帮助。

编辑:我也很想看看您如何调整图像大小。以下是我如何完成我们的代码片段:

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;

请注意(http://msdn.microsoft.com/en-us/library/system.drawing.aspx) > System.Drawing命名空间中的类不支持在Windows或ASP.NET服务中使用。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接