How can I save a PictureBox graphics object to a Stream? [duplicate] - c#

i wanna save a picture that loaded in a picturebox to stream .when i save in png format it work properly but when i want save it in other formats i get
A Generic error occured in GDI + exception
its my code:
Image Img = pictureBox1.Image;
byte[] inputImage = new byte[Img.Width * Img.Height];
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ms.Read(inputImage, 0, Img.Width * Img.Height);
if (System.Drawing.Imaging.ImageFormat.Jpeg.Equals(Img.RawFormat))
{
pictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else if (System.Drawing.Imaging.ImageFormat.Gif.Equals(Img.RawFormat))
{
ms.Seek(0, SeekOrigin.Begin);
pictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
}
else if (System.Drawing.Imaging.ImageFormat.Png.Equals(Img.RawFormat))
{
pictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
}
else if (System.Drawing.Imaging.ImageFormat.Bmp.Equals(Img.RawFormat))
{
pictureBox1.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
}

Try this method:
public Stream ImageToStream(Image image, System.Drawing.Imaging.ImageFormat format)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, format);
return ms;
}
and use it:
using(Stream stream = ImageToStream(pictureBox1.Image,
System.Drawing.Imaging.ImageFormat.Gif))
{
...
}

Related

WCF: using memorystream to transfer bitmaps in C#

I am using WCF for communication between client and server program on the same machine. Earlier I used Bitmaps to transfer video frames to the client. It was successful with WCF, but I only have 6 megabytes / sec LAN. Transferring 1.2Mb every second would block the LAN. I decided to JPEG encode the captured Bitmaps from the camera. It is possible to save a JPEG on the disk from a bitmap, or to a Memorystream. I created a
[MessageContract]
public class RemoteResponse
{
[MessageBodyMember(Order = 1)]
public System.IO.MemoryStream jpegImage;
}
I return this back from the (I)LiveImageService.
As I get it out in the client: RemoteResponse ret = client.GetLiveImage();
MemoryStream returnedImage = returnedResponse.jpegImage;
returnedImage.Position = 0L;
returnedImage.Seek(0, SeekOrigin.Begin);
args.image = returnedImage;
I do this in the event handler:
args.image.Position = 0L;
args.image.Seek(0, SeekOrigin.Begin);
//bitmap = new Bitmap(args.image);
bitmap = (Bitmap)Image.FromStream(args.image);
It gives me a "parameter is not valid" exception.
I have read that this is a buggy solution of Microsoft. Actually the
retreived stream is believed to be 21 bytes long because there is a trailing
zero \0 at the end of the leading "System.Drawing.Bitmap"\0. That is why the
processing of the image is stopped.
I have read a solution that avoids this:
byte[] arr = PdfReader.FlateDecode(PdfReader.GetStreamBytesRaw((PRStream)obj), true);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, pixelFormat);
System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);
Marshal.Copy(arr, 0, bmd.Scan0, arr.Length);
bmp.UnlockBits(bmd);
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png); // here it is the trick
arr = ms.GetBuffer(); // now I replace my incorrect image format bytes for the correct ones
System.Drawing.Image image = System.Drawing.Image.FromStream(ms);
image.Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
How does the last arr = ... have any effect? It is not used anymore later?
So I don't understand.
update:
On a Microsoft website: https://social.msdn.microsoft.com/Forums/vstudio/en-US/f9e39595-04ca-42ae-a353-eb1a08602631/resolved-creating-image-file-parameter-is-not-valid?forum=netfxbcl
I rewrote the example so:
public static Bitmap DecodeJPEGFromMemoryStream(MemoryStream stream, int width, int height, PixelFormat pixelFormat)
{
string content = System.Text.Encoding.UTF8.GetString(stream.ToArray());
byte[] arr = Encoding.UTF8.GetBytes(content);
//byte[] arr = PdfReader.FlateDecode(PdfReader.GetStreamBytesRaw((PRStream)obj), true);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, pixelFormat);
System.Drawing.Imaging.BitmapData bmd = bmp.LockBits(new
System.Drawing.Rectangle(0, 0, width, height),
System.Drawing.Imaging.ImageLockMode.WriteOnly, pixelFormat);
Marshal.Copy(arr, 0, bmd.Scan0, arr.Length);
bmp.UnlockBits(bmd);
using (MemoryStream ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // here it is the trick
arr = ms.GetBuffer(); // now I replace my incorrect image format bytes for the correct ones
System.Drawing.Image image = System.Drawing.Image.FromStream(ms);
Bitmap ret = new Bitmap(image);
return ret;
}
}
I can see the image in the Picturebox, but it has only 2 lines, flickering.
If I obscure the camera I see that it darkens. So the data comes through now. But I cannot reconstruct my JPEG live data.
I was able to decode the JPEG data, only with saving it to disk.
So I've got the image without error. I tried to save the image only
temporarily and delete after.
public static Bitmap DecodeJPEGFromMemoryStream(MemoryStream stream, int width, int height, PixelFormat pixelFormat)
{
try
{
if(File.Exists("c:\\imagecache.jpg") == true)
File.Delete("c:\\imagecache.jpg");
//using (FileStream file = new FileStream("c:\\imagecache.jpg", FileMode.CreateNew, System.IO.FileAccess.ReadWrite))
using (FileStream file = File.Open("c:\\imagecache.jpg", FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite))
{
stream.WriteTo(file);
//JpegBitmapDecoder decoder = new JpegBitmapDecoder(file, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
file.Close();
file.Dispose();
}
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
//BitmapSource bitmapSource = decoder.Frames[0];
Bitmap jpeg;
{
{
FileInfo info = new FileInfo("c:\\imagecache.jpg");
if (info.Length == 0)
{
File.Delete("c:\\imagecache.jpg");
return null;
}
}
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
jpeg = (Bitmap)Image.FromFile("c:\\imagecache.jpg"); //the process cannot access the file...
}
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
if (File.Exists("c:\\imagecache.jpg") == true)
File.Delete("c:\\imagecache.jpg");
return jpeg;
}
catch(Exception ex)
{
return null;
}
}
I get the exception: The process cannot access the file "imagecache.jpg",
because it is being used by another process. Exception comes at the FromFile.
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
Bitmap retImage = (Bitmap)jpeg.Clone();
jpeg.Dispose();
if (File.Exists("c:\\imagecache.jpg") == true)
{
System.IO.FileInfo fi = new System.IO.FileInfo("c:\\imagecache.jpg");
fi.Delete();
}
return retImage;
}
catch (Exception ex)
{
return null;
}
finally
{
stream.Dispose();
}
It is fixed so. Image.FromFile: the File remains locked until the Image is disposed.
So I cloned my Image and disposed the old one.
Before I've seen my Image, now nothing is visible.

