Converting Byte Array To Image Throws "Parameter is not valid." - c#

I'm trying to convert several byte arrays (stored in SQL Server 2008 R2 as varbinary(8000)) into images so I can attach them to a PDF file (an example of the data is below). I keep getting "Parameter is not valid." when creating the Image from the MemoryStream. Any help on this?
MemoryStream memoryStream = new MemoryStream(byteArray);
Image image = Image.FromStream(memoryStream);
Bitmap bitmap = new Bitmap(image);
0x0A020101000000005E006500FA00FA0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010C00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C1C0C7000FC2FFC1FE80C70007C2FFC1FE1FC7FFC1F03FC1FFC1FE3FC7FFC1F807C1FFC1FE3FC8FFC1F3C1FFC1FE3FC8FFC1FEC1FFC1FE3FC8FFC1FE7FC1FE3FC9FFBFC1FE3FC9FFC1DFC1FE3FC9FFC1CFC1FE3FC9FFC1F3C1FE3FC9FFC1FBC1FE3FC9FFC1F9C1FE3FC9FFC1F9C1FE3FC9FFC1FCC1FE3FC9FFC1FE7E3FC9FFC1FE7E3FCAFF7E3FC2FFC1FCC20007C4FF3E3FC2FFC1F8C300C4FF3E3FC2FFC1F1C2FFC1FC7FC3FF3E3FC2FFC1F1C2FFC1FC3FC3FF3E3FC2FFC1F1C3FF9FC3FF3E3FC2FFC1F1C3FFC1CFC3FF3E3FC2FFC1F1C3FFC1E7C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C2FFC1FE7E3FC2FFC1F1C3FFC1E7C2FFC1FE7E3FC2FFC1F1C3FFC1C7C2FFC1FCC1FE3FC2FFC1F1C3FFC1C7C2FFC1F9C1FE3FC2FFC1F1C3FFC1DFC2FFC1F9C1FE3FC2FFC1F1C3FFBFC2FFC1F9C1FE3FC2FFC1F1C2FFC1FC3FC2FFC1F3C1FE3FC2FFC1F0C2FFC1F8C3FFC1E7C1FE3FC2FFC1FEC2000FC3FFC1CFC1FE3FC3FFC2000FC3FF9FC1FE3FC9FF3FC1FE3FC8FFC1FE7FC1FE3FC8FFC1F0C1FFC1FE3FC8FFC1E7C1FFC1FE3FC8FFC1CFC1FFC1FE3FC8FF8FC1FFC1FE3FC8FFC1E0C1FFC1FE3FC8FFC1F8C1FFC1FE3FC8FFC1FC1FC1FE3FC9FF8FC1FE3FC9FFC1E7C1FE3FC9FFC1F0C1FE3FC9FFC1FE7E3FCAFF7E3FC2FFC1FCC300C4FF3E3FC2FFC1F8C3001FC3FF3E3FC2FFC1F1C3FF8FC3FF9E3FC2FFC1F1C3FF87C3FFC1CE3FC2FFC1F1C3FFC1F3C3FFC1CE3FC2FFC1F1C3FFC1F9C3FFC1EE3FC2FFC1F1C3FFC1FCC3FFC1E43FC2FFC1F1C3FFC1FE7FC2FFC1E43FC2FFC1F1C4FF3FC2FFC1E43FC2FFC1F1C4FF1FC2FFC1F03FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C3FFC1FE7FC2FFC1F83FC2FFC1F1C3FFC1FEC3FFC1F83FC2FFC1F1C3FFC1F9C3FFC1F83FC2FFC1F1C3FFC1F3C3FFC1F83FC2FFC1F1C3FFC1F7C3FFC1F83FC2FFC1F1C2FFC1FE0FC3FFC1F83FC2FFC1F0C3003FC3FFC1F83FC2FFC1F8C20001C4FFC1F83FC2FFC1FCC20003C4FFC1FC3FCAFFC1E43FCAFFC1E43FCAFFC1E43FCAFFC1EE3FCAFFC1EE3FCAFFC1CE3FCAFF3E3FCAFF7E3FC9FFC1FE7E3FC9FFC1FE7E3FC9FFC1FCC1FE3FC9FFC1F1C1FE3FC9FFC1C3C1FE3FC9FFC1DFC1FE3FC9FF9FC1FE3FC8FFC1E07FC1FE3FC8FFC1C1C1FFC1FE1FC7FF001FC1FFC1FEC9003FC1FFC1FE80C700C3FFC1FEC1C0C700C3FFC1FE

