代码之家  ›  专栏  ›  技术社区  ›  scubasteve

image.save()对从流加载的图像(image.from stream())引发外部异常

  •  4
  • scubasteve  · 技术社区  · 14 年前

    我正在跟踪一个棘手的问题,我缩小了问题的范围,并意识到只有在处理image.fromstream()返回的图像实例时才会发生这种情况。我有一个实用方法,它使用流从文件中返回一个图像实例,所以我没有打开文件句柄。这是实用方法(没有什么特别的):

    public static Image ImageFromFileReleaseHandle(string filename)
    {
        using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
        {
            return Image.FromStream(fs);
        }
    }
    

    当我试图保存从上述方法加载的图像时,我得到了interopservices.externalException“gdi+中发生了一般性错误”。下面的代码示例将演示这一点:

    private void button6_Click(object sender, EventArgs e)
    {
        var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";
    
        //  Get an Image instance
        Image image;
        using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
        {
            image = Image.FromStream(fs);
        }
    
        //  Save to a temp file - this is the code that throws the exception
        image.Save(Path.GetTempFileName());
    }
    

    如果我使用image.fromfile()加载图像,我就不会保存任何问题:

    private void button6_Click(object sender, EventArgs e)
    {
        var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";
    
        //  Get an Image instance
        Image image = Image.FromFile(filename);
    
        //  Save to a temp file - this is the code that throws the exception
        image.Save(Path.GetTempFileName());
    }
    

    我想不出任何有帮助的附加信息。希望我的代码示例足够简单,您可以清楚地看到问题。

    谢谢, 史蒂夫

    4 回复  |  直到 12 年前
        1
  •  1
  •   msarchet    14 年前

    试试这个

    //  Get an Image instance
        Image image;
        using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
        {
            image = Image.FromStream(fs);
            //  Save to a temp file - this is the code that throws the exception
            image.Save(Path.GetTempFileName());
        }
    

    我认为使用块会给你带来问题

        2
  •  3
  •   Jeff Ogata    14 年前

    根据 documentation :

    您必须在图像的生命周期内保持流的打开状态。

    尝试在using块内调用save,以验证如果流仍然打开,则不会引发异常。

        3
  •  0
  •   scubasteve    14 年前

    基于目前为止的建议和评论以及我自己的附加阅读,我认为我有一个可行的解决方案。基本上问题是我不能关闭流。好的,但是我也不能让一个文件流在没有保证它会被正确关闭的情况下打开。

    相反,我将文件读取到缓冲区中,然后创建一个memoryStream并将其传递给image.fromstream()。

    var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";
    
    byte[] imageData = FileUtils.ReadWholeFileBytes(filename);
    Image image = Image.FromStream(new MemoryStream(imageData));
    
    //  dump the buffer to test if this upsets the Memory Stream.  I need to read more
    //  about MemoryStream and how it may keep the GC from cleaning up it's underlying data
    imageData = null;        
    
    //  Save to a temp file
    image.Save(Path.GetTempFileName());
    

    谢谢大家的建议和问题。

        4
  •  0
  •   Adi Lester    12 年前

    我也有同样的问题,但不是用 FileStream 我只有一个 MemoryStream ,因为我正在从数据库下载图像。当我第一次在数据库中保存图像时,一切都很好,但当我在数据库中执行图像更新时,会引发 ExternalException . 这是我的代码,如果你想分析的话。

    public class ImageConverter
    {
        public static byte[] imageToByteArray(Image imageIn)
        {
            if (imageIn == null)
                return new byte[] { 45 };
    
            using (MemoryStream ms = new MemoryStream())
            {
                imageIn.Save(ms, imageIn.RawFormat);
                return ms.ToArray();
            }
        }
    
        public static Image byteArrayToImage(byte[] byteArrayIn)
        {
            if (byteArrayIn == null)
                return null;
    
            using (MemoryStream ms = new MemoryStream(byteArrayIn))
            {
                Image returnImage = Image.FromStream(ms);
                return returnImage;
            }
        }
    
    }