I have the following code trying to compress a bitmap and use it for uploading.
Bitmap bitmap1 = BitmapFactory.DecodeByteArray(imageFileByte, 0, imageFileByte.Length);
byte[] compressedData = null;
using (var stream = new MemoryStream())
{
bitmap1.Compress(Bitmap.CompressFormat.Jpeg, 50, stream);
compressedData = stream.ToArray();
}
//load compressed bitmap from memory
using (var anotherStream = new MemoryStream(compressedData))
{
var compressedBitmap = BitmapFactory.DecodeStream(anotherStream);
}
When I debug, bitmap1 on line 1 shows 3021330 bytes, when come to the compressedData on line 6, it did shrink to 70128 bytes.
Now I want to convert again the compressedData to a bitmap again since it is a byte array but not a bitmap, when it comes to line 11, the compressedBitmap shows exactly same number of bytes with the bitmap1.
How can I actually use the bitmap that has already been compressed?
Is it possible to compress a bitmap and save the compressed one as a bitmap again?
Thanks for any comment.
Related
I am trying to convert my mediumblob data which is in MySQL to Bitmap image, but I cannot do it. I am getting an error which is
Parameter is not valid.
This is my c# code:
MySqlCommand select = new MySqlCommand("Select FaceName, FaceImage From TrainingSet1", conn);
MySqlDataReader reader = select.ExecuteReader();
while (reader.Read())
{
labels.Add(reader["FaceName"].ToString());
byte[] buffer = (byte[])reader["FaceImage"];
MessageBox.Show("kw");
MemoryStream ms = new MemoryStream(buffer);
ms.Write(buffer, 0, buffer.Length);
Bitmap bmp = new Bitmap(ms); //prb is here
MessageBox.Show("remy");
Image<Gray, byte> image = new Image<Gray, byte>(bmp);
trainingImages.Add(image);
}
reader.Close();
This is my image adding functionality into the database:
private byte[] ConvertToDBFormat(IImage InputImage)
{
Bitmap BmpImage = new Bitmap(InputImage.Bitmap);
MemoryStream MyStream = new MemoryStream();
BmpImage.Save(MyStream, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] ImageAsBytes = MyStream.ToArray();
return ImageAsBytes;
}
Can someone help me with this. Thank you.
When you do:
MemoryStream ms = new MemoryStream(buffer);
ms.Write(buffer, 0, buffer.Length);
You're first initializing the memory stream with the buffer, and then promply overwriting it with the same data - setting the current position to the end of the stream. When the Bitmap class tries to read from it - it won't get anything.
Simply skip the Write call and the memory stream will supply the data from the byte array.
Also - I would suggest having a using block around the memory stream and reader. And, if that Image<> class of you doesn't keep a reference around to the Bitmap, you should dispose of it immediately.
I have this code (C#):
unsafe private Bitmap Test()
{
Bitmap test = null;
byte[] data = memRenderAll.CurrentData;
fixed (byte* m_pBuffer = _data)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
Bitmap a = new Bitmap(720, 576, 2160, System.Drawing.Imaging.PixelFormat.Format24bppRgb, new IntPtr(m_pBuffer));
a.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
test =(Bitmap) Image.FromStream(ms);
a.Dispose();
}
}
return _test;
}
By saving the stream as this:
a.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
I get a 10:1 reduction is size.
Is there a way of avoiding this:
a.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
and specifying it somewhere/somehow in:
Bitmap a = new Bitmap(720, 576, 2160, System.Drawing.Imaging.PixelFormat.Format24bppRgb, new IntPtr(m_pBuffer));
as I would like to create the Bitmap only once.
thanks,
Andrew
I think its impossible todo in one code line using standard System.Drawing.
You use that constructor: http://msdn.microsoft.com/en-us/library/zy1a2d14(v=vs.110).aspx
Your code:
new Bitmap(720, 576, 2160, System.Drawing.Imaging.PixelFormat.Format24bppRgb, new IntPtr(m_pBuffer));
What does it mean? Bitmap read memory pointed by m_pBuffer using fixed width, height, stride and pixel format. You can't read it as jpeg, because jpeg - image zipping fomat. Look on it: http://en.wikipedia.org/wiki/JPEG#JPEG_codec_example . Jpeg codec need all your image for ziping, it can't zip parts and join them after.
I am trying to convert bitmap Image to Byte array. I have select all the image by using MediaLibrary class and added it into a list of bitmap images. Here is my code
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists("ImagesZipFolder"))
{
store.CreateDirectory("ImagesZipFolder");
for (int i = 0; i < imgname.Count(); i++)
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(#"ImagesZipFolder\" + imgname[i], System.IO.FileMode.CreateNew, store))
{
byte[] bytes = null;
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap wBitmap = new WriteableBitmap(ImgCollection[i]);
wBitmap.SaveJpeg(ms, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
bytes = ms.GetBuffer();
stream.Write(bytes, 0, bytes.Length);
}
// byte[] bytes = Encoding.UTF8.GetBytes(imgname[i]);//new byte[ImgCollection[i].PixelWidth * ImgCollection[i].PixelHeight * 4];
// stream.Write(bytes, 0, bytes.Length);
}
}
}
else {
directory = true;
}
}
Basically what I am trying to do is, selecting all images or photo from device and create a zip file of that images. I was successful in creating a zip file of images. When I extract that file there is some images, but the problem is when I double click on image, I can't see that image. I think the problem is in reading the bytes of image. I am not getting what's wrong? Is my code is correct ?
Perhaps you can try the below. I know this code maintains the image, so if you have no luck using this, you may have a different issue.
// Convert the new image to a byte[]
ImageConverter converter = new ImageConverter();
byte[] newBA = (byte[])converter.ConvertTo(newImage, typeof(byte[]));
The ImageConverter is of the System.Drawing namespace.
Update:
http://msdn.microsoft.com/en-GB/library/system.windows.media.imagesourceconverter.convertto.aspx
You should be able to use this in place of the System.Drawing type I suggested.
There is no need to save the WriteableBitmap to a MemoryStream and then copy it to an IsolatedStorageFileStream. Just save the bitmap directly to the IsolatedStorageFileStream.
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(#"ImagesZipFolder\" + imgname[i], System.IO.FileMode.CreateNew, store))
{
WriteableBitmap wBitmap = new WriteableBitmap(ImgCollection[i]);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
}
This will allow you to save on memory as well. If you really want to save memory, you could reuse the WriteableBitmap.
I'm trying to do image processing on wp7,
and now i finished convertImagetoBytes and convertByteToBitmapImage.
I suppose I can change the values in the byte array to do some image processing work,
but it turns out to be a black image in the picturebox.
(Now I just wanna process .jpg images)
convertImagetoBytes
byte[] data = null;
using (MemoryStream stream = new MemoryStream())
{
WriteableBitmap wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
data = stream.GetBuffer();
}
convertBytestoImage
MemoryStream stream = new MemoryStream(bytes);
stream.Position = 0;
BitmapImage bi = new BitmapImage();
bi.SetSource(stream);
return bi;
now if i change the values in the byte array,just like this(grayscale)
for (int i = 0; i < bytesCount; i+=4)
{
colorTemp = data[i+2];
data[i+1 ] =data[i+2]= data[i + 3] = (byte)colorTemp;
}
the image turns out to be black.
You've saved it as a JPEG - but you appear to be trying to change it as if it were raw data. You can't just mess around with the data of a JPEG file to fake greyscale.
By the way, you should use stream.ToArray instead of stream.GetBuffer() as the latter will usually be larger than the real data.
You should also look into using René Schulte's WriteableBitmapEx library.
And consider reading this article about a Windows Phone Picture Effects Application
I am capturing images from a smart camera imager and receiving the byte array from the camera through socket programming (.NET application is the client, camera is the server).
The problem is that i get System.InvalidArgument exception at runtime.
private Image byteArrayToImage(byte[] byteArray)
{
if(byteArray != null)
{
MemoryStream ms = new MemoryStream(byteArray);
return Image.FromStream(ms, false, false);
/*last argument is supposed to turn Image data validation off*/
}
return null;
}
I have searched this problem in many forums and tried the suggestions given by many experts but nothing helped.
I dont think there is any problem with the byte array as such because When i feed the same byte array into my VC++ MFC client application, i get the image. But this doesn't somehow work in C#.NET.
Can anyone help me ?
P.S :
Other methods i've tried to accomplish the same task are:
1.
private Image byteArrayToImage(byte[] byteArray)
{
if(byteArray != null)
{
MemoryStream ms = new MemoryStream();
ms.Write(byteArray, 0, byteArray.Length);
ms.Position = 0;
return Image.FromStream(ms, false, false);
}
return null;
}
2.
private Image byteArrayToImage(byte[] byteArray)
{
if(byteArray != null)
{
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap b = (Bitmap)tc.ConvertFrom(byteArray);
return b;
}
return null;
}
None of the above methods worked. Kindly help.
Image.FromStream() expects a stream that contains ONLY one image!
It resets the stream.Position to 0. I've you have a stream that contains multiple images or other stuff, you have to read your image data into a byte array and to initialize a MemoryStream with that:
Image.FromStream(new MemoryStream(myImageByteArray));
The MemoryStream has to remain open as long as the image is in use.
I've learned that the hard way, too.
Maybe the image is embedded in an OLE field and you have to consider the 88 bytes OLE header plus payload:
byteBlobData = (Byte[]) reader.GetValue(0);
stream = new MemoryStream(byteBlobData, 88, byteBlobData.Length - 88);
img = Image.FromStream(stream);
I'm guessing that something is going wrong when receiving the file from the server. Perhaps you're only getting part of the file before trying to convert it to an Image? Are you sure it's the exact same byte array you're feeding the C++ application?
Try saving the stream to a file and see what you get. You might be able to uncover some clues there.
You can also add a breakpoint and manually compare some of the bytes in the byte array to what they're supposed to be (if you know that).
Edit: It looks like there's nothing wrong with receiving the data. The problem is that it's in raw format (not a format that Image.FromStream understands). The Bitmap(Int32, Int32, Int32, PixelFormat, IntPtr) constructor may be of use here. Or, you can create the blank bitmap and blt it manually from the raw data.
I've had this problem when doing this:
MemoryStream stream = new MemoryStream();
screenshot.Save(stream, ImageFormat.Png);
byte[] bytes = new byte[stream.Length];
stream.Save(bytes, 0, steam.Length);
With the last 2 lines being the problem. I fixed it by doing this:
MemoryStream stream = new MemoryStream();
screenshot.Save(stream, ImageFormat.Png);
byte[] bytes = stream.ToArray();
And then this worked:
MemoryStream stream = new MemoryStream(bytes);
var newImage = System.Drawing.Image.FromStream(stream);
stream.Dispose();
System.InvalidArgument means The stream does not have a valid image format, i.e. an image type that is not supported.
Try this:
public Image byteArrayToImage(byte[] item)
{
Image img=Image.FromStream(new MemoryStream(item));
img.Save(Response.OutputStream, ImageFormat.Gif);
return img;
}
Hope it helps!
I've had the same problem in the past and it was caused by a leak within the windows GDI libraries, which is what 'Bitmap' uses. If this happening all the time for you then its probably unrelated, however.
this code is working
string query="SELECT * from gym_member where Registration_No ='" + textBox9.Text + "'";
command = new SqlCommand(query,con);
ad = new SqlDataAdapter(command);
DataTable dt = new DataTable();
ad.Fill(dt);
textBox1.Text = dt.Rows[0][1].ToString();
textBox2.Text = dt.Rows[0][2].ToString();
byte[] img = (byte[])dt.Rows[0][18];
MemoryStream ms = new MemoryStream(img);
pictureBox1.Image = Image.FromStream(ms);
ms.Dispose();
Try to use something similar to what is described here https://social.msdn.microsoft.com/Forums/vstudio/en-US/de9ee1c9-16d3-4422-a99f-e863041e4c1d/reading-raw-rgba-data-into-a-bitmap
Image ImageFromRawBgraArray(
byte[] arr,
int charWidth, int charHeight,
int widthInChars,
PixelFormat pixelFormat)
{
var output = new Bitmap(width, height, pixelFormat);
var rect = new Rectangle(0, 0, width, height);
var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);
// Row-by-row copy
var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat) / 8;
var ptr = bmpData.Scan0;
for (var i = 0; i < height; i++)
{
Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
ptr += bmpData.Stride;
}
output.UnlockBits(bmpData);
return output;
}
After load from DataBase byteArray has more byte than one image. In my case it was 82.
MemoryStream ms = new MemoryStream();
ms.Write(byteArray, 82, byteArray.Length - 82);
Image image = Image.FromStream(ms);
And for save in the DB I insert 82 byte to begin stream. Properties.Resources.ImgForDB - it is binary file that contain those 82 byte. (I get it next path - Load Image from DB to MemoryStream and save to binary file first 82 byte. You can take it here - https://yadi.sk/d/bFVQk_tdEXUd-A)
MemoryStream temp = new MemoryStream();
MemoryStream ms = new MemoryStream();
OleDbCommand cmd;
if (path != "")
{
Image.FromFile(path).Save(temp, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Write(Properties.Resources.ImgForDB, 0, Properties.Resources.ImgForDB.Length);
ms.Write(temp.ToArray(), 0, temp.ToArray().Length);
cmd = new OleDbCommand("insert into Someone (first, Second, Third) values (#a,#b,#c)", connP);
cmd.Parameters.AddWithValue("#a", fio);
cmd.Parameters.AddWithValue("#b", post);
cmd.Parameters.AddWithValue("#c", ms.ToArray());
cmd.ExecuteNonQuery();