How can I save panel and restore it in c#? [duplicate] - c#

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

Serializing a PictureBox with JSON

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));

Deserialization .json to Bitmap image c#

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

C# .svg file to System.Drawing.Image

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;

How to set image from code behind?

I have the following aspx code
<asp:Image ID="pbScannedImage" runat="server" />
And my code behind c# code is
System.Drawing.Image image;
image = System.Drawing.Image.FromStream(new MemoryStream(dDSImageViewerDTO.ROI));
pbScannedImage.Visible = true;
pbScannedImage.ImageUrl = "";
// This is available but I don't want to write file to the disk and
// assign directly to the image box something like
pbScannedImage.Image = image;
//i know this is not possible so any other work around would be great help
So basically I want to assign the image to the image control without writing it to the anywhere else. Is it possible and if not then are there any workarounds for this available?
You can seperate your database image logic into a Generic Handler (ASHX) and then use the handler as your image's src e.g.
img.src=GetImage.ashx?id=1;
You'd need to create GetImage.ashx and handle your id's (or whatever your using) appropriately. Then you can do a simple write back to the page.
Working off guymid's answer, you can also assign the img.Src from code behind like so...
pbScannedImage.Src = "data:image/png;base64," + ImageToBase64String(Image);
pbScannedImage.Src = "ImageHandler.ashx";
And the handler code must be like:
name
System.Drawing.Image dbImage =
System.Drawing.Image.FromFile("file path");
System.Drawing.Image thumbnailImage =
dbImage.GetThumbnailImage(80, 80, null, new System.IntPtr());
thumbnailImage.Save(mstream, dbImage.RawFormat);
Byte[] thumbnailByteArray = new Byte[mstream.Length];
mstream.Position = 0;
mstream.Read(thumbnailByteArray, 0, Convert.ToInt32(mstream.Length));
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(thumbnailByteArray);
One way to do this, especially if you want to ensure images are never cached (which is common with dynamically loaded images) is to add the image data as CSS background-image data to an element such as a div with:
"background-image:url(data:image/gif;base64," + ImageToBase64String(Image) + ")"
public string ImageToBase64String(Image image)
{
using (MemoryStream stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Png);
return Convert.ToBase64String(stream.ToArray());
}
}
How said #Sain Pradeep, you can create service(ashx or contoller method if you use mvc) for return image stream and use that with html tag <img>(asp:Image is wrapper over<img>).
See samples from Display Image using ashx Handler

Load image from resources area of project in C#