It's a
% file output
output: PCX ver. 2.8 image data, with palette
under linux I just transformed your hex stream from plain text to a binary file called output
echo
"0A020101000000005E006500FA00FA0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010C00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C1C0C7000FC2FFC1FE80C70007C2FFC1FE1FC7FFC1F03FC1FFC1FE3FC7FFC1F807C1FFC1FE3FC8FFC1F3C1FFC1FE3FC8FFC1FEC1FFC1FE3FC8FFC1FE7FC1FE3FC9FFBFC1FE3FC9FFC1DFC1FE3FC9FFC1CFC1FE3FC9FFC1F3C1FE3FC9FFC1FBC1FE3FC9FFC1F9C1FE3FC9FFC1F9C1FE3FC9FFC1FCC1FE3FC9FFC1FE7E3FC9FFC1FE7E3FCAFF7E3FC2FFC1FCC20007C4FF3E3FC2FFC1F8C300C4FF3E3FC2FFC1F1C2FFC1FC7FC3FF3E3FC2FFC1F1C2FFC1FC3FC3FF3E3FC2FFC1F1C3FF9FC3FF3E3FC2FFC1F1C3FFC1CFC3FF3E3FC2FFC1F1C3FFC1E7C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C3FF3E3FC2FFC1F1C3FFC1F3C2FFC1FE7E3FC2FFC1F1C3FFC1E7C2FFC1FE7E3FC2FFC1F1C3FFC1C7C2FFC1FCC1FE3FC2FFC1F1C3FFC1C7C2FFC1F9C1FE3FC2FFC1F1C3FFC1DFC2FFC1F9C1FE3FC2FFC1F1C3FFBFC2FFC1F9C1FE3FC2FFC1F1C2FFC1FC3FC2FFC1F3C1FE3FC2FFC1F0C2FFC1F8C3FFC1E7C1FE3FC2FFC1FEC2000FC3FFC1CFC1FE3FC3FFC2000FC3FF9FC1FE3FC9FF3FC1FE3FC8FFC1FE7FC1FE3FC8FFC1F0C1FFC1FE3FC8FFC1E7C1FFC1FE3FC8FFC1CFC1FFC1FE3FC8FF8FC1FFC1FE3FC8FFC1E0C1FFC1FE3FC8FFC1F8C1FFC1FE3FC8FFC1FC1FC1FE3FC9FF8FC1FE3FC9FFC1E7C1FE3FC9FFC1F0C1FE3FC9FFC1FE7E3FCAFF7E3FC2FFC1FCC300C4FF3E3FC2FFC1F8C3001FC3FF3E3FC2FFC1F1C3FF8FC3FF9E3FC2FFC1F1C3FF87C3FFC1CE3FC2FFC1F1C3FFC1F3C3FFC1CE3FC2FFC1F1C3FFC1F9C3FFC1EE3FC2FFC1F1C3FFC1FCC3FFC1E43FC2FFC1F1C3FFC1FE7FC2FFC1E43FC2FFC1F1C4FF3FC2FFC1E43FC2FFC1F1C4FF1FC2FFC1F03FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C4FF1FC2FFC1F83FC2FFC1F1C3FFC1FE7FC2FFC1F83FC2FFC1F1C3FFC1FEC3FFC1F83FC2FFC1F1C3FFC1F9C3FFC1F83FC2FFC1F1C3FFC1F3C3FFC1F83FC2FFC1F1C3FFC1F7C3FFC1F83FC2FFC1F1C2FFC1FE0FC3FFC1F83FC2FFC1F0C3003FC3FFC1F83FC2FFC1F8C20001C4FFC1F83FC2FFC1FCC20003C4FFC1FC3FCAFFC1E43FCAFFC1E43FCAFFC1E43FCAFFC1EE3FCAFFC1EE3FCAFFC1CE3FCAFF3E3FCAFF7E3FC9FFC1FE7E3FC9FFC1FE7E3FC9FFC1FCC1FE3FC9FFC1F1C1FE3FC9FFC1C3C1FE3FC9FFC1DFC1FE3FC9FF9FC1FE3FC8FFC1E07FC1FE3FC8FFC1C1C1FFC1FE1FC7FF001FC1FFC1FEC9003FC1FFC1FE80C700C3FFC1FEC1C0C700C3FFC1FE"
| xxd -p -r >output
and then the easy part with file output to get the name of the file format from the utility file.

First, make sure you know the encoding, as the Image.FromStream method knows only a limited number of formats.
Make sure that the Position of your MemoryStream is set properly to 0, and not to the end - otherwise, any reads will begin at the end appear to be empty, instead of starting at the beginning.
Also, note that
This constructor does not expose the underlying stream. GetBuffer throws UnauthorizedAccessException.1
Thus, this could be caused by some of the way Bitmap is handling the underlying stream. IF need be, try making an empty memorystream, copying the byte into it, and then resetting the position
MemoryStream memoryStream = new MemoryStream();
foreach(var b in byteArray) memoryStream.WriteByte(b);
memoryStream.Position = 0;
Image image = Image.FromStream(memoryStream);

