I'm doing a C# web service soap receiving an image.
I send a string contain the byte characters.
I transform the string in byte[] and next I world like to create the Bitmap.
The line Bitmap img = new Bitmap(ms); generate an exception : invalid argument.
I have a in the ms object this error : System.InvalidOperationException
value contain the correct string, imgBytes contain the good number of sell.
public string GetImage(string value)
{
byte[] imgBytes = Encoding.ASCII.GetBytes(value);
MemoryStream ms = new MemoryStream(imgBytes, true);
Bitmap img = new Bitmap(ms);
Code with debug mode
Exception
Thank you for your help.
It looks like your string holds base64 encoded data. Try to decode it to a byte array via Convert.FromBase64String
I had a similar problem. Basically you write into your memory stream (in the constructor) and the position pointer is at the end. So before reuse the memory stream you can try setting its position pointer to the beginning. Like this:
MemoryStream ms = new MemoryStream(imgBytes, true);
ms.Position = 0;
Bitmap img = new Bitmap(ms);
or the more general approach:
MemoryStream ms = new MemoryStream(imgBytes, true);
ms.Seek(0, SeekOrigin.Begin);
Bitmap img = new Bitmap(ms);
Hope this will solve your Problem.
Update
I think #heinbeinz answer is also important: First decode your string from the right encoding (normally base64), then set the position.
Related
I would need to take a screenshot, if easy to without saving it. I would sent the image data directly to a PHP script. Because I don't have this PHP script at the moment, so I search for the easiest way of format in which I should convert the screenshot data. For debugging reasons until I've got my PHP script I would like to convert a picture of these data on my client side using C#.
My code at the moment for taking a screenshot and convert it (I'm not sure if I can convert the output in my logfile back into a picture):
internal static byte[] ImageToByteArray(Image img)
{
byte[] byteArray = new byte[0];
MemoryStream stream = new MemoryStream();
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
return byteArray;
}
public static string TakeScreenshot()
{
String filepath = #"C:\log2.txt";
Bitmap bitmap = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bitmap);
graphics.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
graphics.Dispose();
bitmap.Save("C:\\temp.png");
Image img = (Image)bitmap;
string str = System.Text.Encoding.Default.GetString(ImageToByteArray(img));
System.IO.File.AppendAllText(filepath, str);
//just for debugging
return "OH";
}
Main question at the moment, is there any way to get a picture back from my converted code (log2.txt).
This line of code:
string str = System.Text.Encoding.Default.GetString(ImageToByteArray(img));
Will almost certainly not do what you want it to do. It will try to interpret your byte array as a string in whatever is the default character encoding on your machine. If the default is something like UTF-8 or any multibyte character set, then it's quite likely to fail. Even if the default encoding is a single-byte character set, it could create a string that can't be reliably turned back into the original byte array.
If you really want to store the byte array as text, you can call Convert.ToBase64String:
string str = Convert.ToBase64String(ImageToByteArray(img));
If you read that string back from the file into str, you can rebuild the byte array with:
byte[] imageBytes = Convert.FromBase64String(str);
Another advantage in your particular case is that there are PHP functions for dealing with base 64 strings.
My friends,
I am trying convert a image to a Base64 String in a c# console app (.net 4.0).
The method:
public static String ConvertBitmapToBase64String(Bitmap bitmap,
ImageFormat imageFormat)
{
String generatedString = string.Empty;
MemoryStream memoryStream = new MemoryStream();
bitmap.Save(memoryStream, imageFormat);
memoryStream.Position = 0;
byte[] byteBuffer = memoryStream.ToArray();
memoryStream.Close();
generatedString = Convert.ToBase64String(byteBuffer);
byteBuffer = null;
return generatedString;
}
But when I invoke this method it is throwing an exception saying: "generic gdi+ error" and the error number is -2147467259.
Invoker code:
StreamReader streamReader = new StreamReader(#"C:\Anita.jpg");
Bitmap bitmap = new Bitmap(streamReader.BaseStream);
streamReader.Close();
String base64String = ImageUtil.ConvertBitmapToBase64String(bitmap, ImageFormat.Jpeg);
Anybody can give me a help?
Thanks.
The only likely problem I see is that the image is too large or big. Perhaps, instead of using a MemoryStream, you can use File.ReadAllBytes directly instead of passing around the Bitmap object, saving directly to a MemoryStream, and saving.
Also, you're reading the data in with a StreamReader, which is meant for text! Moving to just reading the bytes into an array and calling Convert.ToBase64String() should handle what you want to do.
My goal is to upload and download images using a web service. I understand that in order to do that the images need to be converted to a byte array. However, I’m getting “Unspecified error” when converting a byte array into a BitmapImage.
I’ve create a test rig that converts an image (from a PhotoChooserTask) into a byte array and back again that recreates my problem. The code that does the conversion is listed below with the problem line highlighted.
Any help would be appreciated!
private void PhotoChooserTaskCompleted(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
//Display the photo
BitmapImage PhotoBitmap = new BitmapImage();
PhotoBitmap.SetSource(e.ChosenPhoto);
Photo.Source = PhotoBitmap;
//Convert the photo to bytes
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length);
//Convert the bytes back to a bitmap
BitmapImage RestoredBitmap = new BitmapImage();
MemoryStream stream = new MemoryStream(PhotoBytes);
BitmapImage image = new BitmapImage();
RestoredBitmap.SetSource(stream); //<------ I get "Unspecified error" on this line
//Display the restored photo
RestoredPhoto.Source = RestoredBitmap;
}
}
The first time you use e.ChosePhoto as source, the stream is read and the Position property is advanced to the end. You can inspect the PhotoBytes array in the debugger to see that after your read operation it actually does not have any content (or check the return value of the Read method to confirm zero bytes are read).
What you need to do is reset that Position to zero before you read from it again:
//Convert the photo to bytes
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
// rewind first
e.ChosenPhoto.Position = 0;
// now succeeds
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length);
I would bet that this is what's happening (comments inline):
//Display the photo
BitmapImage PhotoBitmap = new BitmapImage();
PhotoBitmap.SetSource(e.ChosenPhoto); // This is reading from the stream
Photo.Source = PhotoBitmap;
//Convert the photo to bytes
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length); // Fails to read the full stream
// because you already read from it
//Convert the bytes back to a bitmap
BitmapImage RestoredBitmap = new BitmapImage();
MemoryStream stream = new MemoryStream(PhotoBytes); // You're creating a stream that
// doesn't contain the image
BitmapImage image = new BitmapImage();
RestoredBitmap.SetSource(stream); // Fails because your stream is incomplete
Seek to 0 in the stream before you attempt to read from it. And check the return value from the Read call to make sure it matches PhotoBytes.Length.
This:
//Display the photo
BitmapImage PhotoBitmap = new BitmapImage();
PhotoBitmap.SetSource(e.ChosenPhoto);
Photo.Source = PhotoBitmap;
uses the Stream of the e.ChosenPhoto and might not rewind the Position of the Stream.
So when you do this:
Byte[] PhotoBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(PhotoBytes, 0, PhotoBytes.Length);
you are starting at the end of the stream reading nothing.
Use Seek to reset the Position of the stream.
Did you check out my other post where I already did this?
I had receive a pretty good rating from it.
BitmapImage to byte[] and byte[] to BitmapImage
I am trying to convert a byte[] to Bitmap in c#. Following is the code:
MemoryStream ms = new MemoryStream(b);
Bitmap bmp = new Bitmap(ms);
It shows the error Parameter is not valid when creating the Bitmap.
byte[] b is coming from a network stream.
But when I write this byte[] to a file, and open this file in any image viewer just works perfectly. Following is code for writing the byte[] to file:
var fs = new BinaryWriter(new FileStream("tmp.bmp", FileMode.Create, FileAccess.Write));
fs.Write(b);
fs.Close();
What am I missing here?
EDIT
Here is my full code that was causing problem
Socket s = listener.AcceptSocket();
byte[] b = new byte[imgLen];
s.Receive(b);
MemoryStream ms = new MemoryStream(b);
// now here I am using ms.Seek(0, SeekOrigin.Begin); that fixed my problem.
Bitmap bmp = new Bitmap(ms);
pictureBox1.Image = bmp;
s.Close();
I am using this code on Form_Load event and there is nothing extra. I am just trying to display an Image that is streamed on network. The server is written in Java that is streaming this image.
Hope it clarifies the doubts.
Thanks
Okay, just to clarify things a bit... the problem is that new Bitmap(ms) is going to read the data from the stream's current position - if the stream is currently positioned at the end of the data, it's not going to be able to read anything, hence the problem.
The question claims that the code is this:
MemoryStream ms = new MemoryStream(b);
Bitmap bmp = new Bitmap(ms);
In that case there is no requirement to reset the position of the stream, as it will be 0 already. However, I suspect the code is actually more like this:
MemoryStream ms = new MemoryStream();
// Copy data into ms here, e.g. reading from NetworkStream
Bitmap bmp = new Bitmap(ms);
or possibly:
MemoryStream ms = new MemoryStream(b);
// Other code which *reads* from ms, which will change its position,
// before we finally call the constructor:
Bitmap bmp = new Bitmap(ms);
In this case you do need to reset the position, because otherwise the "cursor" of the stream is at the end of the data instead of the start. Personally, however, I prefer using the Position property instead of the Seek method, just for simplicity, so I'd use:
MemoryStream ms = new MemoryStream();
// Copy data into ms here, e.g. reading from NetworkStream
// Rewind the stream ready for reading
ms.Position = 0;
Bitmap bmp = new Bitmap(ms);
It just goes to show how important it is that the sample code in a question is representative of the actual code...
Try resetting current location in the stream
MemoryStream ms = new MemoryStream(b);
ms.Seek(0, SeekOrigin.Begin);
Bitmap bmp = new Bitmap(ms);
Try like this:
byte[] b = ...
using (var ms = new MemoryStream(b))
using (var bmp = Image.FromStream(ms))
{
// do something with the bitmap
}
Error is shown if you are disposing the image. Try removing that from code
I am converting images to byte array and storing in a text file using the following code. I am retrieving them successfully as well.
My concern is that the quality of the retrieved image is not up to the expectation. Is there a way to have better conversion to byte array and retrieving? I am not worried about the space conception.
Please share your thoughts.
string plaintextStoringLocation = #"D:\ImageSource\Cha5.txt";
string bmpSourceLocation = #"D:\ImageSource\Cha50.bmp";
////Read image
Image sourceImg = Image.FromFile(bmpSourceLocation);
////Convert to Byte[]
byte[] clearByteArray = ImageToByteArray(sourceImg);
////Store it for future use (in plain text form)
StoreToLocation(clearByteArray, plaintextStoringLocation);
//Read from binary
byte[] retirevedImageBytes = ReadByteArrayFromFile(plaintextStoringLocation);
//Retrieve from Byte[]
Image destinationImg = ByteArrayToImage(retirevedImageBytes);
//Display Image
pictureBox1.Image = destinationImg;
EDIT: And the solution is - use Base64
//Plain Text Storing Location
string plaintextStoringLocation = #"D:\ImageSource\GirlInflower23.txt";
string bmpSourceLocation = #"D:\ImageSource\GirlInflower1.bmp";
////Read image
Image sourceImg = Image.FromFile(bmpSourceLocation);
string base64StringOfIMage = ImageToBase64(sourceImg, ImageFormat.Bmp);
byte[] byteOfString = Convert.FromBase64String(base64StringOfIMage);
StoreToLocation(byteOfString, plaintextStoringLocation);
byte[] retrievedBytesForStrimngForImage = ReadByteArrayFromFile(plaintextStoringLocation);
MemoryStream memStream = new MemoryStream(retrievedBytesForStrimngForImage);
//memStream.Read();
Image retrievedImg = Image.FromStream(memStream);
pictureBox1.Image = retrievedImg;
Yes, it is possible to get completely lossless storage. If you just store it in its original BMP format there will be no problem. I assume you are converting it to text because you want to send it via some protocol where binary characters will be corrupted.
Instead of whatever you are doing, you could consider using Convert.ToBase64String.
I haven't had any problems with this fragment...try it...if you get good results then the problem is in your Image -> byte[] or byte[] -> Image code :)
Image srcImage;
Image destImage;
// load an image
srcImage = Image.FromFile(filename);
// save the image via stream -> byte[]
using(MemoryStream stream = new MemoryStream()){
image.Save(stream, ImageFormat.xxx);
byte[] saveArray = stream.ToArray();
/*..... strore saveArray......*/
}
// rehydrate
byte[] loadArray = /*...get byte array from storage...*/
using(MemoryStream stream = new MemeoryStream(loadArray)){
destImage = Image.FromStream(stream);
}
pictureBox.Image = dstImage;
// don't forget...dispose of any Image/Stream objects