conversion from BitmapImage to byte array causing high memory usage

I have jpeg.
I convert it to a BitmapImage.
I then reduce the quality (compression).
I then covert to byte array.
I have found the memory escalates very quickly in task manager.
I am certain I am disposing all that I can.
This is my code:
//I am calling this from within a timer set 500ms
byte[] datatest = JpegXr.SaveJpegXrToBytes((Bitmap)frame.Clone(), 40f);
frame.Dispose();
public static class JpegXr
{
public static Bitmap BitmapImage2Bitmap(BitmapImage bitmapImage)
{
// BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative));
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapImage));
enc.Save(outStream);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);
// return bitmap; <-- leads to problems, stream is closed/closing ...
return new Bitmap(bitmap);
}
}
public static byte[] SaveJpegXrToBytes(Bitmap bitmap, float quality)
{
byte[] data = null;
var stream = new MemoryStream();
SaveJpegXr(bitmap, quality, stream);
stream.Seek(0, SeekOrigin.Begin);
data= stream.ToArray();
stream.Close();
bitmap.Dispose();
return data;
}
private static BitmapImage Bitmap2BitmapImage(Bitmap bitmap)
{
BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHbitmap(),
IntPtr.Zero, System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
//BitmapSource bitmapSource = Clipboard.GetImage();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
MemoryStream memoryStream = new MemoryStream();
BitmapImage bImg = new BitmapImage();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(memoryStream);
bImg.BeginInit();
bImg.StreamSource = new MemoryStream(memoryStream.ToArray());
bImg.EndInit();
memoryStream.Close();
bitmap.Dispose();
return bImg;
//return (BitmapImage)i;
//return i;
}
private static void SaveJpegXr(Bitmap bitmap, float quality, Stream output)
{
BitmapImage bitmapSource = Bitmap2BitmapImage((Bitmap)bitmap.Clone());
//var bitmapSource = bitmap.ToWpfBitmap();
var bitmapFrame = BitmapFrame.Create(bitmapSource);
var jpegXrEncoder = new WmpBitmapEncoder();
jpegXrEncoder.Frames.Add(bitmapFrame);
jpegXrEncoder.ImageQualityLevel = quality / 100f;
jpegXrEncoder.Save(output);
bitmap.Dispose();
}
}
Is it just the case that doing these conversions is memory consuming by its very nature and as such calling it frequently from within a timer does not give the garbage collector time to dispose objects correctly?
Appreciate peoples wisdom on this...

Convert bitmap to ImageSource give NullReference exception

