Im writing my own cache for for our Silverlight application to get around any size problems.
The cache works fine, however, it doesnt work for images.
Ive narrowed down the problem to a little test application that converts a BitmapImage to bytes (to simulate reading it our from the cache) and then convert those bytes back into an image.
Here is the code:
public MainPage()
{
InitializeComponent();
firstImage.ImageOpened += first_Loaded;
}
void first_Loaded(object sender, RoutedEventArgs e)
{
var bmp = firstImage.Source;
var bytes = ToByteArray(bmp as BitmapImage);
otherImage.Source = CreateImageFromBytes(bytes);
}
private byte[] ToByteArray(BitmapImage bi)
{
var enc = new BitmapEncoder(bi);
return enc.GetBitmapData();
}
private BitmapImage CreateImageFromBytes(byte[] data)
{
var bitmapImage = new BitmapImage();
bitmapImage.ImageFailed += bitmapImage_ImageFailed;
var ms = new MemoryStream(data);
bitmapImage.SetSource(ms);
return bitmapImage;
}
void bitmapImage_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
Console.WriteLine(e.ErrorException.Message);
}
The ImageFailed event is always raised with the message "AG_E_NETWORK_ERROR"
Ive read a little about the problem and it seems to have to do with the origin of the image being different but surely I should be able to load an image from bytes in memory right?
Any ideas how to get around this?
I should add that the converting to bytes works fine since if I save those bytes down to disk I can open the image.
From the Remarks in the Silverlight BitmapImage page on MSDN:
The BitmapImage can be used to reference images in the JPEG and PNG
file formats.
Unfortunately the BitmapEncoder class that you are using seems to encode bitmaps in BMP format. Hence the encoded buffer can't be decoded by BitmapImage.
You would have to find another implementation of a BitmapEncoder, which is capable of encoding JPEG or PNG.
Related
Hello we are using InkCanvas control on the wpf page. And we are saving Base64String string in the database. See code
private void submitButtonsCommand_Event(object sender)
{
byte[] sigByte;
InkCanvas icSignature = sender as InkCanvas;
using (var memoryStream = new MemoryStream())
{
icSignature.Strokes.Save(memoryStream);
sigByte = memoryStream.ToArray();
}
ServiceCallReportSignatureModel.SigCustomerSignature = Convert.ToBase64String(sigByte);
UpdateRecord();
}
And when we are retrieving data from the database and converting into the FromBase64String and after that when we creating image then we are getting the error.
public Image LoadImage(base64string)
{
//data:image/gif;base64,
//this image is a single pixel (black)
byte[] bytes = Convert.FromBase64String(base64string);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
}
I don't know why this is occurring. Please help me find out the error.
Our base64 string is : "AIwBAwxIEEWfARsCAAb/RjURAACAPx8JEQAAAAAAAPA/Cmwsh/EgR4kP+Etw/ojDWG7NZ8OZQxBN5otEzmU1mk04I7DnATcLHomzzUbxw/h3Dtp16yhlTQ2UsoTQh+uE64XgjsN6Js2UZpAZmFpmaZTKzzKZ4ctFmw3Mlmm0Bw9h/DtpTPKu79CYgm+VJqA="
Actually we are taking signature from the ink canvas control and we want to display in the pdf when we need. So we want create image from the base 64 data but we are getting the error.
The StrokeCollection.Save(Stream) method does not save a bitmap. Instead,
The Save method saves the StrokeCollection as Ink Serialized Format (ISF).
You can restore the saved StrokeCollection by passing a Stream with the saved data to the StrokeCollection(Stream) constructor.
I'm working with Microsoft's OCR library and am having problems converting the BitmapImage to a pixel array.
I'm making this application for Windows Phone 8, and WriteableBitmap.PixelBuffer.ToArray() isn't an option so I have a static function that'll change a normal BitmapImage into a byte array to feed into the OCR engine.
Well, every time I feed it in the application crashes. What's wrong here?
Here is my static class with the bitmap converter
public static class ByteArrayChange
{
public static byte[] ConvertToBytes(this BitmapImage bitmapImage)
{
byte[] data = null;
using (MemoryStream stream = new MemoryStream())
{
WriteableBitmap wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
data = stream.GetBuffer();
}
return data;
}
}
Here is the piece of code in the OCR method that's causing the application to crash.
byte[] pa = ByteArrayChange.ConvertToBytes(bitmap);
//Here Is he problem
var ocrResult = await ocrEngine.RecognizeAsync((uint)bitmap.PixelHeight, (uint)bitmap.PixelWidth, pa);
What am I doing wrong here?
Thanks!
You're saving your image as JPEG, but I'm fairly certain that OCR library accept RGB/BGRA as an input.
So why don't you use Pixels property? It represents image as BGRA array, so the only thing you need is to convert it to byte[] array.
I'm developing a control where user can set an image and i want this this to be as user friendly as possible - so support for copy & paste, drag & drop.
I've got this part working using IDataObjects, testing for fileformats of FileDrop, FileContents (eg from outlook), and bitmap eg:
private void GetImageFromIDataObject(IDataObject myIDO)
{
string[] dataformats = myIDO.GetFormats();
Boolean GotImage = false;
foreach (string df in dataformats)
{
if (df == DataFormats.FileDrop)
{
// code here
}
if (df == DataFormats.Bitmap)
{
// Source of my problem here... this gets & displays image but
// how do I then convert from here ?
ImageSource myIS = Utilities.MyImaging.ImageFromClipboardDib();
ImgPerson.Source = myIS;
}
}
}
The ImageFromClipboard code is Thomas Levesque's as referenced in the answer to this SO question wpf InteropBitmap to bitmap
http://www.thomaslevesque.com/2009/02/05/wpf-paste-an-image-from-the-clipboard/
No matter how I get the image onto ImgPerson, this part is working fine; image displays nicely.
When user presses save I need to convert the image to a bytearray and send to a WCF server which will save to server - as in, reconstruct the bytearray into an image and save it in a folder.
For all formats of drag & drop, copy & paste the image is some form of System.Windows.Media.Imaging.BitmapImage.
Except for those involving the clipboard which using Thomas's code becomes System.Windows.Media.Imaging.BitmapFrameDecode.
If I avoid Thomas's code and use:
BitmapSource myBS = Clipboard.GetImage();
ImgPerson.Source = myBS;
I get a System.Windows.Interop.InteropBitmap.
I can't figure out how to work with these; to get them into a bytearray so I can pass to WCF for reconstruction and saving to folder.
Try this piece of code
public byte[] ImageToBytes(BitmapImage imgSource)
{
MemoryStream objMS = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imgSource));
encoder.Save(objMS);
return objMS.GetBuffer();
}
You can also use JpegBitmapEncoder, BmpBitmapEncoder based on your requirements.
byte[] arr = ImageToBytes(ImgPerson.Source as BitmapImage);
I can't believe I didn't see this SO question but the this is essentially the same as my question:
WPF: System.Windows.Interop.InteropBitmap to System.Drawing.Bitmap
The answer being:
BitmapSource bmpSource = msg.ThumbnailSource as BitmapSource;
MemoryStream ms = new MemoryStream();
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmpSource));
encoder.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(ms);
So similar in execution to Nitesh's answer but crucially, works with an inter-op bitmap.
I'm trying to display an image on a Windows 8 app. The image data is gathered from a web service, and provided as a Base64 encoded string.
I found the following on Stack Overflow:
How do i read a base64 image in WPF?
However, when I come to use the BitmapImage Class, I can't seem to access System.Windows.Media.Imaging, even though the following Microsoft documentation leads us to believe that it is available for use in .NET 4.5, and with Windows 8 apps:
http://msdn.microsoft.com/en-us/library/ms619218.aspx
Many thanks for your help.
The classes you want are in the Windows.UI.Xaml.Media.Imaging namespace. Here is an example of taking a Base64 image and creating an image out of it ...
var img = #"/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQ ... "; // Full Base64 image as string here
var imgBytes = Convert.FromBase64String(img);
var ms = new InMemoryRandomAccessStream();
var dw = new Windows.Storage.Streams.DataWriter(ms);
dw.WriteBytes(imgBytes);
await dw.StoreAsync();
ms.Seek(0);
var bm = new BitmapImage();
bm.SetSource(ms);
// img1 is an Image Control in XAML
bm.ImageOpened += (s, e) => { this.img1.Source = bm; };
bm.ImageFailed += (s, e) => { Debug.WriteLine(e.ErrorMessage); };
I could not copy a full Base64 image into the answer.
I have a data class in my application which maintains a collection of byte arrays representing JPEG images. It's defined as:
private ArrayList FrameList = new ArrayList();
I'm having some troubles with my Image object rendering a blank page (and taking its sweet time to do it as well). When I insert a blank image with a 2K in-memory byte array (byte x[] = { lots of hex values };):
FrameList.Insert(currFrame, x);
and then import a JPEG file over it later on with:
byte[] bytes = File.ReadAllBytes(fspec);
FrameList[currFrame] = bytes;
the array is read correctly into memory and stored in the ArrayList (confirmed with the debugger).
However,I then have a function to get the image:
public BitmapImage getCurrPicture()
{
MemoryStream strm;
BitmapImage bmp = new BitmapImage();
strm = new MemoryStream((byte[])FrameList[currFrame-1]);
bmp.CacheOption = BitmapCacheOption.None;
bmp.BeginInit();
bmp.StreamSource = strm;
bmp.EndInit();
strm.Close();
return bmp;
}
which is called:
imgPicB.Source = data.getCurrPicture();
and it doesn't always render.
imgPicB is defined in my XAML as:
<Image x:Name="imgPicB"
Width="400"
Height="300"
Stretch="Fill"
VerticalAlignment="Top" />
Funny thing is, if I use the exact same JPEG setting the source with setting the source to the file URI directly, it renders fine.
Is there some problem with using in-memory JPEG images in WPF? Is there some extra smarts performed when loading from a file (say auto-detection of the image type)?
Try this:
public BitmapSource GetCurrPicture()
{
var bitmapImage = new BitmapImage();
using (Stream stream = new MemoryStream((byte[])FrameList[currFrame-1]))
{
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
This works by having WPF decode the image immediately with OnLoad, and then release the reference to the stream when it is done. This means the stream can be garbage collected when it leaves the function. Otherwise, BitmapImage could hold onto the stream until it is rendered.
In the code posted in the question, the render would fail because:
the decode is delayed; and
the stream has been closed at the point where the decode tries to happen.
Link
DwayneNeed 20 Jun 2008 5:11 PM Comments
Caching BitmapImage will store the decoded bitmap in system memory. You can control when this happens by setting the CacheOption property. BitmapImage also maintains a cache of previous BitmapImage instances (via weak references) so that loading the same Uri multiple times will share the same instance. To avoid this cache, you can include the BitmapCreateOptions.IgnoreImageCache flag in the CreateOptions property.