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

发布于 2024-07-30 07:53:05 字数 659 浏览 7 评论 0原文

好吧,我很抱歉,这可能是一个菜鸟问题,但我有点卡住了。

所以我正在做的(在我的 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+."

我知道图像是“ok”,因为我可以将其写入浏览器并查看调整大小的图像,只有当我尝试保存它时才会收到错误。 我有点新,被困住了,我这样做完全错了吗? (嗯,我想这很明显,但你知道我的意思......)

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:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荒岛晴空 2024-08-06 07:53:07

试试这个代码...我使用了相同的代码来调整图像大小并保存。

    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

Try this code... I have used the same code for resizing image and saving.

    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

落墨 2024-08-06 07:53:07

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

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

这种方法保证文件在 using 块末尾关闭

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 :

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

傲性难收 2024-08-06 07:53:07

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

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

我发现我需要跟踪属于我的位图的 MemoryStream 并将它们全部放在一起。 调整图像大小会产生一个带有新位图图像的新 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;

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.

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.

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.

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.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文