3

I am storing images in a database and would like to convert them from byte array to image. I have no problem converting an object to byte array but I get an error of "Parameter is not valid" when trying to convert from byte array to image. The object I am passing to my method is from a dataset row.

Stored procedure

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)

Upload File control /convert Image file to byte array and save data to database

 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();
                    }
                }
            }
        }
    }

Convert object to byte array and to image

 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;
        }

Any ideas would be helpful.

nick gowdy
  • 6,191
  • 25
  • 88
  • 157

5 Answers5

3

Image.FromStream is probably throwing an ArgumentException because the image format is invalid. Expecting a random serialized object to be formatted as a valid image is not reasonable.

insipid
  • 3,238
  • 3
  • 26
  • 38
  • How would you suggest I change my code because I am out of ideas? – nick gowdy Jan 16 '12 at 11:15
  • You shouldn't be serializing at all, it makes no sense. If the parameter came from the data set it should already be an array of type byte. – insipid Jan 18 '12 at 01:22
1

Try the following, your stream may not be initialized to the beginning:

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

What type of image is it? Are you sure the image that is stored is valid?

Also just a comment on usage (won't affect your issue), it is good practice to use a using statement when working with streams. Eg:

using (MemoryStream ms = new MemoryStream())
{
    // your code here
}
Kelsey
  • 47,246
  • 16
  • 124
  • 162
  • 1
    He needs to make sure the stream stays open until he is done with the Image. – insipid Jan 13 '12 at 16:09
  • I modified the code some the stream is pointing to the beginning before trying to draw the image from the memorystream and it still throws the same error. – nick gowdy Jan 16 '12 at 11:05
  • @nick gowdy What type of image is it? Have you verified that the image that is stored is valid? – Kelsey Jan 16 '12 at 14:48
1

Is the data you're using raw RGB data? If so, there's a user comment in the docs for FromStream() that mentions that the method will throw if the stream contains raw RGB data: http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx (see the bottom of the page); it recommends using a Bitmap instead (http://msdn.microsoft.com/en-us/library/zy1a2d14.aspx).

atkretsch
  • 2,367
  • 18
  • 24
0

The solution by Kelsey should work. This is because, when you read data from byteArray to memory stream, the pointer is placed at the end of the stream, and now when you try to read data from this memory stream, it tries to read head of this pointer, and as there is no data after this, you get an error. Now if you do ms.Seek(0, SeekOrigin.Begin);, the reader pointer is placed at the beginning of the memory stream. And dispose the memory stream when you are done using it ms.Dispose(). Hope this helps.

Amar Palsapure
  • 9,590
  • 1
  • 27
  • 46
0

You don't need the binary formatter, that's what's messing with your data, it's for serializing objects really.

The key thing to note is that the object is a byte array already so you can just cast it and use that.

Try this:-

    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;
        }
    }