GDI +的Bitmap.Save方法中发生一般错误


69

我正在上载该图像的缩略图副本并将其保存在缩略图文件夹中。

我正在使用以下链接:

http://weblogs.asp.net/markmcdonnell/archive/2008/03/09/resize-image-before-uploading-to-server.aspx

newBMP.Save(directory + "tn_" + filename);   

导致异常“ GDI +中发生一般错误”。

我尝试授予文件夹权限,还尝试在保存时使用新的单独bmp对象。

编辑:

    protected void ResizeAndSave(PropBannerImage objPropBannerImage)
    {
        // Create a bitmap of the content of the fileUpload control in memory
        Bitmap originalBMP = new Bitmap(fuImage.FileContent);

        // Calculate the new image dimensions
        int origWidth = originalBMP.Width;
        int origHeight = originalBMP.Height;
        int sngRatio = origWidth / origHeight;
        int thumbWidth = 100;
        int thumbHeight = thumbWidth / sngRatio;

        int bannerWidth = 100;
        int bannerHeight = bannerWidth / sngRatio;

        // Create a new bitmap which will hold the previous resized bitmap
        Bitmap thumbBMP = new Bitmap(originalBMP, thumbWidth, thumbHeight);
        Bitmap bannerBMP = new Bitmap(originalBMP, bannerWidth, bannerHeight);

        // Create a graphic based on the new bitmap
        Graphics oGraphics = Graphics.FromImage(thumbBMP);
        // Set the properties for the new graphic file
        oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

        // Draw the new graphic based on the resized bitmap
        oGraphics.DrawImage(originalBMP, 0, 0, thumbWidth, thumbHeight);

        Bitmap newBitmap = new Bitmap(thumbBMP);
        thumbBMP.Dispose();
        thumbBMP = null;

        // Save the new graphic file to the server
        newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);

        oGraphics = Graphics.FromImage(bannerBMP);
        // Set the properties for the new graphic file
        oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

        // Draw the new graphic based on the resized bitmap
        oGraphics.DrawImage(originalBMP, 0, 0, bannerWidth, bannerHeight);
        // Save the new graphic file to the server
        bannerBMP.Save("~/image/" + objPropBannerImage.ImageId + ".jpg");


        // Once finished with the bitmap objects, we deallocate them.
        originalBMP.Dispose();

        bannerBMP.Dispose();
        oGraphics.Dispose();
    }

Answers:


100

从文件构造位图对象或图像对象时,文件在对象的生存期内保持锁定状态。如此一来,您将无法更改图像并将其保存回原始位置。 http://support.microsoft.com/?id=814675

GDI +,JPEG图像到MemoryStream中发生一般错误

Image.Save(..)引发GDI +异常,因为内存流已关闭

http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html

编辑:
只是从内存写入...

保存到“中间”内存流,应该可以

例如尝试这个-替换

    Bitmap newBitmap = new Bitmap(thumbBMP);
    thumbBMP.Dispose();
    thumbBMP = null;
    newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);

与类似:

string outputFileName = "...";
using (MemoryStream memory = new MemoryStream())
{
    using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
    {
        thumbBMP.Save(memory, ImageFormat.Jpeg);
        byte[] bytes = memory.ToArray();
        fs.Write(bytes, 0, bytes.Length);
    }
}

谢谢,使用这些我得到了它的工作。我正在重新发布代码。
donstack 2013年

2
一个相关的问题,也许会对某人有帮助-我已经在打开位图时收到“ GDI +中发生了一般错误” 。并且仅在远程Web服务器上,而不在我的本地测试机上。事实证明,存在于Azure IIS服务器上的GDI +无法处理GIMP生成的新格式BMP。我不得不a)用Paint重新保存BMP b)使用未压缩的PNG代替c)使用GIMP另存为24bit BMP(质量较差)
Andrew

不确定我在修补的项目中做错了什么...但是由于某种原因,MemoryStream / FileStream组合为我工作(有一些细微的变化以解决我的特定方法调用)。这是5岁的帖子的+1。
WernerCD '18

1
我知道@WernerCD,这个问题(和解决方法)有点违反直觉-但是对此基础(在许多情况下,具体取决于具体情况)的过于简单的解释是,您需要脱离原始的位图对象(及其引用) ,内存流对此有所帮助。
NSGaga-大部分时间都未激活'18

@NSGaga我使用的是MS(我将PDF中的文件拉到Bitmap / Image对象中)...但是当我尝试将Bitmap / Image对象拉出并放到磁盘上时,它本身就处于崩溃状态。该Memory /FileStreamVSbitmap.Save(...)是我觉得反直觉的步骤,为我工作。我认为。无论如何,这给了我在解决问题的HOURS之后一直在寻找的动力。
WernerCD '18

