3

当我尝试使用 BinaryFormatter 对一些图像进行序列化时,我会得到一个 ExternalException - 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

4

3 回答 3

4

正如 OP 指出的那样,提供的代码引发了一个异常,该异常似乎只发生在他提供的图像上,但适用于我机器上的其他图像。

选项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 序列化的附加信息的工具创建的。

PS 图像可以使用BMPPNG格式保存到内存流。如果可以选择更改格式,那么您可以尝试其中一种或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);
    }
}
于 2013-04-10T05:27:27.433 回答
2

尽管Bitmap该类被标记为[Serializable],但它实际上并不支持序列化。您可以做的最好的事情是序列化包含原始图像数据,然后使用和方法byte[]重新创建它。MemoryStreamImage.FromStream()

我无法解释您遇到的不一致行为;对我来说,它无条件地失败(尽管我在尝试在不同的应用程序域之间编组图像时首先发现了这一点,而不是手动序列化它们)。

于 2013-04-10T04:09:07.617 回答
1

我不确定,但我会倾向于 XP 与 Windows 7 的不同安全模型。图像继承自 System.MarshalByRefObject。执行序列化时,可能在应用程序域之间进行代理。此代理可能在 Windows 7 中被禁止。

http://msdn.microsoft.com/en-us/library/system.marshalbyrefobject%28v=vs.71%29.aspx

于 2013-04-10T04:49:19.387 回答