将字节数组转换为图像:参数无效。

3

我正在将图像存储在数据库中,并希望将它们从字节数组转换为图像。我没有问题将对象转换为字节数组,但在尝试从字节数组转换为图像时出现“参数无效”的错误。我传递给方法的对象来自数据集行。

存储过程

USE [----------------]
GO
/****** Object:  StoredProcedure [dbo].[usp_imageloader_add_test]    Script Date: 01/16/2012    09:19:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER   procedure [dbo].[usp_imageloader_add_test]
@p_Image Image

as 

INSERT into Test_Images VALUES(@p_Image)

上传文件控件 / 将图像文件转换为字节数组并将数据保存到数据库中

 protected void btnUpload_Click(object sender, EventArgs e)
    {
        if (ctrlUpload.PostedFile != null)
        {
            if (ctrlUpload.PostedFile.ContentLength > 0)
            {
                // Get Posted File
                HttpPostedFile objHttpPostedFile = ctrlUpload.PostedFile;

                // Find its length and convert it to byte array
                int ContentLength = objHttpPostedFile.ContentLength;

                // Create Byte Array
                byte[] bytImg = new byte[ContentLength];

                // Read Uploaded file in Byte Array
                objHttpPostedFile.InputStream.Read(bytImg, 0, ContentLength);

                using (SqlConnection dbConnection = new SqlConnection(app_settings.sql_conn_string_db))
                {
                    try
                    {
                        string sql = "usp_imageloader_add_test";
                        SqlCommand cmd = new SqlCommand(sql, dbConnection);
                        cmd.CommandType = System.Data.CommandType.StoredProcedure;
                        cmd.Parameters.AddWithValue("@p_Image", bytImg).SqlDbType = SqlDbType.Image;
                        cmd.Connection.Open();
                        cmd.ExecuteNonQuery();
                        cmd.Connection.Close();
                    }


                    catch (Exception ex)
                    {
                        ex.Message.ToString();
                    }
                }
            }
        }
    }

将对象转换为字节数组并转换为图像
 private System.Drawing.Image ObjToImg(object obj)
    {
        byte[] byteArray;
        if (obj == null)
            return null;
        else
        {
            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);
            byteArray = ms.ToArray(); // Byte Array
            ms.Close();

            ms = new MemoryStream(byteArray, 0, byteArray.Length);
            ms.Seek(0, SeekOrigin.Begin);
            System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
            return returnImage;
        }

任何想法都将有所帮助。

将二进制数据保存到文件中并查看图像编辑器的响应。 - Tim Schmelter
5个回答

3

Image.FromStream 可能会抛出 ArgumentException,因为图像格式无效。期望将随机序列化对象格式化为有效图像是不合理的。


你会建议我如何更改我的代码,因为我已经没有想法了? - nick gowdy
你根本不应该进行序列化,这毫无意义。如果参数来自数据集,它应该已经是一个字节数组类型的数组了。 - insipid

1

1
尝试以下操作,您的流可能没有初始化到开头:
ms = new MemoryStream(byteArray, 0, byteArray.Length);
ms.Seek(0, SeekOrigin.Begin);
System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);

这是什么类型的图像?您确定存储的图像是有效的吗?
另外,关于用法的评论(不影响您的问题),在使用流时使用using语句是良好的实践。例如:
using (MemoryStream ms = new MemoryStream())
{
    // your code here
}

1
他需要确保流保持打开状态,直到他完成图像处理。 - insipid
我修改了代码,使流指向起始位置,然后尝试从内存流中绘制图像,但仍然出现相同的错误。 - nick gowdy
@nick gowdy 这是什么类型的图像?您已经验证存储的图像是否有效吗? - Kelsey

0
Kelsey的解决方案应该是可行的。这是因为,当你从byteArray读取数据到内存流时,指针被放置在流的末尾,现在当你尝试从这个内存流中读取数据时,它会尝试读取指针的头部,由于此后没有数据,所以会出现错误。现在如果你执行ms.Seek(0, SeekOrigin.Begin);,读取器指针就会被放置在内存流的开头。并且在使用完毕后要处理内存流ms.Dispose()。希望这可以帮助到你。

0
你不需要二进制格式化程序,那会搞乱你的数据,它实际上是用来序列化对象的。
需要注意的关键点是对象已经是字节数组,因此你可以直接进行强制类型转换并使用它。
尝试这个:-
    private System.Drawing.Image ObjToImg(object obj)
    {
        if (obj == null)
            return null;
        else
        {
            byte[] byteArray = (byte[])obj;
            System.Drawing.Image returnImage;
            using (var ms = new MemoryStream(byteArray, 0, byteArray.Length))
            {
                returnImage = System.Drawing.Image.FromStream(ms);
            }
            return returnImage;
        }
    }

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