51

如果您传递的路径Bitmap.Save()无效(文件夹不存在等),则会显示此错误消息。


7
当然,我就是这种情况,我投了赞成票,所以没有其他人应该再浪费时间了。还请确保您的路径也包括文件名。
ahsant

21
错误无法报告如此基本的问题是多么愚蠢
Dan Hastings

12
    // Once finished with the bitmap objects, we deallocate them.
    originalBMP.Dispose();

    bannerBMP.Dispose();
    oGraphics.Dispose();

这是一种编程风格,您迟早会后悔。快敲门,你忘了一个。您没有处置newBitmap。这将保持文件锁定,直到垃圾收集器运行为止。如果它没有运行,那么第二次尝试保存到同一文件时,您将得到klaboom。GDI +异常情况太悲惨,无法给出良好的诊断,因此造成了严重的头痛。除了数以千计的提及该错误的可查询帖子之外,

始终喜欢使用using语句。即使代码抛出异常,也不会忘记处理对象。

using (var newBitmap = new Bitmap(thumbBMP)) {
    newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
}

尽管还不清楚为什么还要创建一个新的位图,但保存thumbBMP应该已经足够了。顺便说一句,用爱给其余的一次性物品一样。


简单的答案是最好的!很好的建议。
Ferd

8

就我而言,位图图像文件已存在于系统驱动器中,因此我的应用抛出了错误“ GDI +中发生了通用错误”

  1. 验证目标文件夹是否存在
  2. 确认目标文件夹中没有相同名称的文件

7

检查文件夹在图像保存位置的权限右键单击文件夹,然后转到:

属性>安全性>编辑>添加-选择“所有人”,然后选中允许“完全控制”


5

我遇到了同样的问题在使用MVC应用程序时,保存时在GDI +中发生了一般性错误,由于出现了错误的保存图像路径,我更正了保存路径,因此对我来说很好,这是我收到此错误的原因。

img1.Save(Server.MapPath("/Upload/test.png", System.Drawing.Imaging.ImageFormat.Png);


--Above code need one change, as you need to put close brackets on Server.MapPath() method after writing its param.

像这样-

img1.Save(Server.MapPath("/Upload/test.png"), System.Drawing.Imaging.ImageFormat.Png);

3

我总是检查/测试这些:

  • 路径+文件名是否包含给定文件系统的非法字符?
  • 该文件已经存在吗?(坏)
  • 该路径是否已经存在?(好)
  • 如果路径是相对的:我是否希望它在正确的父目录中(主要是 bin/Debug;-)中)?
  • 该程序的路径可写,并且以哪个用户身份运行?(这里的服务可能很棘手!)
  • 完整路径是否真的,真的不包含非法字符?(一些Unicode字符接近不可见)

Bitmap.Save()除了这个列表,我从来没有任何问题。


3

由于以下几点而发生GDI +异常

  1. 资料夹存取问题
  2. 图像缺少属性

如果文件夹有问题-请提供对应用程序的访问权限如果缺少属性,请使用以下代码

代码1

using (Bitmap bmp = new Bitmap(webStream))
{
     using (Bitmap newImage = new Bitmap(bmp))
     {
         newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
     }
}

代码2