The byte array you gave is 1117 bytes long. That's not evenly divisible by 4 or 3, so I'm pretty certain that the image is not raw bytes and is actually encoded in an image format of some sort.
The Image.FromStream() method can't decode an encoded image without knowing the format, and the byte array you gave doesn't specify what that format is. Therefore the parameter you gave is invalid. If you know the format of the image you could attempt to insert a header into the byte array before the rest of the image, and see if that helps. It's curious you have the image but not its header, although it doesn't appear to be a base-64 string either.
Without knowing the image format it could be difficult to convert these byte arrays into images. Is there any way you could find out what they are? How is the image data retrieved to be stored?

Related

How to reduce jpg size saved from a base64 string C#

I'm receiving a base64 string from the client side that represents a jpg and I'm saving it using the following code
byte[] imageBytes = Convert.FromBase64String(base64File.base64Data);
using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
Image image = Image.FromStream(ms, true);
image.Save("aPath");
}
The problem is that that the original image entered on the client side (before the base64 encoding) is about 3MB and once that I save it using the method above, it turns to be a 24MB image!
Is there any way to reduce it's size? (I know that sending big images encoded in base64 is not very smart, but I need to find a solution keeping this part)
Just save the bytes, don't convert it back into an image, otherwise you will have to use the same settings as when it was originally saved.
I.e its already the image you want, loading it from a stream and calling save, saves it as a bitmap in probably 32bit
Update
So I tried the code below
byte[] imageBytes = Convert.FromBase64String(base64File.base64Data); File.WriteAllBytes("apath"),imageBytes);
But it generates a 18MB file,
still much larger than the original
Basically this means, when ever you are converting it base64 (server side), it is probably doing the same thing. Maybe its loading it into an Image and saving the bytes before converting it to Base64.
I believe a way to tell if the image is actually a bitmap (in your case) before conversion base64, is just look to see if the first 2 bytes of the file are BM.
Either way, the image is being manipulated on the other side before its converted to base64, maybe its a bitmap or its just reenconding it, its hard to tell. That's to say base64 encoding isn't smart enough to reenconde the image format and inflate the size

Cannot convert YUV420 frame to Bitmap

I am trying to convert YUV420 frames to Bitmap or Image. I am reading these frames from an MP4 video in C# using the AVBlocks library. So, after creating an input and output socket using AVBlocks classes, I then pull each frame from the video with a YUV420 color format and UncompressedVideo stream type. I basically do this by calling Transcoder.Pull(int outputIndex, MediaSample outputData) and then the MediaBuffer that's part of the outputData has the data in an array of bytes. So I am trying to convert these bytes to a Bitmap or Image so that I can eventually show each frame into a PictureBox in the Winforms application.
What I've tried:
I have tried using a MemoryStream, as shown below, but I get an unhandled ArgumentException saying that the parameter is not valid. I tried using ImageConverter() as well to convert to an Image, but I get the same exception. Then, I converted the byte array from YUV to RGB format and gave the updated array as a parameter to the MemoryStream, but again no luck. I also tried changing the color format of the output socket from YUV420 to a BGR format, but it resulted in the same issue as above. The code that tries to convert to a bitmap using MemoryStream:
while (transcoder.Pull(out inputIndex, yuvFrame))
{
buffer = (MediaBuffer) yuvFrame.Buffer.Clone();
Bitmap b;
byte[] temp = new byte[buffer.DataSize];
Array.Copy(buffer.Start, buffer.DataOffset, temp, 0, buffer.DataSize);
var ms = new MemoryStream(temp);
b = new Bitmap(ms);
}
The aforementioned exception is thrown in the last line of the code. I'm not sure if it's the color format or the stream type, or something else that's causing the problem. If someone wants to see more of the code (setting up input & output sockets etc), let me know. For reference, the link to the example I've been following from AVBlocks is this and the link to MediaBuffer class is this.
The Bitmap(MemoryStream ms) constructor expects the bytes from an actual file, like a png, jpeg, bmp or gif. If I'm reading this correctly, you don't have that; you only have pure RGB triplets data. That isn't enough, because it lacks all information about the image's width, height, colour depth etc.
You will need to actually construct an image object from the RGB data. This isn't really trivial; it means you need to make a new image object with the correct dimensions and colour format, then access its backing bytes array, and write your data into it. The actual code for creating an image out of a byte array can be found in this answer.
Note that you'll have to take into account the actual stride in the resulting data you get; the amount of bytes on each line of the image. Images are saved per line, and those lines are usually padded to a multiple of 4 bytes. This obviously messes up a lot if you don't take it into account.
If your data is completely compact, then the stride to give to the BuildImage function I linked to will just be your image width multiplied by the amount of bytes per pixel (should be 3 for 24bpp RGB), but if not, you'll have to pad it to the next multiple of 4.

