I need to convert an picture (that is stored in an object of type Image) to a string for storage (and later for conversion back into an Image object for display) in a metro app
I have found lots of answers for converting an image to a base64 string in .NET 4.0 etc but in 4.5 the System.Windows.Bitmap namespace isn't there (the Image class is in Windows.UI.Xaml.Media.Imaging) and the method that was in that namespace that made it possible in 4.0 "Save()" doesn't seem to be in 4.5...unless I just can't find it.
Theres an example of doing this here but like I said it doesn't work in a metro app/.NET 4.5
any ideas?
more details:
the method that will do this will convert an instance field that contains an image object (ive used its source property, is this correct?) and needs to store the resultant string from the conversion in an instance string field. this whole object can then be serialized, ignoring the Image field, with the hope of deserializing later and restoring the string to the Image field for display. so far ive tried to use a DataContractSerializer to serialize string from the image, but it doesn't seem to like it. Once I get a string from the image I would be able to serialize that, but its not something I've ever done before.
Also, it seems that the only .net 4.5 documentation that is definitely correct is the pages here: http://msdn.microsoft.com/library/windows/apps/
pages at the "normal looking" msdn site for .net 4.5 don't seem to always work in metro apps? (just a theory?)
[solved]
I finally got it! for anyone else that ever has to do this the answer is here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/38c6cb85-7454-424f-ae94-32782c036567/
I did this
var reader = new DataReader(myMemoryStream.GetInputStreamAt(0));
var bytes = new byte[myMemoryStream.Size];
await reader.LoadAsync((uint)myMemoryStream.Size);
reader.ReadBytes(bytes);
after this sequence, the byte array bytes will have the data from the stream in it, from there I set a string to the value of
Convert.ToBase64String(bytes);
I finally got it! for anyone else that ever has to do this the answer is here: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/38c6cb85-7454-424f-ae94-32782c036567/
I did this
var reader = new DataReader(myMemoryStream.GetInputStreamAt(0));
var bytes = new byte[myMemoryStream.Size];
await reader.LoadAsync((uint)myMemoryStream.Size);
reader.ReadBytes(bytes);
after this sequence, the byte array bytes will have the data from the stream in it, from there I set a string to the value of
Convert.ToBase64String(bytes);
I'm not sure of this because I do not have the .net 4.5 installed here, but I think this could work:
You could use the BitmapSource.CopyPixels() method to extract the pixels of the image:
http://msdn.microsoft.com/en-us/library/ms616043(v=vs.110).aspx
Then use Convert.ToBase64String() to do the convertion.
Also, here are some useful imaging HOW-TOs:
http://msdn.microsoft.com/en-us/library/ms750864(v=vs.110)
Try BitmapEncoder. Example of how to create a BitmapEncoder here. The appropriate namespace is Windows.Graphics.Imaging.
BitmapEncoder gets you an encoder. You can then use GetPixelDataAsync(BitmapPixelFormat, BitmapAlphaMode, BitmapTransform, ExifOrientationMode, ColorManagementMode) to get your pixel data. Following that you can use any generic C# base64 encoder.
(Examples are Javascript but should work for C# as well since the classes exist in C#)
You should store the encoded format of image (say JPEG) format, decoded back to byte[], create a MemoryStream, then Metro BitmapImage can be created from the stream.
Related
I am writing a web API to return an object with a byte array property, something like this in the controller:
...
car.name=Cruze;
car.Image=[123,145,10,...] // image data as byte[]
return Ok(car);
On the UI, I can see the returned car object, but the car.Image property is converted to Base64String.
I am not sure why this happens. How can I make sure the car.Image is sent as byte[] to client?
Thanks for any help!
Web API communication happens over HTTP. HTTP does not know anything about byte[]. Because your byte[] is part of C# and HTTP does not know anything about C# either.
So it is correctly serialised as Base64String (this is the best thing to do, really) and your client needs to decode Base64 into byte array for further processing.
All communication between your server and the client must be serialized. So your byte array will be serialized among everything else. The standard serialization used in this case is the Base64String.
Actually if you want to use your image on the website, then the Base64String has just made it easier for you. All you need is to add data:image/jpeg;base64, at the beginning of the string and use it wherever you usually use the image URL. Change jpeg to the type of your image. Examples:
HTML:
<img src="data:image/jpeg;base64,..." />
JavaScript:
img.src = "data:image/jpeg;base64,...";
CSS:
URL("data:image/jpeg;base64,...")
You can also load it to a canvas if you like to edit the image using the HTML5 capabilities.
If you're using a client other than the browser, there is increasing number of libraries to convert between Base64String and images in any programming framework, so just look for one for your framework.
If you want to use the byte array for something else, you can easily decode the Base64String back to a byte array.
Wee bit of background to set the scene : we've told a client he can provide us with images of any type and we'll put them on his reports. I've just had a quick run through of doing this and found that the reports (and other things between me and them) are all designed to only use SVGs.
I thought I'd struck gold when I found online that you can convert an image from a jpg or PNG into an SVG using free tools but alas I've not yet succeeded in getting an SVG stored as bytes in the DB in a format that allows me to use it again after reading it back out.
Here's a quick timeline of what followed leading up to my problem.
I use an online tool to generate an SVG from a PNG (e.g., MobileFish)
I can open and view it in Firefox and it looks ok
I ultimately need the SVG to be stored as bytes in the DB, from where the report will pull it via a webpage that serves it up as SVG. So I write it as bytes into a SQL data script. The code I use to write these bytes is included below.
I visit said webpage and I get an error that there is an "XML parsing error on Line 1 Column 1" and it shows some of my bytes. They begin "3C73"
I revisit the DB and compare the bytes I've just written there with some pre-existing (and working ones). While my new ones begin "3C73", the others begin "0xFFFE".
I think I've probably just pointed out something really fundamental but it hasn't clicked.
Can someone tell me what I've done that means my bytes aren't stored in the correct encoding/format?
When I open my new SVG in Notepad++ I can see the content includes the following which could be relevant :
<image width="900" height="401" xLink:href="data:image/png;base64,
(base 64 encoded data follows for 600+ lines)
Here's the brains of the code that turns my SVG into the bytes to be stored in DB :
var bytes = File.ReadAllBytes(file);
using (var fs = new StreamWriter(file + ".txt"))
{
foreach (var item in bytes)
{
fs.Write(String.Format("{0:X2}",item));
}
}
Any help appreciated.
Cheers
Two things:
SVGs are vector images, not bitmap files. All that online tool is doing is taking a JPEG and creating a SVG file with a JPEG embedded in it. You aren't really getting the benefit of a true SVG image. If you realise and understand that, then no worries.
SVG files are just text. In theory there is no reason you can't just store them as strings in your db. As long as the column is big enough. However normally if you are storing unstructured files in a db, the preferred column type to use is a "Blob".
http://technet.microsoft.com/en-us/library/bb895234.aspx
Converting your SVG file to hex is just making things slower and doubling the size of your files. Also when you convert back, you have to be very careful about the string encoding you are using. Which, in fact, sounds like the problem you are having.
I am suspecting you are doing it incorrectly. SVG is simply and XML based vector image format. I guess your application might be using SVG image element and you need to convert your png image to base64 encoded string .
I have some C# code that converts an image to base64 string. The code is :
MemoryStream ms = new MemoryStream();
Image img = Image.FromFile(filename);
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
string s = Convert.ToBase64String(ms.GetBuffer());
I am trying to implement it with JAVA. my java code is :
BufferedImage img = null;
img = ImageIO.read(new File(filename));
byte[] bytes = ((DataBufferByte)img.getData().getDataBuffer()).getData();
String js = Base64.encodeBase64String(bytes);
this two piece of code should return the same string for the same image file. But they are returning different strings. I am unable to figure out why. Can anyone shed some light on it?
this two piece of code should return the same string for the same image file
No, they really shouldn't.
The C# code is returning the base64 representation of a JPEG-encoded version of the image data - and potentially some 0s at the end, as you're using GetBuffer instead of ToArray. (You want ToArray here.)
The Java code is returning the base64 representation of the raw raster data, according to its SampleModel. I'd expect this to be significantly larger than the string returned by the C# code.
Even if both pieces of code encoded the image with the same format, that doesn't mean they'll come up with the exact same data - it will depend on the encoding.
Importantly, if you just want "the contents of the file in base64" then you don't need to go via an Image at all. For example, in C# you could use:
string base64 = Convert.ToBase64String(File.ReadAllBytes(filename));
The fact that it's an image is irrelevant in that respect - the file is just a collection of bytes, and you can base64-encode that without understanding the meaning of those bytes at all.
I'm trying to produce a system which takes an image in OpenCV, writes it to XML, reads it from XML, and displays it in an Image control in a WPF application.
The problem I'm having is that I'm unclear as to how .NET classes (e.g. BitmapImage) process images from a byte array. I've tried a number of methods and gotten various errors - too numerous to post unless required.
I was wondering if someone could point me in the right direction regarding this? What I want to know is how does the data need to be presented to a .NET object in order to display it in an Image control?
Thanks in advance for your help - it is much appreciated.
EDIT: I expect what I need to do is convert the XML into a byte array and use that, along with a definition of the format, to instantiate a BitmapImage object or equivalent to use as source for the Image control. What I'm not sure of is how to do this.
Use int cvSaveImage(const char* filename, const CvArr* image)
to save the file as an Image.The image format is chosen based on the filename extension
No need to store it in XML if you can directly store it as Image file.
The .NET classes requires an Image.That's it.
Note:
If you want to store red,green,blue values as comma separated strings, it would be very inefficient.Save it in Base64 instead.You can then convert it into bytes and feed it to any .NET image class.Also the .NET ImageConverter Class may be very helpful.
I found that the issue was (presumably) that I wasn't Base64 encoding the XML data before writing it. Thus the solution is to Base64 encode the data before writing to XML, Base64 decoding it on the other side, reading the data as a byte array and using that to instantiate a MemoryStream and then a BitmapImage object.
Thanks for your help everyone.
You can use:
public static BitmapSource Create(
int pixelWidth,
int pixelHeight,
double dpiX,
double dpiY,
PixelFormat pixelFormat,
BitmapPalette palette,
Array pixels,
int stride
)
I'm prototyping a video streaming client for the iphone that gets it's content from a webserver written in C#.
The server outputs an XML document where the jpg data for the image is stored in one of the tags (). It writes it out using WriteBase64.
On the iPhone, I'm using libxml to parse the xml and storing the bytes for the image in an NSString.
The next step is to create an NSData object using the data and then a new UIImage using it's +initWithData method.
However, each time I try to create a new image, the result is a nil object indicating failure. My best guess is that there is something I need to do to convert the NSString back somehow.
Please help!!
Are you properly base64 decoding your the string from your XML? There is not a native way to do this in Objective-C that I am aware of, but there is a good discussion on how to roll your own here: http://www.cocoadev.com/index.pl?BaseSixtyFour
An alternate approach would be to attach the image binary data directly after the XML stream and parse it out yourself - base64 encoding really expands the size of the image you are transferring.