I've got WCF service to send image as a stream to client app.
My client app gets the stream :
Stream imageStream = client.GetImage();
When I use this code:
imageStream.CopyTo(stream);
int size = (int)stream.Length;
stream.Seek(0, SeekOrigin.Begin);
BitmapFrame bf = BitmapFrame.Create(stream,
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
cam_img.Source = bf;
It work's fine but I need apply some filters to image before assign to source.
So I need bitmap. First, I convert Stream imageStream to byte array and then I use some code I find on forums:
byte[] tab_img;
using (var memoryStream = new MemoryStream())
{
imageStream.CopyTo(memoryStream);
tab_img= memoryStream.ToArray();
}
Bitmap bm;
using (MemoryStream mStream = new MemoryStream())
{
mStream.Write (tab_img, 0, tab_img.Length);
mStream.Seek(0, SeekOrigin.Begin);
bm = new Bitmap(mStream);
Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721);
Bitmap bm_post = filter.Apply(bm);
ImageSourceConverter c = new ImageSourceConverter();
object source = new ImageSourceConverter().ConvertFrom(bm_post);
ImageSource is1 = (ImageSource)source;
cam_img.Source = is1;
}
but I still get NullReferenceException in line
object source = new ImageSourceConverter().ConvertFrom(bm_post);

ExifLib requires a seekable stream

I am getting an error while instantiating ExifReader in Windows Phone 8 C#. Please find the code snippet below. Kindly do the needful
Error : "ExifLib requires a seekable stream"
byte[] imageBytes = (byte[])PhoneApplicationService.Current.State["ViewImage"];
MemoryStream ms = new MemoryStream(imageBytes,0,imageBytes.Length);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(ms);
try
{
ExifReader xif = new ExifReader(toStream(bitmapImage)); // Getting Error here
double gpsLat, gpsLng;
xif.GetTagValue<double>(ExifTags.GPSLatitude, out gpsLat);
xif.GetTagValue<double>(ExifTags.GPSLongitude, out gpsLng);
map.Center = new System.Device.Location.GeoCoordinate(gpsLat, gpsLng);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
Stream toStream(BitmapImage img)
{
WriteableBitmap bmp = new WriteableBitmap((BitmapSource)img);
using (MemoryStream stream = new MemoryStream())
{
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
stream.Position = 0;
return stream;
}
}
Your MemoryStream is returning false when CanSeek is called. This is because you've wrapped your MemoryStream in a using statement, which means that you're returning a disposed object.
Your toStream method should actually look like this:
Stream ToStream(BitmapImage img)
{
MemoryStream stream = new MemoryStream();
using (WriteableBitmap bmp = new WriteableBitmap((BitmapSource)img))
{
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
}
stream.Position = 0;
return stream;
}

How to put image in a picture box from a byte[] in C#

I've a byte array which contains an image binary data in bitmap format. How do I display it using the PictureBox control in C#?
I went thru a couple of posts listed below but not sure if I need to convert the byte array into something else before sending it to a picturebox. I'd appreciate your help. Thanks!
How to put image in a picture box from Bitmap
Load Picturebox Image From Memory?
This function converts byte array into Bitmap which can be use to set the Image Property of the picturebox.
public static Bitmap ByteToImage(byte[] blob)
{
MemoryStream mStream = new MemoryStream();
byte[] pData = blob;
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Bitmap bm = new Bitmap(mStream, false);
mStream.Dispose();
return bm;
}
Sample usage:
pictureBox.Image = ByteToImage(byteArr); // byteArr holds byte array value
byte[] imageSource = **byte array**;
Bitmap image;
using (MemoryStream stream = new MemoryStream(imageSource))
{
image = new Bitmap(stream);
}
pictureBox.Image = image;
using System.IO;
byte[] img = File.ReadAllBytes(openFileDialog1.FileName);
MemoryStream ms = new MemoryStream(img);
pictureBox1.Image = Image.FromStream(ms);
or you can access like this directly,
pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);
You can also convert pictureBox image to byte array like this,
MemoryStream ms = new MemoryStream();
pictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] img = ms.ToArray();
The ImageConverter class in the System.Drawing namespace can do the conversion:
byte[] imageArray = **byte array**
ImageConverter converter = new ImageConverter();
pictureButton.Image = (Image)converter.ConvertFrom(imageArray);
If you want to use BinaryReader to convert then use like this,
FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] img = br.ReadBytes((int)fs.Length);
Try this for Converting Bitmap Images to array of bytes for jpeg pictures and png file types:
public byte[] UdfConvertPicToByte(Bitmap bitmapImages)
{
using (MemoryStream stream = new MemoryStream())
{
bitmapImages.Compress(Bitmap.CompressFormat.Png, 0, stream);
byte[] bitmapData = stream.ToArray();
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 50, stream);
bitmapData = stream.ToArray();
return bitmapData;
}
}

Categories

Resources