using (Bitmap bmp = new Bitmap(webStream))
{

     using (Bitmap newImage = new Bitmap(bmp))
     {
        newImage.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
        Rectangle lockedRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
        BitmapData bmpData = newImage.LockBits(lockedRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
        bmpData.PixelFormat = bmp.PixelFormat;
        newImage.UnlockBits(bmpData);
        using (Graphics gr = Graphics.FromImage(newImage))
         {
             gr.SmoothingMode = SmoothingMode.HighQuality;
             gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
             gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
         }

         foreach (var item in bmp.PropertyItems)
         {
             newImage.SetPropertyItem(item);
         }
         newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
    }
}

代码1和代码2之间的区别

代码-1:它将仅创建图像并可以在常规图像查看器上打开它

  • 图片无法在Photoshop中打开
  • 图片大小将是原来的两倍

代码-2:在图像编辑工具中打开图像使用代码

通过使用代码1,它仅创建图像,但不分配图像标记。


1

我使用FileStream使其正常工作,并从这些
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html http://csharpdotnetfreak.blogspot.com/2010/中获取帮助02 / resize-image-upload-ms-sql-database.html

System.Drawing.Image imageToBeResized = System.Drawing.Image.FromStream(fuImage.PostedFile.InputStream);
        int imageHeight = imageToBeResized.Height;
        int imageWidth = imageToBeResized.Width;
        int maxHeight = 240;
        int maxWidth = 320;
        imageHeight = (imageHeight * maxWidth) / imageWidth;
        imageWidth = maxWidth;

        if (imageHeight > maxHeight)
        {
            imageWidth = (imageWidth * maxHeight) / imageHeight;
            imageHeight = maxHeight;
        }

        Bitmap bitmap = new Bitmap(imageToBeResized, imageWidth, imageHeight);
        System.IO.MemoryStream stream = new MemoryStream();
        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
        stream.Position = 0;
        byte[] image = new byte[stream.Length + 1];
        stream.Read(image, 0, image.Length);
        System.IO.FileStream fs
= new System.IO.FileStream(Server.MapPath("~/image/a.jpg"), System.IO.FileMode.Create
, System.IO.FileAccess.ReadWrite);
            fs.Write(image, 0, image.Length);


1

除了相同的例外,我还有另一个问题。

简而言之:

在调用之前,请确保没有处置Bitmap对象。Stream.Save

全文:

有一种方法返回了一个Bitmap对象,该对象是MemoryStream通过以下方式构建的:

private Bitmap getImage(byte[] imageBinaryData){
    .
    .
    .
    Bitmap image;
    using (var stream = new MemoryStream(imageBinaryData))
    {
        image = new Bitmap(stream);
    }
    return image;
}

然后有人使用返回的图像将其保存为文件

image.Save(path);

问题在于,当尝试保存图像时,原始流已经被丢弃,并抛出了GDI +异常。

解决此问题的方法是在Bitmap不处理流本身而是返回Bitmap对象的情况下返回。

private Bitmap getImage(byte[] imageBinaryData){
   .
   .
   .
   Bitmap image;
   var stream = new MemoryStream(imageBinaryData))
   image = new Bitmap(stream);

   return image;
}

然后:

using (var image = getImage(binData))
{
   image.Save(path);
}

这是一个很好的答案,可惜它被埋在许多与错误道路有关的重复答案之下。基础流无法销毁。另一种方法是从旧的位图创建新的位图:new Bitmap(oldBitmap).Save(...)
Corey Alix


0
    I used below logic while saving a .png format. This is to ensure the file is already existing or not.. if exist then saving it by adding 1 in the filename

Bitmap btImage = new Bitmap("D:\\Oldfoldername\\filename.png");
    string path="D:\\Newfoldername\\filename.png";
            int Count=0;
                if (System.IO.File.Exists(path))
                {
                    do
                    {
                        path = "D:\\Newfoldername\\filename"+"_"+ ++Count + ".png";                    
                    } while (System.IO.File.Exists(path));
                }

                btImage.Save(path, System.Drawing.Imaging.ImageFormat.Png);

0

尝试将Tiff图像转换为Jpeg时遇到此错误。对我来说,问题源于tiff尺寸太大。最高约62000像素的像素都可以,但超过此尺寸的像素都可以产生错误。


0

对我来说,这是保存图像时的路径问题。

int count = Directory.EnumerateFiles(System.Web.HttpContext.Current.Server.MapPath("~/images/savedimages"), "*").Count();

var img = Base64ToImage(imgRaw);

string path = "images/savedimages/upImages" + (count + 1) + ".png";

img.Save(Path.Combine(System.Web.HttpContext.Current.Server.MapPath(path)));

return path;

所以我通过添加以下正斜杠来修复它

String path = "images/savedimages....

应该

String path = "/images/savedimages....

希望可以帮助任何陷入困境的人!


0

来自msdn:public void Save (string filename);这对我来说非常令人惊讶,因为我们不必传递文件名,而必须传递文件名以及路径,例如:MyDirectory/MyImage.jpeg,这里MyImage.jpeg实际上还不存在,但是我们的文件将使用该名称保存。

这里的另一个重要点是,如果您Save()在Web应用程序中使用Server.MapPath(),则与其一起使用,它基本上只是返回传入的虚拟路径的物理路径。类似:image.Save(Server.MapPath("~/images/im111.jpeg"));


0

我用这个解决方案

int G = 0;

private void toolStripMenuItem17_Click(object sender, EventArgs e)
{
  Directory.CreateDirectory("picture");// هذه العملية للرسم بدون ان يحذف بقية الرسومات
  G = G + 1;
  FormScreen();
  memoryImage1.Save("picture\\picture" + G.ToString() + ".jpg");
  pictureBox1.Image = Image.FromFile("picture\\picture" + G.ToString() + ".jpg");
}

您可以编辑帖子,而不必删除并重新发布新帖子。
LarsTech
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.