kkuilla
kkuilla

Reputation: 2256

How to convert an SQL Server BLOB string to System.Drawing.Image?

How can I convert a BLOB represented as a string to a System.Drawing.Image type?

Background

I am going to import information about users together with their photo from a csv file using c#. The proprietary SDK that I use requires the photo to be a System.Drawing.Image

Below is an example of the csv file.

surname firstname   photo                       
Blogs    Joe        0xFFD8FFE000104A46494600010101005F005F0000FFDB0043000D090A
                    

The photo field is actually 5k chars long and is a direct export of the BLOB field value in the sql server db. We have just taken the raw value from the database field and exported it to the csv file.

Below is the code that demonstrates how far I have got. The cvsuser variable represents one row of the csv file.

// We need to convert the photo from a string to a byte array
string strPhoto = null;
strPhoto = csvuser.photo; // The string that represents the BLOB
byte[] bytes = new byte[strPhoto.Length * sizeof(char)];
System.Buffer.BlockCopy(strPhoto.ToCharArray(), 0, bytes, 0, bytes.Length);
                   
// Then we create a memory stream that holds the image
MemoryStream photostream = new MemoryStream( bytes );

// Then we can create a System.Drawing.Image by using the Memory stream
var photo = Image.FromStream(photostream);

However, the Image.FromStream() line throws a System.ArgumentException with the message "Parameter is not valid."

Question

How can I convert the BLOB represented as a string to a System.Drawing.Image type?

The examples I have seen previously would, for example, fetch the blob straight from the database or reading the image from a file.

Upvotes: 1

Views: 5228

Answers (2)

pdriegen
pdriegen

Reputation: 2039

The issue is that the conversion between the hex-encoded string to byte array isn't being done property.

The code you listed will treat each of the chars in the blob as a byte, so an 'F' will be treated as 0x46 (the ascii code for a capital F). What you want to do is de-code each 2 characters as a single byte - i.e. F0 = 240 etc.

It assumes the string is an even number of characters. You'll also need to strip off the '0x' prefix, as that's just an indicator that what follows is a hexadecimal representation of the data.

So instead of this:

strPhoto = csvuser.photo; // The string that represents the BLOB
byte[] bytes = new byte[strPhoto.Length * sizeof(char)];
System.Buffer.BlockCopy(strPhoto.ToCharArray(), 0, bytes, 0, bytes.Length);

Do something like this (adapted from previous answer given here):

      strPhoto = csvuser.photo; // The string that represents the BLOB

      //remove first 2 chars (the '0x')
      strPhoto = strPhoto.Remove(0, 2);

      //convert hex-string to bytes:
      int NumberChars = strPhoto.Length/2;
      byte[] bytes = new byte[NumberChars];
      using (StringReader sr = new StringReader(strPhoto)){
            for (int i = 0; i < NumberChars; i++)
               bytes[i] = Convert.ToByte(new string(new char[2]{(char)sr.Read(), (char)sr.Read()}), 16);
      }

      // Then we create a memory stream that holds the image
      MemoryStream photostream = new MemoryStream( bytes );

      // Then we can create a System.Drawing.Image by using the Memory stream
      var photo = Image.FromStream(photostream);

Upvotes: 2

ataravati
ataravati

Reputation: 9155

Do this to convert your string to byte[]:

System.Text.ASCIIEncoding  encoding = new System.Text.ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(strPhoto);

Upvotes: 1

Related Questions