10

I have a page that sends html5 canvas data, encoded as a base64 bmp image (using this algorithm http://devpro.it/code/216.html) to a serverside process that converts it into a System.Drawing.Image object and does some operations on it.

In my local environment, this works just fine, but on my ec2 instance I get the following error:

System.ArgumentException: Parameter is not valid. at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData) at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement)

My code looks as follows:

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

Here's a text file with a sample b64string that I'm using to test: https://docs.google.com/leaf?id=0BzVLGmig1YZ3MTM0ODBiNjItNzk4Yi00MzI5LWI5ZWMtMzU1OThlNWEyMTU5&hl=en_US

I've also tried the following and had the same results:

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

Any insight would be greatly appreciated!

17
  • What version of the framework are you running this on, locally and on the ec2 instance? Commented Sep 23, 2011 at 19:31
  • Do you mean that the actual test data (that file) cannot be decoded on the ec2 instance, but can be on your dev machine? E.g. there's no possibility that there is different data being processed in your dev and in your server test. Commented Sep 23, 2011 at 19:39
  • Sorry, forgot to mention .NET 4.0 on both. Commented Sep 23, 2011 at 19:40
  • Correct, that test data can be decoded locally, but not on the ec2 instance. Commented Sep 23, 2011 at 19:41
  • 1
    It's unlikely that this is the cause of your problem, but you shouldn't be using a using here. Documentation at msdn.microsoft.com/en-us/library/1kcb3wy4.aspx says, "You must keep the stream open for the lifetime of the Image." Commented Sep 23, 2011 at 23:23

3 Answers 3

5
+50

I still don't know the real cause of your problem, but i guess it is related with a image format which Image class doesn't recognize. After inspecting the binary data a little bit, I could be able to form your image. I hope this helps.

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; } } 
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks! this gets me a good deal closer. The resulting output does change the colors though - R and B swapped? Original: i.imgur.com/a0UXf.gif Output: i.imgur.com/TVUmk.gif (note: the black background might be because of the canvas data conversion)
Source? No I made it up. I don't know the original image. So, you have to play a little bit with SetPixel like this bitmap.SetPixel(x, height - y - 1, Color.FromArgb(buf[offset + 3], buf[offset+2], buf[offset + 1], buf[offset])); Note: I swapped buf[offset+2] and buf[offset]
awesome! thank you so much, that did it. Do you have an algorithm reference or bitmap data spec I can review? I hate to use code I don't completely understand.
I must admit, I have no idea about image formats etc. I opened the binary data with a binary editor and tried to guess. If you do the same you'll see that first 70-80 bytes seem different that the rest. So, i thought this must be header, etc...etc... Shortly, colors are respresented with 4 bytes in the file. R-G-B-Alpha
3

The posted code seems correct. I have tested it and it works fine.

The exception "System.ArgumentException: Parameter is not valid." without any other hint (especially not the name of the parameter) is a wrapper for GDI+ (the underlying technology behind .NET Image class) standard InvalidParameter error, which does not tell use exactly what parameter is invalid.

So, following the FromStream code with .NET Reflector, we can see that the parameters used in GDI+ calls are essentially ... the input stream.

So my guess is the input stream you provide is sometimes invalid as an image? You should save the failing input streams (using File.SaveAllBytes(sf) for example) for further investigation.

6 Comments

So my guess is the input stream you provide is sometimes invalid as an image? What do you think about sample data? Image class fails to load but I think it is somehow correct.
@L.B - I can load sample data (the link given by the OP) as a .BMP successfully.
But I can't with my XP-Home(32bit). I get the same error Parameter is not valid
@L.B - Interesting. Maybe the GDI+ version is not the same, so it does not support the input image data.
I think --until someome comes with a better solution-- using a conditional compilation or trying to load images with both (GetBitmap or Image.FromStream) functions would be the best solution
|
0

This could happen if sf contained invalid image data. Verify the validity of the data you're passing into the stream, and see if that fixes your issue.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.