How to save image file to string in wpf? - wpf

I want to read Image file(png, jpg, etc).
and save xml file, load image from xml.
but first. Deserialize throw System.InvalidOperationException.
second. I don't know below method is correct.
Scenario.
1. Open Image file from hdd.
2. Save document(text with image like 'SomeClass' in below source) in my application.
3. When save document, application will serialize SomeClass with image.
4. Rerun application, and load xml file.
5. then, show image in my application.
using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(#"C:\z.jpg")))
{
StreamReader sr = new StreamReader(ms);
someClass.ImageData = sr.ReadToEnd();
Xml.Serialize<SomeClass>(someClass, #"C:\z.xml");
}
SomeClass someClass = Xml.Deserialize<SomeClass>(#"C:\z.xml");
BitmapImage image = new BitmapImage();
image.BegineInit();
image.Source = ??
image.EndInit();
System.Windows.Controls.Image imageControl = new Image();
imageControl.Source = image;
this.Content = imageControl;
this is Serialize, Deserialize static method.
public static class Xml
{
public static void Serialize<T>(T data, string path)
{
XmlSerializer s = new XmlSerializer(typeof(T));
using (FileStream fs = new FileStream(path, FileMode.Create))
{
s.Serialize(fs, data);
}
}
public static T Deserialize<T>(string path)
{
XmlSerializer s = new XmlSerializer(typeof(T));
using (FileStream fs = new FileStream(path, FileMode.Open))
{
fs.Position = 0;
return (T)s.Deserialize(fs);
}
}
}
This is SomeClass
[Serializable]
public class SomeClass
{
public string ImageData { get; set; }
public string TextData { get; set; }
}
thank you.

You need to convert the binary image data to a string. You can use the Convert methods to handle that.
Edit note - Noticed you were reading all bytes into a memory stream and then reading them again from a stream reader. It would simplify the code to just read it directly and convert those bytes to Base64.
Example below.
someClass.ImageData = Convert.ToBase64String(File.ReadAllBytes(#"C:\z.jpg"));
Xml.Serialize<SomeClass>(someClass, #"C:\z.xml");
------------------
SomeClass someClass = Xml.Deserialize<SomeClass>(#"C:\z.xml");
BitmapImage image = new BitmapImage();
image.BegineInit();
image.Source = Convert.FromBase64String(someClass.ImageData);
image.EndInit();

Related

Convert drawing.bitmap to windows.controls.image

I am reading data from a smartcard.
This data contains a picture as well.
Code to get the picture in a class ReadData:
public Bitmap GetPhotoFile()
{
byte[] photoFile = GetFile("photo_file");
Bitmap photo = new Bitmap(new MemoryStream(photoFile));
return photo;
}
Code in the xaml:
imgphoto = ReadData.GetPhotoFile();
Error being generated:
Cannot implicitly convert type 'System.Drawing.Bitmap' to 'System.Windows.Controls.Image'
What is the best approach in this?
Do not create a System.Drawing.Bitmap from that file. Bitmap is WinForms, not WPF.
Instead, create a WPF BitmapImage
public ImageSource GetPhotoFile()
{
var photoFile = GetFile("photo_file");
var photo = new BitmapImage();
using (var stream = new MemoryStream(photoFile))
{
photo.BeginInit();
photo.CacheOption = BitmapCacheOption.OnLoad;
photo.StreamSource = stream;
photo.EndInit();
}
return photo;
}
Then assign the returned ImageSource to the Source property of the Image control:
imgphoto.Source = ReadData.GetPhotoFile();

Diplay Converted reportview Report

I am trying to display a report that is converted to a PDF. I have found a bit of code that will display the PDF but it needs to be stored on disk. Is there a way to store the PDF locally temporally so it can be called by a reader?
Here is the code that currently is for the print button.
namespace Dispatch311.Views
/// <summary>
/// Interaction logic for PrintDialog.xaml
/// </summary>
public partial class PrintDialog : Window
{
public PrintDialog()
{
InitializeComponent();
}
public void DisplayReport(int eventID)
{
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtention;
reportViewer.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Remote;
ServerReport serverReport = reportViewer.ServerReport;
reportViewer.ShowParameterPrompts = false;
serverReport.ReportServerUrl = new Uri("http://sql2008test/reportserver");
serverReport.ReportPath = "/311Reports/311SingleEvent";
ReportParameter ID = new ReportParameter();
ID.Name = "ID";
ID.Values.Add(eventID.ToString());
reportViewer.ServerReport.SetParameters(
new ReportParameter[] { ID });
byte[] bytes = reportViewer.ServerReport.Render(
"PDF", null, out mimeType, out encoding, out filenameExtention,
out streamids, out warnings);
using (FileStream fs = new FileStream("EventPDF.pdf", FileMode.Create))
{
fs.Write(bytes, 0, bytes.Length);
}
reportViewer.RefreshReport();
}
}
Fixed the end of my code so it looks like this:
byte[] bytes = reportViewer.ServerReport.Render("PDF",
null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);
using (FileStream fs = new FileStream("311Event.pdf", FileMode.Create))
{
fs.Write(bytes, 0, bytes.Length);
}
string fileName = "311Event.pdf";
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = fileName;
process.Start();
process.WaitForExit();
This makes it so Adobe reader pops up instead of reportviewer and returns to the application when the user exits the reader.

Silverlight/ImageTools to Convert Webcam Imagesource to Jpeg not working

I have a utility that allows the user to take a camera photo and upload it, in addition to another option to upload a file. I've got most of it working, except for the part where I have to convert the webcam image to a jpg prior to upload. The code below has no error but produces invalid image data:
void CaptureImageCompleted(object sender, CaptureImageCompletedEventArgs e)
{
busyIndicator.IsBusy = true;
stopCapture();
capturedImage.ImageSource = e.Result;
ImageTools.ExtendedImage eimg = e.Result.ToImage();
var encoder = new ImageTools.IO.Jpeg.JpegEncoder();
Stream stream = eimg.ToStreamByExtension("jpg");
//DO THIS LATER
//if (stream.Length > 512000)
//{
// eimg = ExtendedImage.Resize(eimg, 240, new NearestNeighborResizer());
// stream = eimg.ToStreamByExtension("jpg");
//}
encoder.Encode(eimg, stream);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(stream);
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
// picture file a class object to be used by uploader
pictureFile.PictureName = "webcam.jpg"; // name will be changed later
pictureFile.PictureStream = bytes;
HtmlPage.Window.Invoke("gotDetails_WebCam", ""); // post page, then come back and do upload
}
Here is what PictureFile looks like:
[DataContract]
public class PictureFile
{
[DataMember]
public string PictureName { get; set; }
[DataMember]
public byte[] PictureStream { get; set; }
}
Can anyone figure out what I'm doing wrong to produce the bytes needed for a jpeg?
good to see that you solved,
here is my running code,
I use png format,there is also file size check.
Maybe it helps s.one else.
dSrvPR is my Domain Service Class instance
photo is an entity object in my EF.
_captureSource.CaptureImageCompleted += ((s, args) =>
{
if (dSrvPR.PR_PATIENTPHOTOs.Count > 0 && photo != null)
{
dSrvPR.PR_PATIENTPHOTOs.Remove(photo);
}
dSrvPR.PR_PATIENTPHOTOs.Clear();
photo = new PR_PATIENTPHOTO();
ImageTools.ExtendedImage eimg=args.Result.ToImage();
var encoder=new ImageTools.IO.Png.PngEncoder();
Stream stream= eimg.ToStreamByExtension("png");
if (stream.Length > 512000)
{
eimg= ExtendedImage.Resize(eimg, 240, new NearestNeighborResizer());
stream = eimg.ToStreamByExtension("png");
}
if (stream.Length <= 512001)
{
BinaryReader binary = new BinaryReader(stream);
//Read bytes from the BinaryReader and put them into a byte array.
Byte[] file = binary.ReadBytes((int)stream.Length);
photo.ID = Guid.NewGuid();
photo.PHOTO = file;
photo.PHOTODATE = DateTime.Now;
photo.ISACTIVE = true;
//some more unrelated fields
dSrvPR.PR_PATIENTPHOTOs.Add(photo);
dSrvPR.SubmitChanges();
//Msg succedded
}
else
{
Util.alert(...,"file size exceeded! :)";
}
});
My mistake. It seems I had some extra code in there (unnecessarily converting stream to bitmap). Here is what I got working:
void CaptureImageCompleted(object sender, CaptureImageCompletedEventArgs e)
{
busyIndicator.IsBusy = true;
stopCapture();
capturedImage.ImageSource = e.Result;
ImageTools.ExtendedImage eimg = e.Result.ToImage();
var encoder = new ImageTools.IO.Jpeg.JpegEncoder();
Stream stream = eimg.ToStreamByExtension("jpg");
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
// picture file a class object to be used by uploader
pictureFile.PictureName = "webcam.jpg"; // name will be changed later
pictureFile.PictureStream = bytes;
HtmlPage.Window.Invoke("gotDetails_WebCam", ""); // post page, then come back and do upload
}

Silverlight - Passing WritableBitmap Image to COM and convert to Bitmap

Need help in passing Image from Silverlight4 to COM.
I am trying to pass a ByteArray from WritableBitmap and convert it back to Bitmap.
//In silverlight 4:
public string func1()
{
WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)imgTempCropped.Source);
byte[] imgbytes = ToByteArray(bitmap);
dynamic comClass = AutomationFactory.CreateObject("OCRLibrary.OCRClass");
ocrText = comClass.Process(imgbytes);
}
//In COM:
public string Process(byte []imgbytes)
{
Stream input = new MemoryStream(imgbytes);
try{
Bitmap bitmap1 = new Bitmap(input);
}catch(Exception e)
{
return e.Message;
}
}
//Error Message:
Parameter is not valid.
I even tried passing in a Base64String but the same error message is thrown :(
what is COM ???
private void SaveToIsolatedStorage(Stream imageStream, string fileName, byte[] arr)
{
try
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(fileName))
{
myIsolatedStorage.DeleteFile(fileName);
}
myIsolatedStorage.CreateDirectory("Album");
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(fileName);
fileStream.Write(arr, 0, arr.Length);
fileStream.Close();
return;
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(imageStream);
WriteableBitmap wb = new WriteableBitmap(bitmap);
wb.SaveJpeg(fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
}
}
catch (Exception ex) { }
}
and
Stream uc = new MemoryStream(img);
SaveToIsolatedStorage(uc, tempJPEG, img);
check it
public string func1()
{
WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)imgTempCropped.Source);
byte[] imgbytes = ToByteArray(bitmap);
dynamic comClass = AutomationFactory.CreateObject("OCRLibrary.OCRClass");
ocrText = comClass.Process(imgbytes);
}
//In COM:
public string Process(byte []imgbytes)
{
Stream input = new MemoryStream(imgbytes);
input.Write(arr, 0, arr.Length);
input.Close();
try{
Bitmap bitmap1 = new Bitmap(input);
}catch(Exception e)
{
return e.Message;
}
}
I finally got it working...passing Bitmap from Silverlight to Silverlight COM Wrapper.
//In Silverlight:
dynamic comClass = AutomationFactory.CreateObject("OCRLibrary.OCRClass");
WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)imgTempCropped.Source);
byte[] imgbytes = ToByteArrayOptimized(bitmap);
ocrText = comClass.Process(imgbytes);
//Found this for ImageTools: ImageTools.IO.Jpeg.JpegEncode
//using ImageTools;
//using ImageTools.Helpers;
//using ImageTools.IO;
//using ImageTools.IO.Bmp;
//using ImageTools.IO.Png;
//using ImageTools.IO.Jpeg;
//I have yet to remove couple of using from here since I added all to test the code ;)
#region To byte array (optimized)
/// <summary>
/// Synchronously converts a bitmap to a byte array.
/// The used format can be JPEG or PNG, depending on which one
/// results in a smaller file size.
/// </summary>
/// <param name="bitmap">The bitmap to encode.</param>
/// <returns>The encoded image either in PNG or JPEG format.</returns>
public byte[] ToByteArrayOptimized(WriteableBitmap bitmap)
{
ExtendedImage image = bitmap.ToImage();
// encode to jpeg
MemoryStream jpegStream = new MemoryStream();
_jpegEncoder.Encode(image, jpegStream);
// encode to png
// MemoryStream pngStream = new MemoryStream();
// _pngEncoder.Encode(image, pngStream);
// decide which one we should use
// MemoryStream formatToUse = jpegStream.Length < pngStream.Length ? jpegStream : pngStream;
MemoryStream formatToUse = jpegStream;
byte[] result = formatToUse.ToArray();
// done
return result;
}
//In COM:
[ComVisible(true)]
//public string Process(string base64string )
public string Process(byte[] imgbytes)
{
MemoryStream mystream = new MemoryStream(imgbytes);
System.Drawing.Image p = System.Drawing.Image.FromStream(mystream);
Bitmap Img = new Bitmap(p); // :) I got Bitmap here.
}
http://www.pitorque.de/MisterGoodcat/post/Improving-the-image-upload-sample.aspx

WPF loading serialized image

In an app I need to serialize an image through a binarywriter, and to get it in an other app to display it.
Here is a part of my "serialization" code :
FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write);
BinaryWriter bin = new BinaryWriter(fs);
bin.Write((short)this.Animations.Count);
for (int i = 0; i < this.Animations.Count; i++)
{
MemoryStream stream = new MemoryStream();
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(Animations[i].Image));
encoder.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
bin.Write((int)stream.GetBuffer().Length);
bin.Write(stream.GetBuffer());
stream.Close();
}
bin.Close();
And here is the part of my deserialization that load the image :
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader bin = new BinaryReader(fs);
int animCount = bin.ReadInt16();
int imageBytesLenght;
byte[] imageBytes;
BitmapSource img;
for (int i = 0; i < animCount; i++)
{
imageBytesLenght = bin.ReadInt32();
imageBytes = bin.ReadBytes(imageBytesLenght);
img = new BitmapImage();
MemoryStream stream = new MemoryStream(imageBytes);
BitmapDecoder dec = new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
img = dec.Frames[0];
stream.Close();
}
bin.Close();
When I use this method, I load the image (it seems to be stored in the "img" object) but it can't be displayed.
Has somedy an idea?
Thanks
KiTe
UPD :
I already do this : updating my binding, or even trying to affect it directly through the window code behing. None of these approaches work :s
However, when I add this :
private void CreateFile(byte[] bytes)
{
FileStream fs = new FileStream(Environment.CurrentDirectory + "/" + "testeuh.png", FileMode.Create, FileAccess.Write);
fs.Write(bytes, 0, bytes.Length);
fs.Close();
}
at the end of you function, it perfectly create the file, which can be read without any problems ... So I don't know where the problem can be.
UPD 2 :
A weird things happens.
Here is the binding I use :
<Image x:Name="imgSelectedAnim" Width="150" Height="150" Source="{Binding ElementName=lstAnims, Path=SelectedItem.Image}" Stretch="Uniform" />
(the list is itself binded on an observableCollection).
When I create manually the animation through the app, it works (the image is displayed).
But when I load it, it is not displayed (I look at my code, there are not any "new" which could break up my binding, since there are others properties binded the same way and they does not fail).
Moreover, I've put a breakpoint on the getter/setter of the properties Image of my animation.
When it is created, no problems, it has the good informations.
But when it is retreived through the getter, it return a good image the first time, and then and image with pixelWidth, pixelHeight, width, height of only 1 but without going through the setter anymore !
Any idea?
UPD3
tried what you said like this :
Added a property TEST in my viewModel :
private BitmapSource test;
public BitmapSource TEST { get { return test; } set { test = value; RaisePropertyChanged("TEST"); } }
then did it :
img = getBmpSrcFromBytes(bin.ReadBytes(imageBytesLenght));
TEST = img;
(in the code showed and modified before)
and my binding :
<Image x:Name="imgSelectedAnim" Width="150" Height="150" Source="{Binding Path=TEST}" Stretch="Uniform" />
(datacontext is set to my ViewModel)
And it still doesn't work and does the weird image modification (pixW, pixH, W and H set to 1)
FINAL UPD:
It seems I finally solved the problem. Here is simply what I did :
byte[] bytes = bin.ReadBytes(imageBytesLenght);
MemoryStream mem = new MemoryStream(bytes);
img = new BitmapImage();
img.BeginInit();
img.StreamSource = mem;
img.EndInit();
the strange thing is that it didn't work the first time, maybe it is due to an architectural modification within my spriteanimation class, but I don't think it is.
Well, thank you a lot to Eugene Cheverda for his help
At the first, I think you should store your images in a list of BitmapSource and provide reverse encoding of image for using stream as BitmapImage.StreamSource:
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader bin = new BinaryReader(fs);
int animCount = bin.ReadInt16();
int imageBytesLenght;
byte[] imageBytes;
List<BitmapSource> bitmaps = new List<BitmapSource>();
for (int i = 0; i < animCount; i++)
{
imageBytesLenght = bin.ReadInt32();
imageBytes = bin.ReadBytes(imageBytesLenght);
bitmaps.Add(getBmpSrcFromBytes(imageBytes));
}
bin.Close();
UPD
In code above use func written below:
private BitmapSource getBmpSrcFromBytes(byte[] bytes)
{
using (var srcStream = new MemoryStream(bytes))
{
var dec = new PngBitmapDecoder(srcStream, BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(dec.Frames[0]);
BitmapImage bitmapImage = null;
bool isCreated;
try
{
using (var ms = new MemoryStream())
{
encoder.Save(ms);
bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = ms;
bitmapImage.EndInit();
isCreated = true;
}
}
catch
{
isCreated = false;
}
return isCreated ? bitmapImage : null;
}
}
Hope this helps.
UPD #2
Your binding is incorrect. You may be should bind selected item to for example CurrentImageSource. And then this CurrentImageSource bind to Image control.
Code:
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<BitmapSource> ImagesCollection { get; set; }
private BitmapSource _currentImage;
public BitmapSource CurrentImage
{
get { return _currentImage; }
set
{
_currentImage = value;
raiseOnPropertyChanged("CurrentImage");
}
}
private void raiseOnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Then:
<ListBox ItemsSource="{Binding ImagesCollection}" SelectedItem="{Binding CurrentImage}"/>
<Image Source="{Binding CurrentImage}"/>
ADDED
Here is the sample project in which implemented technique as I described above.
It creates animations collection and represent them in listbox, selected animation is displayed in Image control using its Image property.
What I want to say is that if you cannot obtain image as it should be, you need to search problems in serialization/deserialization.

Resources