Reading image to byte array and changing it

I am trying to work with MemoryStream in C#.
So, I do converting Image to byte array and byte array to Image.
Like this
var bytes = File.ReadAllBytes("1.jpg");
var ms = new MemoryStream(bytes, true);
var image = Image.FromStream(ms);
pictureBox1.Image = image;
It works fine (displaying image in picture box). But when i try to change byte array
bytes[0] = 254
It throws exception invalid parameter.
So, how I can change byte array or write bytes to stream? ms.WriteByte not works. Thanks
JPEG (JPG) file is compressed representation of an image. It has complex structure, it is not byte matrix. Modification of first byte in it will most likely render it invalid. You better apply your modifications to image. And then save image as JPEG.

Saving and retrieving an image from database in c#

I've got a c# application which saves and displays records, When saving a record with an image using the picture box it seems as though the image has saved just fine but in the database all the images seem to have the same tag
[BLOB - 13B]
when saving the exact same image into the database manually using the dbms the image tag will read
[BLOB - 2.4KB]
with this tag I can use my image display method and it will be fine
The image is being converted or something when being saved but I cant seem to understand what is the problem.
here is the code for selecting and saving the image
MemoryStream ms = new MemoryStream();
pictureBox.Image.Save(ms, pictureBox.Image.RawFormat);
byte[] img = ms.ToArray();
because of the way this code changes the image, when retrieving it, I receive an error which says "parameter is invalid"
using c# and a mysqldatabase, although the database type is irrelevant.
Anyone understand what is going wrong?
It sounds like you're saving a byte array of your image to your database and need to know how to convert that byte array back into an image so that it can be displayed. You can do that with a function like this:
public Image ConvertByteArrayToImage(byte[] byteArray)
{
MemoryStream ms = new MemoryStream(byteArray, 0, byteArray.Length);
ms.Write(byteArray, 0, byteArray.Length);
Image image = Image.FromStream(ms, true);
return image;
}
UPDATE: After reading it over again. I don't think I answered the actual question you were asking. It sounds like your not converting your image into a byte array. I would try taking the image from your picturebox and putting it into an Image object. Then converting that Image object into a byte array. Rather than saving picturebox.Image.RawFormat
For any future readers.
I figured out my own problem after some research, turns out that when I was concatenating the SQL string and placing the byte array into it, the byte array would be changed to follow the string parameters. Hence the blob in the database would say [Blob 13B] only rather than the 2.7KB it should have been
To avoid this, you have to use a "parameterized" SQL query and not a standard concatenated one.
see Why my BLOB field is still 13B - what I am doing wrong?
and SQL Insert Query Using C#

Can't figure out where these C# and Java code differ

I have some C# code that converts an image to base64 string. The code is :
MemoryStream ms = new MemoryStream();
Image img = Image.FromFile(filename);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
string s = Convert.ToBase64String(ms.GetBuffer());
I am trying to implement it with JAVA. my java code is :
BufferedImage img = null;
img = ImageIO.read(new File(filename));
byte[] bytes = ((DataBufferByte)img.getData().getDataBuffer()).getData();
String js = Base64.encodeBase64String(bytes);
this two piece of code should return the same string for the same image file. But they are returning different strings. I am unable to figure out why. Can anyone shed some light on it?
this two piece of code should return the same string for the same image file
No, they really shouldn't.
The C# code is returning the base64 representation of a JPEG-encoded version of the image data - and potentially some 0s at the end, as you're using GetBuffer instead of ToArray. (You want ToArray here.)
The Java code is returning the base64 representation of the raw raster data, according to its SampleModel. I'd expect this to be significantly larger than the string returned by the C# code.
Even if both pieces of code encoded the image with the same format, that doesn't mean they'll come up with the exact same data - it will depend on the encoding.
Importantly, if you just want "the contents of the file in base64" then you don't need to go via an Image at all. For example, in C# you could use:
string base64 = Convert.ToBase64String(File.ReadAllBytes(filename));
The fact that it's an image is irrelevant in that respect - the file is just a collection of bytes, and you can base64-encode that without understanding the meaning of those bytes at all.

Categories

Resources