【问题标题】:Create a new image on the file system from System.Drawing.Image?从 System.Drawing.Image 在文件系统上创建一个新图像?
【发布时间】:2010-11-16 20:04:27
【问题描述】:

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

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

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

【问题讨论】:

    标签: c# asp.net gdi+ thumbnails image-resizing


    【解决方案1】:

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

        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

    【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      支持原始图像的原始流是否可能已关闭?如果位图后面的流已关闭,您将开始收到 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 中,从中加载图像,然后将两者都粘贴到这个容器中。无论我在哪里从旧图像创建新图像,我总是将流和图像保持在一起。

      我希望这会有所帮助。

      编辑:我也有兴趣了解您如何调整图像大小。这是我做我们的方式的一个sn-p:

      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;
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多