How can I load a bitmapImage from base64String in windows 8?
I tried this but I am not successful. It used to work on windows phone. What is different?
Looks like I have to use the function setsourceasync. When I use that, then I am required to pass the parameter as IRandomMemory which I am unable to do. How to do this?
public static BitmapImage Base64ToImage(string base64String)
{
var bitmapImage = new BitmapImage();
try
{
if (!String.IsNullOrEmpty(base64String))
{
var imageBytes = Convert.FromBase64String(base64String);
using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
bitmapImage.SetSourcec(ms);
return bitmapImage;
}
}
}
catch (Exception e)
{
}
return null;
}
To create an IRandomAccessStream object for the SetSource method, you need to use a DataWriter. Take a look to this code:
public async Task<BitmapImage> GetImage(string value)
{
if (value == null)
return null;
var buffer = System.Convert.FromBase64String(value);
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes(buffer);
await writer.StoreAsync();
}
var image = new BitmapImage();
image.SetSource(ms);
return image;
}
}
Here conversion methods for both System.Drawing.Bitmap and System.Windows.Media.BitmapSource.
Enjoy
Remark: Not tested on Win8 but there is not reason why it should not work.
string ToBase64(Bitmap bitmap)
{
if (bitmap == null)
throw new ArgumentNullException("bitmap");
using (var stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Png);
return Convert.ToBase64String(stream.ToArray());
}
}
string ToBase64(BitmapSource bitmapSource)
{
using (var stream = new MemoryStream())
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(stream);
return Convert.ToBase64String(stream.ToArray());
}
}
Bitmap FromBase64(string value)
{
if (value == null)
throw new ArgumentNullException("value");
using (var stream = new MemoryStream(Convert.FromBase64String(value)))
{
return (Bitmap)Image.FromStream(stream);
}
}
BitmapSource BitmapSourceFromBase64(string value)
{
if (value == null)
throw new ArgumentNullException("value");
using (var stream = new MemoryStream(Convert.FromBase64String(value)))
{
var decoder = new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
BitmapSource result = decoder.Frames[0];
result.Freeze();
return result;
}
}
Related
I want to store a WPF BitmapImage to XML. (I know this is not usually recommended but for my case, it makes sense as I want to embed all my resource to a single XML file besides other data I have).
So Here are my extension methods:
public static string ToBase64(this BitmapImage image, string format)
{
return Convert.ToBase64String(Encode(image, format));
}
public static Stream FromBase64(this string content)
{
var bytes = Convert.FromBase64String(content);
var stream = new MemoryStream();
stream.Write(bytes, 0, bytes.Length);
return stream;
}
private static byte[] Encode(BitmapImage bitmapImage, string format)
{
byte[] data = null;
BitmapEncoder encoder = null;
switch (format.ToUpper())
{
case "PNG": encoder = new PngBitmapEncoder();
break;
case "GIF": encoder = new GifBitmapEncoder();
break;
case "BMP": encoder = new BmpBitmapEncoder();
break;
case "JPG": encoder = new JpegBitmapEncoder();
break;
}
if (encoder != null)
{
encoder.Frames.Add(BitmapFrame.Create(bitmapImage));
using (var ms = new MemoryStream())
{
encoder.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
data = ms.ToArray();
}
}
return data;
}
public static BitmapImage ToBitmapImage(this Stream stream)
{
try
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
return bitmap;
}
catch (Exception ex)
{
}
return null;
}
and here is my XML logics:
public async void LoadImage(Guid imageSourceGuid)
{
var sourceElement = await GetImageSource(imageSourceGuid);
if (sourceElement != null)
{
var data = sourceElement.Element("Value").Value;
Format = sourceElement.Attribute("Format").Value.ToUpper();
if (string.IsNullOrEmpty(data) == false)
{
using (var stream = data.FromBase64())
{
SetImage(stream.ToBitmapImage());
}
}
}
}
private void SetImage(BitmapImage bitmap)
{
this.ImageShape.Source = bitmap;
}
public async Task<XElement> GetImageSource(Guid id)
{
XElement result = null;
await Task.Run(() =>
{
var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment, IgnoreWhitespace = true, IgnoreComments = true, Async = true };
using (var reader = XmlReader.Create(FilePath, settings))
{
while (reader.Read())
{
if (reader.IsStartElement() && reader.Name == "ImageSource")
{
var att = reader.GetAttribute("Id");
if (att != null && Guid.Parse(att) == id)
{
result = XNode.ReadFrom(reader) as XElement;
break;
}
}
}
}
});
return result;
}
My XML file looks like:
<?xml version="1.0" encoding="utf-8"?>
<ImageSources>
<ImageSource Id="1b1e4ebc-484c-4f63-bbed-bf33430f85f2" Format="JPG" OriginalWidth="534" OriginalHeight="338">
<Value><![CDATA[....]]<Value>
</ImageSource>
</ImageSources>
...
But when I try to create a BitmapImage using ToBitmapImage method from the XML data I saved earlier I get "The image cannot be decoded. The image header might be corrupted." exception.
This only happens for JPG files I have no issue with PNG files at all.
You should rewind the MemoryStream after writing in your FromBase64 method:
public static Stream FromBase64(this string content)
{
var bytes = Convert.FromBase64String(content);
var stream = new MemoryStream();
stream.Write(bytes, 0, bytes.Length);
stream.Seek(0, SeekOrigin.Begin); // here
return stream;
}
Or construct it directly from the byte array:
public static Stream FromBase64(this string content)
{
return new MemoryStream(Convert.FromBase64String(content));
}
Afaik, JpegBitmapDecoder is the only BitmapDecoder in WPF that is affected by the source stream's actual Position.
I'm new to C# and got problem with QR code decoding using ZXing.Net. The application launches with no errors, but I get nothing in the result string. I think the problem could be in RGBLuminanceSource().
private static byte[] ToByteArray(Image img)
{
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
img.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
stream.Close();
byteArray = stream.ToArray();
}
return byteArray;
}
private void button1_Click(object sender, EventArgs e)
{
*** SOME OTHER CODE HERE ***
Bitmap BitmapImage = new Bitmap(#"D:\1.png");
QRCodeReader reader = new QRCodeReader();
LuminanceSource source = new RGBLuminanceSource(ToByteArray(BitmapImage), BitmapImage.Width, BitmapImage.Height);
var binarizer = new HybridBinarizer(source);
var binBitmap = new BinaryBitmap(binarizer);
string result = reader.decode(binBitmap).Text;
*** SOME OTHER CODE HERE ***
}
Just call function. Also, replace ... with your handling
public Result decode(Uri uri)
{
Bitmap image;
try
{
image = (Bitmap) Bitmap.FromFile(uri.LocalPath);
}
catch (Exception)
{
throw new FileNotFoundException("Resource not found: " + uri);
}
using (image)
{
LuminanceSource source;
source = new BitmapLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result = new MultiFormatReader().decode(bitmap);
if (result != null)
{
... code found
}
else
{
... no code found
}
return result;
}
}
for (int i = 3; i < 10; i++)
{
Uri uriimg = new Uri("http://i.msdn.microsoft.com/dynimg/IC53593" + i + ".jpg", UriKind.RelativeOrAbsolute);
SaveToLocalStorage(ImageToArray(uriimg), "anh1.jpg");
}
private byte[] ImagesToArray(Uri uriimg)
{
var image = new BitmapImage(uriimg);
MemoryStream ms = new MemoryStream();
image.ImageOpened += (s, e) =>
{
image.CreateOptions = BitmapCreateOptions.None;
WriteableBitmap wb = new WriteableBitmap(image);
wb.SaveJpeg(ms, image.PixelWidth, image.PixelHeight, 0, 100);
};
return ms.ToArray();
}
public async void SaveToLocalStorage(byte[] _imageBytes, string fileName)
{
if (_imageBytes == null)
{
return;
}
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
if (!isoFile.DirectoryExists("dataImages"))
{
isoFile.CreateDirectory("dataImages");
}
string filePath = System.IO.Path.Combine("dataImages", fileName);
using (var stream = isoFile.CreateFile(filePath))
{
await stream.WriteAsync(_imageBytes, 0, _imageBytes.Length);
}
}
public ImageSource LoadFromLocalStorage(string fileName)
{
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
ImageSource imageSource = null;
if (isoFile.DirectoryExists("dataImages"))
{
string filePath = System.IO.Path.Combine("dataImages", fileName);
using (var imageStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
imageSource = PictureDecoder.DecodeJpeg(imageStream);
}
}
return imageSource;
}
I get the value as byte [0] it can not convert to byte [].
The problem I see is in ImagesToArray. You create a new MemoryStream, subscribe to an event that sets it, and then immediately return it. I'm pretty sure that ms will have 0 bytes when it is returned.
You should instead not use image.ImageOpened, and just put that code in the ImagesToArray method directly:
private byte[] ImagesToArray(Uri uriimg)
{
var image = new BitmapImage(uriimg);
MemoryStream ms = new MemoryStream();
image.CreateOptions = BitmapCreateOptions.None;
WriteableBitmap wb = new WriteableBitmap(image);
wb.SaveJpeg(ms, image.PixelWidth, image.PixelHeight, 0, 100);
return ms.ToArray();
}
I have saved Image in database as binary :
Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
if (fd.ShowDialog() == true)
{
ILogo.Source = new BitmapImage(new Uri(fd.FileName));
Stream stream = File.OpenRead(fd.FileName);
binaryImage = new byte[stream.Length];
stream.Read(binaryImage, 0, (int)stream.Length);
}
_merchantInfo.Logo = binaryImage;
I want to read the image and showing it image tool, I tried this:
_merchantInfo = new MerchantInfo();
_merchantInfo = _context.MerchantInfo.FirstOrDefault();
byte[] binaryPhoto = (byte[])_merchantInfo.Logo;
Stream stream = new MemoryStream(binaryPhoto);
_merchantLogo = new BitmapImage();
_merchantLogo.StreamSource = stream;
ILogo.Source = _merchantLogo;
No Error, But the image does not showing in image box :(
Is there error in my code?
Thanks.
Universal Binary Storage Method -> You must read all the bites of the picture/file and save them in a binary array.
OpenFileDialog FileDialog = new OpenFileDialog();
byte[] BinaryData = new byte[]{};
if(FileDialog.ShowDialog())
{
BinaryData = System.IO.File.ReadAllBytes(FileDialog.FileName);
}
Binary Retrieval(For Images Only in WPF) -> You must set an BitmapImage and store all the binary information within it with the help of a MemoryStream.
BitmapImage image = new BitmapImage();
byte[] binary = new byte{}; /* <--- The array where
we stored the binary
information of the picture*/
image.BeginInit();
image.StreamSource = new System.IO.MemoryStream(binary)
image.EndInit();
Universal Binary Retrieval and Binary File Upload Method ->
byte[] BinaryData = new byte[]{};
private void Download()
{
OpenFileDialog FileDialog = new OpenFileDialog();
if(FileDialog.ShowDialog())
{
BinaryData = System.IO.File.ReadAllBytes(FileDialog.FileName);
}
}
private void Save()
{
OpenFileDialog FileDialog = new SaveFileDialog();
if(FileDialog.ShowDialog())
{
using(System.IO.Stream stream = new File.Open(FileDialog.FileName, FileMode.Create))
{
using (var BinaryWriter = new BinaryWriter(stream))
{
BinaryWriter.Write(BinaryData);
BinaryWriter.Close();
}
}
}
}
Finally I have solved this, here is the code for store and retrieve the image in database as binary :
To store the image:
Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
if (fd.ShowDialog() == true)
{
ILogo.Source = new BitmapImage(new Uri(fd.FileName));
Stream stream = File.OpenRead(fd.FileName);
binaryImage = new byte[stream.Length];
stream.Read(binaryImage, 0, (int)stream.Length);
}
_merchantInfo.Logo = binaryImage;
_context.SaveChanges();
Image retrieval and display:
merchantInfo = new MerchantInfo();
_merchantInfo = _context.MerchantInfo.FirstOrDefault();
byte[] binaryPhoto = (byte[])_merchantInfo.Logo;
Stream stream = new MemoryStream(binaryPhoto);
_merchantLogo = new BitmapImage();
_merchantLogo.BeginInit();
_merchantLogo.StreamSource = stream;
_merchantLogo.EndInit();
ILogo.Source = _merchantLogo;
Thanks for everyone helped me :)
i create this class and i am using it without any problems, try it and share it.
/// <summary>
/// created by Henka Programmer.
/// Class to make the converting images formats and data structs so easy.
/// This Class supporte the following types:
/// - BtimapImage,
/// - Stream,
/// - ByteImage
///
/// and the other option is image resizing.
/// </summary>
public class Photo
{
public BitmapImage BitmapImage;
public System.IO.Stream Stream;
public byte[] ByteImage;
public Photo(Uri PhotoUri)
{
this.BitmapImage = new BitmapImage(PhotoUri);
this.Stream = new MemoryStream();
this.Stream = this.BitmapImage.StreamSource;
this.ByteImage = StreamToByteArray(this.Stream);
}
public Photo(Bitmap Photo_Bitmap)
: this((ImageSource)(new ImageSourceConverter().ConvertFrom(Photo_Bitmap)))
{
/*
ImageSourceConverter c = new ImageSourceConverter();
byte[] bytes = (byte[])TypeDescriptor.GetConverter(Photo_Bitmap).ConvertTo(Photo_Bitmap, typeof(byte[]));
Photo ph = new Photo(bytes);*/
}
public Photo(ImageSource PhotoSource) : this(PhotoSource as BitmapImage) { }
public Photo(BitmapImage BitmapPhoto)
{
this.BitmapImage = BitmapPhoto;
this.ByteImage = GetByteArrayFromImageControl(BitmapPhoto);
this.Stream = new MemoryStream();
WriteToStream(this.Stream, this.ByteImage);
}
public Photo(string path)
{
try
{
this.Stream = System.IO.File.Open(path, System.IO.FileMode.Open);
this.BitmapImage = new BitmapImage();
BitmapImage.BeginInit();
BitmapImage.StreamSource = Stream;
BitmapImage.EndInit();
this.ByteImage = StreamToByteArray(this.Stream);
}
catch (Exception exception)
{
Debug.WriteLine(exception.Message);
}
}
public Photo(byte[] byteimage)
{
this.ByteImage = new byte[byteimage.Length];
this.ByteImage = byteimage;
// WriteToStream(this.Stream, this.ByteImage);
//MemoryStream ms = new MemoryStream(byteimage);
this.Stream = new MemoryStream(byteimage);
}
private void WriteToStream(Stream s, Byte[] bytes)
{
using (var writer = new BinaryWriter(s))
{
writer.Write(bytes);
}
}
private byte[] StreamToByteArray(Stream inputStream)
{
if (!inputStream.CanRead)
{
throw new ArgumentException();
}
// This is optional
if (inputStream.CanSeek)
{
inputStream.Seek(0, SeekOrigin.Begin);
}
byte[] output = new byte[inputStream.Length];
int bytesRead = inputStream.Read(output, 0, output.Length);
Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length");
return output;
}
private BitmapImage BitmapImageFromBytes(byte[] bytes)
{
BitmapImage image = new BitmapImage();
using (System.IO.MemoryStream imageStream = new System.IO.MemoryStream())
{
imageStream.Write(ByteImage, 0, ByteImage.Length);
imageStream.Seek(0, System.IO.SeekOrigin.Begin);
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = imageStream;
image.EndInit();
//image.Freeze();
}
return image;
}
public BitmapImage GetResizedBitmap(int width, int height)
{
ImageSource imgSrc = CreateResizedImage(this.ByteImage, width, height);
return new Photo(GetEncodedImageData(imgSrc, ".jpg")).BitmapImage;
}
private ImageSource CreateResizedImage(byte[] imageData, int width, int height)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
if (width > 0)
{
bmpImage.DecodePixelWidth = width;
}
if (height > 0)
{
bmpImage.DecodePixelHeight = height;
}
bmpImage.StreamSource = new MemoryStream(imageData);
bmpImage.CreateOptions = BitmapCreateOptions.None;
bmpImage.CacheOption = BitmapCacheOption.OnLoad;
bmpImage.EndInit();
Rect rect = new Rect(0, 0, width, height);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
drawingContext.DrawImage(bmpImage, rect);
}
RenderTargetBitmap resizedImage = new RenderTargetBitmap(
(int)rect.Width, (int)rect.Height, // Resized dimensions
96, 96, // Default DPI values
PixelFormats.Default); // Default pixel format
resizedImage.Render(drawingVisual);
return resizedImage;
}
internal byte[] GetEncodedImageData(ImageSource image, string preferredFormat)
{
byte[] returnData = null;
BitmapEncoder encoder = null;
switch (preferredFormat.ToLower())
{
case ".jpg":
case ".jpeg":
encoder = new JpegBitmapEncoder();
break;
case ".bmp":
encoder = new BmpBitmapEncoder();
break;
case ".png":
encoder = new PngBitmapEncoder();
break;
case ".tif":
case ".tiff":
encoder = new TiffBitmapEncoder();
break;
case ".gif":
encoder = new GifBitmapEncoder();
break;
case ".wmp":
encoder = new WmpBitmapEncoder();
break;
}
if (image is BitmapSource)
{
MemoryStream stream = new MemoryStream();
encoder.Frames.Add(BitmapFrame.Create(image as BitmapSource));
encoder.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
returnData = new byte[stream.Length];
BinaryReader br = new BinaryReader(stream);
br.Read(returnData, 0, (int)stream.Length);
br.Close();
stream.Close();
}
return returnData;
}
public byte[] GetByteArrayFromImageControl(BitmapImage imageC)
{
MemoryStream memStream = new MemoryStream();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imageC));
encoder.Save(memStream);
return memStream.GetBuffer();
}
public ImageSource ToImageSource()
{
ImageSource imgSrc = this.BitmapImage as ImageSource;
return imgSrc;
}
public System.Windows.Controls.Image ToImage()
{
System.Windows.Controls.Image Img = new System.Windows.Controls.Image();
Img.Source = this.ToImageSource();
return Img;
}
}
I'm trying to Convert a Bitmap (SystemIcons.Question) to a BitmapImage so I can use it in a WPF Image control.
I have the following method to convert it to a BitmapSource, but it returns an InteropBitmapImage, now the problem is how to convert it to a BitmapImage. A direct cast does not seem to work.
Does anybody know how to do it?
CODE:
public BitmapSource ConvertToBitmapSource()
{
int width = SystemIcons.Question.Width;
int height = SystemIcons.Question.Height;
object a = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(SystemIcons.Question.ToBitmap().GetHbitmap(), IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromWidthAndHeight(width, height));
return (BitmapSource)a;
}
property to return BitmapImage: (Bound to my Image Control)
public BitmapImage QuestionIcon
{
get
{
return (BitmapImage)ConvertToBitmapSource();
}
}
InteropBitmapImage inherits from ImageSource, so you can use it directly in an Image control. You don't need it to be a BitmapImage.
You should be able to use:
public BitmapImage QuestionIcon
{
get
{
using (MemoryStream ms = new MemoryStream())
{
System.Drawing.Bitmap dImg = SystemIcons.ToBitmap();
dImg.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Position = 0;
System.Windows.Media.Imaging.BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage();
bImg.BeginInit();
bImg.StreamSource = new MemoryStream(ms.ToArray());
bImg.EndInit();
return bImg;
}
}
}
public System.Windows.Media.Imaging.BitmapImage QuestionIcon
{
get
{
using (MemoryStream ms = new MemoryStream())
{
System.Drawing.Bitmap dImg = SystemIcons.ToBitmap();
dImg.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Position = 0;
var bImg = new System.Windows.Media.Imaging.BitmapImage();
bImg.BeginInit();
bImg.StreamSource = ms;
bImg.EndInit();
return bImg;
}
}
}