I have an image in my project stored at Resources/myimage.jpg. How can I dynamically load this image into Bitmap object?
Are you using Windows Forms? If you've added the image using the Properties/Resources UI, you get access to the image from generated code, so you can simply do this:
var bmp = new Bitmap(WindowsFormsApplication1.Properties.Resources.myimage);
You can get a reference to the image the following way:
Image myImage = Resources.myImage;
If you want to make a copy of the image, you'll need to do the following:
Bitmap bmp = new Bitmap(Resources.myImage);
Don't forget to dispose of bmp when you're done with it. If you don't know the name of the resource image at compile-time, you can use a resource manager:
ResourceManager rm = Resources.ResourceManager;
Bitmap myImage = (Bitmap)rm.GetObject("myImage");
The benefit of the ResourceManager is that you can use it where Resources.myImage would normally be out of scope, or where you want to dynamically access resources. Additionally, this works for sounds, config files, etc.
You need to load it from resource stream.
Bitmap bmp = new Bitmap(
System.Reflection.Assembly.GetEntryAssembly().
GetManifestResourceStream("MyProject.Resources.myimage.png"));
If you want to know all resource names in your assembly, go with:
string[] all = System.Reflection.Assembly.GetEntryAssembly().
GetManifestResourceNames();
foreach (string one in all) {
MessageBox.Show(one);
}
Way easier than most all of the proposed answers
tslMode.Image = global::ProjectName.Properties.Resources.ImageName;
The best thing is to add them as Image Resources in the Resources settings in the Project. Then you can get the image directly by doing Resources.myimage. This will get the image via a generated C# property.
If you just set the image as Embedded Resource you can get it with:
string name = "Resources.myimage.jpg"
string namespaceName = "MyCompany.MyNamespace";
string resource = namespaceName + "." + name;
Type type = typeof(MyCompany.MyNamespace.MyTypeFromSameAssemblyAsResource);
Bitmap image = new Bitmap(type.Assembly.GetManifestResourceStream(resource));
Where MyTypeFromSameAssemblyAsResource is any type that you have in your assembly.
Code I use in several of my projects...
It assumes that you store images in resource only as bitmaps not icons
public static Bitmap GetImageByName(string imageName)
{
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
string resourceName = asm.GetName().Name + ".Properties.Resources";
var rm = new System.Resources.ResourceManager(resourceName, asm);
return (Bitmap)rm.GetObject(imageName);
}
Use below one. I have tested this with Windows form's Grid view cell.
Object rm = Properties.Resources.ResourceManager.GetObject("Resource_Image");
Bitmap myImage = (Bitmap)rm;
Image image = myImage;
Name of "Resource_Image", you can find from the project.
Under the project's name, you can find Properties. Expand it. There you can see Resources.resx file. Open it. Apply your file name as "Resource_Image".
JDS's answer worked best. C# example loading image:
Include the image as Resource (Project tree->Resources, right click to add the desirable file ImageName.png)
Embedded Resource (Project tree->Resources->ImageName.png, right click select properties)
.png file format (.bmp .jpg should also be OK)
pictureBox1.Image = ProjectName.Properties.Resources.ImageName;
Note the followings:
The resource image file is "ImageName.png", file extension should be omitted.
ProjectName may perhaps be more adequately understood as "Assembly name", which is to be the respective text entry on the Project->Properties page.
The example code line is run successfully using VisualStudio 2015 Community.
I suggest:
System.Reflection.Assembly thisExe;
thisExe = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream file =
thisExe.GetManifestResourceStream("AssemblyName.ImageFile.jpg");
Image yourImage = Image.FromStream(file);
From msdn:
http://msdn.microsoft.com/en-us/library/aa287676(v=vs.71).aspx
Using Image.FromStream is better because you don't need to know the format of the image (bmp, png, ...).
With and ImageBox named "ImagePreview
FormStrings.MyImageNames contains a regular get/set string cast method, which are linked to a scrollbox type list.
The images have the same names as the linked names on the list, except for the .bmp endings.
All bitmaps are dragged into the resources.resx
Object rm = Properties.Resources.ResourceManager.GetObject(FormStrings.MyImageNames);
Bitmap myImage = (Bitmap)rm;
ImagePreview.Image = myImage;
In my case -- I was using Icons in my resource, but I needed to add them dynamically as Images to some ToolStripMenuItem(s). So in the method that I created (which is where the code snippet below comes from), I had to convert the icon resources to bitmaps before I could return them for addition to my MenuItem.
string imageName = myImageNameStr;
imageName = imageName.Replace(" ", "_");
Icon myIcon = (Icon)Resources.ResourceManager.GetObject(imageName);
return myIcon.ToBitmap();
Something else to be aware of, if your image/icon has spaces (" ") in its name when you add them to your resource, VS will automatically replace those spaces with "_"(s). Because, spaces are not a valid character when naming your resource. Which is why I'm using the Replace() method in my referenced code. You can likely just ignore that line.
You can also save the bmp in a var like this:
var bmp = Resources.ImageName;
hope it helps!
Strangely enough, from poking in the designer I find what seems to be a much simpler approach:
The image seems to be available from .Properties.Resources.
I'm simply using an image as all I'm interested in is pasting it into a control with an image on it.
(Net 4.0, VS2010.)
I looked at the designer code from one of my projects and noticed it used this notation
myButton.Image = global::MyProjectName.Properties.Resources.max;
where max is the name of the resource I uploaded into the project.
Or you could use this line when dealing with WPF or Silverlight, especially where you have the source string already in the XAML markup:
(ImageSource)new ImageSourceConverter().ConvertFromString(ImagePath);
Where the ImagePath is something like:
string ImagePath = "/ProjectName;component/Resource/ImageName.png";
This is how I manage to create an ImageList from a Resource (.rc) file of a windows forms application:
ImageList imgList = new ImageList();
var resourceSet = DataBaseIcons.ResourceManager.GetResourceSet(CultureInfo.CreateSpecificCulture("en-EN"), true, true);
foreach (var r in resourceSet)
{
Logger.LogDebug($"Resource Type {((DictionaryEntry)r).Key.ToString()} is of {((DictionaryEntry)r).Value.GetType()}");
if (((DictionaryEntry)r).Value is Bitmap)
{
imgList.Images.Add(((Bitmap)(((DictionaryEntry)r).Value)));
}
else
{
Logger.LogWarning($"Resource Type {((DictionaryEntry)r).Key.ToString()} is of type {((DictionaryEntry)r).Value.GetType()}");
}
}
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStrip1.Location = new System.Drawing.Point(0, 0);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(444, 25);
this.toolStrip1.TabIndex = 0;
this.toolStrip1.Text = "toolStrip1";
object O = global::WindowsFormsApplication1.Properties.Resources.ResourceManager.GetObject("best_robust_ghost");
ToolStripButton btn = new ToolStripButton("m1");
btn.DisplayStyle = ToolStripItemDisplayStyle.Image;
btn.Image = (Image)O;
this.toolStrip1.Items.Add(btn);

Categories