二进制格式化程序.Serialize(图像) - ExternalException - GDI+中发生了一般错误。

3

在使用BinaryFormatter序列化一些图片时,我遇到了ExternalException - A generic error occurred in GDI+"的问题。经过一番琢磨后,我决定创建一个简单的测试项目来缩小问题的范围:

    static void Main(string[] args)
    {
        string file = @"C:\temp\delme.jpg";

        //Image i = new Bitmap(file);
        //using(FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))

        byte[] data = File.ReadAllBytes(file);
        using(MemoryStream originalms = new MemoryStream(data))
        {
            using (Image i = Image.FromStream(originalms))
            {
                BinaryFormatter bf = new BinaryFormatter();

                using (MemoryStream ms = new MemoryStream())
                {
                    // Throws ExternalException on Windows 7, not Windows XP
                    bf.Serialize(ms, i);
                }
            }
        }
    }

针对某些特定图片,我已经尝试了各种加载方式,但在Windows 7下无法运行,即使以管理员身份运行程序也无效。然而,当我将完全相同的可执行文件和图片复制到Windows XP的VMWare实例中时,却没有任何问题。
有人知道为什么在Windows 7下有些图片不能正常工作,但在XP下可以吗?
以下是其中一张图片: http://www.2shared.com/file/7wAXL88i/SO_testimage.html delme.jpg md5: 3d7e832db108de35400edc28142a8281

请提供其中一个有问题的图片(将其上传到某个地方并提供链接)。 - Mohammad Dehghan
你好,请选择最能满足你需求的帖子作为答案,谢谢。 - Patrick D'Souza
3个回答

4
作为楼主指出的,所提供的代码会抛出一个异常,似乎只在他提供的图片上发生,但在我的机器上使用其他图片则正常。 选项1
static void Main(string[] args)
{
    string file = @"C:\Users\Public\Pictures\delme.jpg";

    byte[] data = File.ReadAllBytes(file);
    using (MemoryStream originalms = new MemoryStream(data))
    {
        using (Image i = Image.FromStream(originalms))
        {
            BinaryFormatter bf = new BinaryFormatter();

            using (MemoryStream ms = new MemoryStream())
            {
                // Throws ExternalException on Windows 7, not Windows XP                        
                //bf.Serialize(ms, i);

                i.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); // Works
                i.Save(ms, System.Drawing.Imaging.ImageFormat.Png); // Works
                i.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // Fails
            }    
         }
     }
}

可能是所涉及的图像是使用某个工具创建的,该工具添加了一些额外信息,这些信息干扰了JPEG序列化。
附注:可以使用BMP或PNG格式将图像保存到内存流中。如果更改格式是一种选择,则可以尝试其中任何一个或在ImageFormat中定义的任何其他格式。
选项2:如果您的目标只是将图像文件内容放入内存流中,则仅执行以下操作即可帮助。
static void Main(string[] args)
{
    string file = @"C:\Users\Public\Pictures\delme.jpg";
    using (FileStream fileStream = File.OpenRead(file))
    {
        MemoryStream memStream = new MemoryStream();
        memStream.SetLength(fileStream.Length);
        fileStream.Read(memStream.GetBuffer(), 0, (int)fileStream.Length);
    }
}

只是想补充一下,另一个解决方案是创建图像的副本并对其进行序列化,但由于这种方法不可行(因为某些图像可能非常大),所以最终我重写了代码和其他方法,完全消除了序列化。为了在Win7上运行项目而进行了很多工作,真是让人沮丧。 :[ - Generic Comrade

2
尽管Bitmap类被标记为[Serializable],但实际上它并不支持序列化。最好的方法是将包含原始图像数据的byte[]进行序列化,然后使用MemoryStreamImage.FromStream()方法重新创建它。
我无法解释您正在经历的不一致行为;对我来说,它总是失败的(尽管我最初是在尝试在不同的应用程序域之间传递图像时发现了这一点,而不是手动序列化它们)。

1

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