I'm working on a C# Windows Form app project where i need to serialize PictureBox with JSON and save it to a file. For some reason JSON is giving me an error when trying to serialize the PictureBox:
"Newtonsoft.Json.JsonSerializationException: 'Self referencing loop detected for property 'Owner' with type 'System.Windows.Forms.PictureBox'. Path 'AccessibilityObject'.'"
I tried to create a new project and use the serializing on a PictureBox and it worked fine. What could possibly give the error on the current project i'm working on?
string dataToSave = JsonConvert.SerializeObject(bagPicture1);
You can serialize the img like this:
var img = this.pictureBox1.Image;
var ms = new MemoryStream();
// any ImageFormat you like, ImageFormat.Bmp for uncompressed
img.Save(ms, ImageFormat.Jpeg);
var serialized = JsonConvert.SerializeObject(ms.ToArray());
Restore the img:
var myBytes = JsonConvert.DeserializeObject<byte[]>(serialized);
var img = Bitmap.FromStream(new MemoryStream(myBytes));
Related
I'm working on a C# Windows Form app project where i need to serialize PictureBox with JSON and save it to a file. For some reason JSON is giving me an error when trying to serialize the PictureBox:
"Newtonsoft.Json.JsonSerializationException: 'Self referencing loop detected for property 'Owner' with type 'System.Windows.Forms.PictureBox'. Path 'AccessibilityObject'.'"
I tried to create a new project and use the serializing on a PictureBox and it worked fine. What could possibly give the error on the current project i'm working on?
string dataToSave = JsonConvert.SerializeObject(bagPicture1);
You can serialize the img like this:
var img = this.pictureBox1.Image;
var ms = new MemoryStream();
// any ImageFormat you like, ImageFormat.Bmp for uncompressed
img.Save(ms, ImageFormat.Jpeg);
var serialized = JsonConvert.SerializeObject(ms.ToArray());
Restore the img:
var myBytes = JsonConvert.DeserializeObject<byte[]>(serialized);
var img = Bitmap.FromStream(new MemoryStream(myBytes));
I have a bitmap image, which I converted to a JSON file using:
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Bitmap image);
Content of .json file:
{
"Tag":null,
"PhysicalDimension":{
"IsEmpty":false,
"Width":376,
"Height":221
},
"Size":{
"IsEmpty":false,
"Width":376,
"Height":221
},
"Width":376,
"Height":221,
"HorizontalResolution":96,
"VerticalResolution":96,
"Flags":2,
"RawFormat":{
"Guid":"b96b3caa-0728-11d3-9d7b-0000f81ef32e"
},
"PixelFormat":2498570,
"Palette":{
"Flags":62,
"Entries":[
]
},
"FrameDimensionsList":[
"7462dc86-6180-4c7e-8e3f-ee7333a7a483"
],
"PropertyIdList":[
],
"PropertyItems":[
]
}
Now I tried to deserialize the file in this way:
Bitmap bm = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Bitmap>(json);
But got the error:
System.MissingMethodException: "For the" System.Bitmap "type, the
constructor without parameters is not defined."
Is there another way to deserialize the file or how can I fix this code?
Thanks!
The error of the message is... quite clear on this. If you look at the MSDN documentation for Bitmap, you'll find that it has no empty constructors defined. The JSON deserializer basically creates an new instance of a specified type (using the empty constructor) then fills out the properties. The Bitmap is a bit too complex for that to work. So... you need to work around that.
Bernard Vander Beken already showed you how to read a base64 string containin bitmap data. Here's how you can CREATE it from an existing bitmap:
ImageConverter converter = new ImageConverter();
var bitmapData = Convert.ToBase64String((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
Note that bitmapData, in the example above, is a string which can easily be sent, stored, etc. (so no need to serialize this into JSON).
EDIT:
Please note that given the above, you need to update BOTH your serialization and deserialization code. I.e. to use the deserialization samples provided, you need to send / store a completely different JSON from the one you're currently working with... which won't be a JSON any more.
In fact, your current JSON file doesn't really contain an actual image; it only has some metadata about the image you originally used. So you definitely need to change the code responsible for serialization.
I would also modify the code for deserializing a bitmap ever so slightly (MemoryStream should, in theory, be disposed of properly and setting the position isn't required).
var bytes = Convert.FromBase64String(bitmapData);
Bitmap bitmap;
using (var ms = new MemoryStream(bytes))
bitmap = new Bitmap(Bitmap.FromStream(ms));
Since Bitmap has no default constructor, it cannot be used out of the box for deserialization.
You can try to deserialize the JSON payload to a byte array, then pass it to Bitmap.FromStream via a MemoryStream.
string image = json;
byte[] byteBuffer = Convert.FromBase64String(image);
MemoryStream memoryStream = new MemoryStream(byteBuffer);
memoryStream.Position = 0;
return (Bitmap)Bitmap.FromStream(memoryStream);
Credits to http://ingsharksoft.blogspot.be/2013/07/solution-problem-serializedeserialize.html
I need to convert the selected .svg file to System.Drawing.Image object, so I can resize it and save it as .png. Can anyone help me with this?
Here is what I have so far:
Svg.SvgDocument svgDocument = SVGParser.GetSvgDocument(mPath);
image = svgDocument.Draw();
But it gives me out of memory error.
You can use the SVG Rendering Engine Lib:
Install-Package Svg
It's quite easy to draw images using it:
var svgDoc = SvgDocument.Open(imagePath);
using(var Image = new Bitmap(svgDoc.Draw()))
{
Image.Save(context.Response.OutputStream, ImageFormat.Png);
context.Response.ContentType = "image/png";
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetExpires(DateTime.Now.AddMonths(1));
}
In this example i'm using a handler to display the image on the browser but you can easily save it on some folder just by changing the first parameter of the Save method.
The resource Miljan Vulovic used is svg (https://archive.codeplex.com/?p=svg).
Link is only valid until July 2021, it might be available on GitHub by then, but I'm not sure.
Anyways his solution works for me.
So,
SVGParser.MaximumSize = new System.Drawing.Size(4000, 4000);
svgDocument = SVGParser.GetSvgDocument(mPath);
var bitmap = svgDocument.Draw();
image = bitmap;
i have images on a webserver and I convert they in Base64 to receive it on a .Net application. I use this code:
$imagedata = file_get_contents($local_uri);
$d = base64_encode($imagedata);
It works perfekt.
Now i had the idea to resize the images to save time for transmission.
So I resize the images with a simple PHP-Framework from http://deruwe.de/vorschaubilder-einfach-mit-php-realisieren-teil-2.html
On behind it use ImageJPEG to "return" or create the edited image.
On an other post here i read that if you want to use ImageJPEG and translate it on Base64 you have to use this code:
ob_start();
$thumbnail->output(false, false);
$p = ob_get_contents();
ob_end_clean();
$d = base64_encode($p);
The "new" Base64 code seems legit, because if I try to illustrate it with http://www.freeformatter.com/base64-encoder.html, I got a legit image.
BUT due an unknown reason my .Net application will throw an System.NotSupportedException (No imaging component suitable to complete this operation was found.) and don't like the "new" one.
This is my .Net function to convert Base64 String in BitmapImage:
public static BitmapImage getImage(String s)
{
byte[] binaryData = Convert.FromBase64String(s);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = new MemoryStream(binaryData);
bi.EndInit();
return bi;
}
Any idea whats gone wrong or how to fix it?
Im loading an image from a SQL CE db and then trying to load that into a PictureBox.
I am saving the image like this:
if (ofd.ShowDialog() == DialogResult.OK)
{
picArtwork.ImageLocation = ofd.FileName;
using (System.IO.FileStream fs = new System.IO.FileStream(ofd.FileName, System.IO.FileMode.Open))
{
byte[] imageAsBytes = new byte[fs.Length];
fs.Read(imageAsBytes, 0, imageAsBytes.Length);
thisItem.Artwork = imageAsBytes;
fs.Close();
}
}
and then saving to the Db using LINQ To SQL.
I load the image back like so:
using (FileStream fs = new FileStream(#"C:\Temp\img.jpg", FileMode.CreateNew ,FileAccess.Write ))
{
byte[] img = (byte[])encoding.GetBytes(ThisFilm.Artwork.ToString());
fs.Write(img, 0, img.Length);
}
but am getting an OutOfMemoryException. I have read that this is a slight red herring and that there is probably something wrong with the filetype, but i cant figure what.
Any ideas?
Thanks
picArtwork.Image = System.Drawing.Bitmap.FromFile(#"C:\Temp\img.jpg");
Based on the code you provided it seems like you are treating the image as a string, it might be that data is being lost with the conversion from byte[] to string and string to byte[].
I am not familiar with SQL CE, but if you can you should consider treating the data as a byte[] and not encoding to and from string.
I base my assumption in this line of code
byte[] img = (byte[])encoding.GetBytes(ThisFilm.Artwork.ToString());
The GDI has the bad behavior of throwing an OOM exception whenever it is not capable of understanding a certain image format. Use Irfanview to see what kind of image that really is, it is likely GDI can't handle it.
My advice would be to not use a FileStream to load images unless you need access to the raw bytes. Instead, use the static methods provided in Bitmap or Image objects:
Image img = Image.FromFile(#"c:\temp\img.jpg")
Bitmap bmp = Bitmap.FromFile(#"c:\temp\img.jpg")
To save the file use .Save method of the Image or Bitmap object:
img.Save(#"c:\temp\img.jpg")
bmp.Save(#"c:\temp\img.jpg")
Of course we don't know what type ArtWork is. Would you care to share that information with us?