参数无效:System.ArgumentException

10

我有一个页面,可以将html5画布数据编码为base64 bmp图像(使用这个算法http://devpro.it/code/216.html),将其发送到服务器端进行处理,转换为System.Drawing.Image对象,并执行一些操作。

在我的本地环境中,这可以正常工作,但是在我的ec2实例上,我遇到了以下错误:

System.ArgumentException: 参数无效。 在 System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData) 在 System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement)

我的代码如下:

System.Drawing.Image image = null;
string b64string = "...";
byte[] sf = Convert.FromBase64String(b64string );
using (MemoryStream s = new MemoryStream(sf, 0, sf.Length))
{
   image = System.Drawing.Image.FromStream(s, false);
}
...

这是一个文本文件,其中包含我用来测试的示例b64string:https://docs.google.com/leaf?id=0BzVLGmig1YZ3MTM0ODBiNjItNzk4Yi00MzI5LWI5ZWMtMzU1OThlNWEyMTU5&hl=en_US

我还尝试过以下方法,并且得到了相同的结果:

System.Drawing.ImageConverter converter = new System.Drawing.ImageConverter();
image = converter.ConvertFrom(sf) as System.Drawing.Image;         

非常感谢任何见解!


你在本地和EC2实例上运行的框架版本是什么? - Oded
你的错误发生在尝试从字节数组读取数据并转换为图像时 - 我建议直接将字节数组写入文件,以便您可以检查它/与本地获取的内容进行比较。我怀疑问题出现在base64解码中。 - Jamie Treworgy
好失望啊 :) 我能想到的唯一尝试就是看看当你明确使用第三个参数(validateImageData)时会发生什么。框架补丁级别?非常奇怪。 - Jamie Treworgy
这是一个程序相关的内容,它使用标准的canvas toDataURL()函数对一个base64编码png工作正常。 - ari
1
这很可能不是您问题的原因,但您在此处不应该使用 using。http://msdn.microsoft.com/en-us/library/1kcb3wy4.aspx 上的文档说:“您必须在 Image 的生命周期内保持流打开状态。” - Jim Mischel
显示剩余12条评论
3个回答

5

我仍然不知道你问题的真正原因,但我猜测它与一种 Image 类不识别的图像格式有关。经过对二进制数据的检查,我可能能够形成你的图像。希望这能有所帮助。

Bitmap GetBitmap(byte[] buf)
{
    Int16 width = BitConverter.ToInt16(buf, 18);
    Int16 height = BitConverter.ToInt16(buf, 22);

    Bitmap bitmap = new Bitmap(width, height);

    int imageSize = width * height * 4;
    int headerSize = BitConverter.ToInt16(buf, 10);

    System.Diagnostics.Debug.Assert(imageSize == buf.Length - headerSize);

    int offset = headerSize;
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            bitmap.SetPixel(x, height - y - 1, Color.FromArgb(buf[offset + 3], buf[offset], buf[offset + 1], buf[offset + 2]));
            offset += 4;
        }
    }
    return bitmap;
}

private void Form1_Load(object sender, EventArgs e)
{
    using (FileStream f = File.OpenRead("base64.txt"))
    {
        byte[] buf = Convert.FromBase64String(new StreamReader(f).ReadToEnd());

        Bitmap bmp = GetBitmap(buf);
        this.ClientSize = new Size(bmp.Width, bmp.Height);
        this.BackgroundImage = bmp;
    }
}

谢谢!这让我更接近目标了。但是生成的输出改变了颜色——红色和蓝色互换了吗? 原图:http://i.imgur.com/a0UXf.gif 输出图:http://i.imgur.com/TVUmk.gif (注意:黑色背景可能是由于画布数据转换导致的) - ari
来源?没有,我是自己编的。我不知道原始图像。所以,你需要像这样使用SetPixel进行一些操作:bitmap.SetPixel(x, height - y - 1, Color.FromArgb(buf[offset + 3], buf[offset+2], buf[offset + 1], buf[offset])); 注意:我交换了 buf[offset+2]buf[offset] - L.B
太棒了!非常感谢,解决了我的问题。你有算法参考或位图数据规范可以让我查看吗?我不喜欢使用我完全不理解的代码。 - ari
我必须承认,对于图像格式等方面我完全不了解。我用二进制编辑器打开了二进制数据并尝试去猜测。如果你也这样做,你会发现前70-80个字节与后面的内容有所不同。所以我认为这一定是头部之类的东西...差不多就是这样,文件中用4个字节来表示颜色。R-G-B-Alpha - L.B

3
发布的代码看起来是正确的。我已经测试过了,它可以正常工作。
异常“System.ArgumentException:参数无效。”没有任何其他提示(特别是不包括参数名称),它是GDI+(.NET Image类背后的基础技术)标准InvalidParameter错误的包装器,它并没有告诉我们哪个参数是无效的。
因此,根据使用.NET Reflector的FromStream代码,我们可以看到在GDI+调用中使用的参数实际上是……输入流。
所以我的猜测是,您提供的输入流有时无法作为图像有效?您应该保存失败的输入流(例如使用File.SaveAllBytes(sf))以进行进一步的调查。

所以我的猜测是您提供的输入流有时无效,无法作为图像处理?您对样本数据有什么看法?图像类无法加载,但我认为它在某种程度上是正确的。 - L.B
@L.B - 我可以成功地将样本数据(由OP提供的链接)作为.BMP加载。 - Simon Mourier
但是我的XP-Home(32位)无法运行。我收到了相同的错误“参数无效”。 - L.B
@L.B - 有趣。也许GDI+版本不同,因此它不支持输入图像数据。 - Simon Mourier
我认为,在没有更好的解决方案出现之前,使用条件编译或尝试同时加载图像(GetBitmapImage.FromStream函数)将是最佳解决方案。 - L.B
这是我现在必须做的事情。虽然我希望我知道一开始为什么它不能正常工作。 - ari

0
这可能是因为sf包含无效的图像数据。验证您传递到流中的数据的有效性,看看是否可以解决问题。

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