11

I am trying to convert a Unicode string to an image in C#. Each time I run it I get an error on this line

Image image = Image.FromStream(ms, true, true);

that says: ArgumentException was unhandled by user code. Parameter is not valid. Any ideas why this is happening? Below is the rest of the function.

public Image stringToImage(string inputString)
    {
        byte[] imageBytes = Encoding.Unicode.GetBytes(inputString);
        MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);

        ms.Write(imageBytes, 0, imageBytes.Length);
        Image image = Image.FromStream(ms, true, true);

        return image;
    }
7
  • Do you want to convert the text to image? Or does the input string contains some raw bytes of image data. Commented Jun 27, 2013 at 16:09
  • It's raw bytes of image data Commented Jun 27, 2013 at 16:10
  • Sorry, should have clarified that Commented Jun 27, 2013 at 16:10
  • 2
    Depending in your use, you could convert the image into a Base64 string as shown here dailycoding.com/Posts/… Commented Jun 27, 2013 at 16:16
  • 3
    On a side note - wrap your MemoryStream in a using statement, as you have a resource leak at the moment. Commented Jun 27, 2013 at 16:31

5 Answers 5

8

Unicode doesn't encode all possible byte sequences that you'll need to represent an image.

byte[] -> String -> byte[] is a transformation that just won't work for many given sequences of bytes. You'll have to use a byte[] throughout.

For example, if you read the bytes, convert them to UTF-16 then it's possible that byte sequences will be discarded as invalid. Here's an example of an invalid byte sequence from UTF-16.

Code points U+D800 to U+DFFF[edit] The Unicode standard permanently reserves these code point values for UTF-16 encoding of the lead and trail surrogates, and they will never be assigned a character, so there should be no reason to encode them. The official Unicode standard says that all UTF forms, including UTF-16, cannot encode these code points.

Sign up to request clarification or add additional context in comments.

2 Comments

If it's raw bytes of image data you might be best creating an image of the appropriate size, writing this data out into its frame buffer and then persisting the image.
Agreed, shouldn't be trying to store raw image data encoded in a string, UTF16 (C#'s unicde string byte encoding) has illegal sequences and impossible values that you would otherwise want to use to store bytes. If you do have an actual string containing characters and not byte data, you need to use the drawing APIs to draw the text to an image.
5

May this can help you:

public Bitmap stringToImage(string inputString)
{
   byte[] imageBytes = Encoding.Unicode.GetBytes(inputString);
   using (MemoryStream ms = new MemoryStream(imageBytes))
   {
       return new Bitmap(ms);
   }
}

1 Comment

The last line is giving me problems
3

Take out your call that writes to the MemoryStream. The constructor call that accepts a byte array automatically puts the contents of the byte array into the stream. Otherwise your stream contains 2 copies of the raw data. In addition, the call to Write will leave the stream's position at the end of stream, so there is no data that the FromStream call can read.

So it would be:

public Image stringToImage(string inputString)
{
    byte[] imageBytes = Encoding.Unicode.GetBytes(inputString);

    // Don't need to use the constructor that takes the starting offset and length
    // as we're using the whole byte array.
    MemoryStream ms = new MemoryStream(imageBytes);

    Image image = Image.FromStream(ms, true, true);

    return image;
}

5 Comments

Where are you getting the source string from?
An image that was converted into a string
How was it converted into a string? The encoding that was used to encoding the raw bytes as a string must match the decoding used to convert the string back into raw bytes.
Not sure, I am pulling it from Active Directory. I'll try to find out
Try using Encoding.Default.GetBytes instead. The data may be transferred as a ANSI character stream instead of Unicode.
3

You're getting an image as a string, out of ldap? I'm pretty sure if that was true, the string would actually be base64 encoded, and in that case contains bytes that represent actual characters, and not image data.

Could you post a snippit of the string you're getting?

If it's true, you need to take the string and turn it a byte[] by un-base64'ing it, and then use the byte array to make the image. Combined with @JonBenedicto's code:

public Image stringToImage(string inputString)
{
    byte[] imageBytes = Convert.FromBase64String(inputString);
    MemoryStream ms = new MemoryStream(imageBytes);

    Image image = Image.FromStream(ms, true, true);

    return image;
}

1 Comment

It may be, but whenever I try with base64, I get this error "The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."
0

With string you might get loss of data,i will just post example on converting image to byte array and array to image again,and after image to byte array,to string and back,without loss of data.

            MemoryStream ms = new MemoryStream();
            Image.FromFile(@"C:\..\..\..\img.jpg").Save(ms,ImageFormat.Jpeg);
            byte[] bytes = ms.ToArray();
            MemoryStream ms1 = new MemoryStream(bytes);
            Image NewImage = Image.FromStream(ms1);
            NewImage.Save(@"C:\..\..\..\img1.jpg");

try this out and it might help you produce what you need.

trying to convert to string and back,better use base64.

            MemoryStream ms = new MemoryStream();
            Image.FromFile(@"C:\..\..\..\img.jpg").Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] bytes = ms.ToArray();
            string byteString = Convert.ToBase64String(bytes);
            byte[] NewBytes = Convert.FromBase64String(byteString);
            MemoryStream ms1 = new MemoryStream(NewBytes);
            Image NewImage = Image.FromStream(ms1);

This should give you the outcome you need.

 MemoryStream ms = new MemoryStream();
    Image.FromFile(@"C:\..\..\..\img.jpg").Save(ms,ImageFormat.Jpeg);
    byte[] bytes = ms.ToArray();
    string byteString = Convert.ToBase64String(bytes);

then when you pass this string into your method...

    public Image stringToImage(string inputString)
    {
         byte[] NewBytes = Convert.FromBase64String(inputString);
         MemoryStream ms1 = new MemoryStream(NewBytes);
         Image NewImage = Image.FromStream(ms1);

         return NewImage;
     }

4 Comments

That seems like it would work, but I don't want to save the file. I want to do it all in memory.
then you just dont do the last line of code of the first example,in the second example its just like what you do.
base64 is the safest way not to lose data, when converting byte data that its not originaly encoded text,to string.
Whenever I tried base64 I would get this error "The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.