Reading and Writing Images to Isolated Storage - silverlight

I have come across a couple of different ways to write images to isolated storage on some Windows Phone sites, however I am unsure which is the best to use for a camera app or if there are some that are better than others:
The first is from this post on a basic camera application: http://msdn.microsoft.com/en-us/library/hh202956(v=VS.92).aspx It takes the jpeg from the camera and writes it to isolated storage directly.
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
string fileName = savedCounter + ".jpg";
try
{ // Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Captured image available, saving picture.";
});
// Save picture to the library camera roll.
library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Picture has been saved to camera roll.";
});
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
// Save picture as JPEG to isolated storage.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(fileName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to isolated storage.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
// Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Picture has been saved to isolated storage.";
});
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
It seems to use a 4kb Buffer, is there any point in doing it this way? Seems a bit more complicated than this method which converts the image to a bitmap then uses the save as Jpeg method (http://www.windowsphonegeek.com/tips/All-about-WP7-Isolated-Storage---Read-and-Save-Images):
// Create a filename for JPEG file in isolated storage.
String tempJPEG = "logo.jpg";
// Create virtual store and file stream. Check for duplicate tempJPEG files.
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(tempJPEG))
{
myIsolatedStorage.DeleteFile(tempJPEG);
}
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(tempJPEG);
StreamResourceInfo sri = null;
Uri uri = new Uri(tempJPEG, UriKind.Relative);
sri = Application.GetResourceStream(uri);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(sri.Stream);
WriteableBitmap wb = new WriteableBitmap(bitmap);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
//wb.SaveJpeg(fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
}
If there are any alternative methods you have also I'd be interested, thanks!

Think you should check this out:
I believe I already answered this and got a +50 bounty SO Save image to Isolated Storaged using byte[]

Related

How to open PDF from memory using iTextsharp in Windows Application [duplicate]

I am doing html to pdf file . Its Downloading instantly . I dont want download instantly. i want to save the file in my project folder once converted.
My C# Code
string html ="<table><tr><td>some contents</td></tr></table>";
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=WelcomeLetter.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
StringReader sr = new StringReader(table);
Document ResultPDF = new Document(iTextSharp.text.PageSize.A4, 25, 10, 20, 30);
PdfPTable Headtable = new PdfPTable(7);
Headtable.TotalWidth = 525f;
Headtable.LockedWidth = true;
Headtable.HeaderRows = 5;
Headtable.FooterRows = 2;
Headtable.KeepTogether = true;
HTMLWorker htmlparser = new HTMLWorker(ResultPDF);
PdfWriter.GetInstance(ResultPDF, Response.OutputStream);
ResultPDF.Open();
htmlparser.Parse(sr);
ResultPDF.Close();
Response.Write(ResultPDF);
Response.End();
For saving pdf file locally in your project folder you can use FileStream class like this.
FileStream stream = new FileStream(filePath, FileMode.Create);//Here filePath is path of your project folder.
Now use this stream instead of using Response.OutputStream when you create instance of PdfWriter object.
PdfWriter.GetInstance(ResultPDF, stream);
Now do not use Responce.Write as you don't want to download your file.And close your stream at end.
stream.Close();
I'm going to combine everyone's answer into one that you should be able to drop in and use. If this works, I would accept Manish Parakhiya's answer because that had the most important part.
First, I'm going to assume you are using a recent version of iTextSharp. I think 5.5.5 is the most recent version. Second, because of this, I'm going to restructure your code a bit in order to use the using pattern. If you're stuck on an older obsolete unsupported version like 4.1.6 you'll need to re-adjust.
Almost every tutorial out there shows you that you can bind directly the Response.OutputStream. This is 100% valid but I would argue that it is also a really bad idea. Instead, bind to a more generic MemoryStream. This makes debugging much easier and your code will port and adapt that much easier.
The below code includes comments about each of the changes and what things are actually doing. The top section is all about creating a PDF from a string of HTML. The bottom actually does something with it, including writing it to disk and/or streaming it to a browser.
//Will hold our PDF eventually
Byte[] bytes;
//HTML that we want to parse
string html = "<table><tr><td>some contents</td></tr></table>";
//Create a MemoryStream to write our PDF to
using (var ms = new MemoryStream()) {
//Create our document abstraction
using (var ResultPDF = new Document(iTextSharp.text.PageSize.A4, 25, 10, 20, 30)) {
//Bind a writer to our Document abstraction and our stream
using (var writer = PdfWriter.GetInstance(ResultPDF, ms)) {
//Open the PDF for writing
ResultPDF.Open();
//Parse our HTML using the old, obsolete, not support parser
using (var sw = new StringWriter()) {
using (var hw = new HtmlTextWriter(sw)) {
using (var sr = new StringReader(html)) {
using (var htmlparser = new HTMLWorker(ResultPDF)) {
htmlparser.Parse(sr);
}
}
}
}
//Close the PDF
ResultPDF.Close();
}
}
//Grab the raw bytes of the PDF
bytes = ms.ToArray();
}
//At this point, the bytes variable holds a valid PDF file.
//You can write it disk:
System.IO.File.WriteAllBytes("your file path here", bytes);
//You can also send it to a browser:
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=WelcomeLetter.pdf");
Response.BinaryWrite(bytes);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
//Never do the next line, it doesn't do what you think it does and actually produces corrupt PDFs
//Response.Write(ResultPDF); //BAD!!!!!!
Response.End();
string tempDirectory = Session.SessionID.ToString();
string location = Path.Combine(Server.MapPath(
WebConfigurationManager.AppSettings["PathSet"].ToString()), tempDirectory);
if (!Directory.Exists(location))
{
Directory.CreateDirectory(location);
}
string fileName="abc.pdf";
filePath = Path.Combine(location, fileName);

Cannot decode jpeg using JpegBitmapDecoder

I have the following two functions to convert bytes to image and display on Image in WPF
private JpegBitmapDecoder ConvertBytestoImageStream(byte[] imageData)
{
Stream imageStreamSource = new MemoryStream(imageData);
JpegBitmapDecoder decoder = new JpegBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
return decoder;
}
The above code does not work at all. I always get the exception that "No imaging component found" Image is not displayed.
private MemoryStream ConvertBytestoImageStream(int CameraId, byte[] ImageData, int imgWidth, int imgHeight, DateTime detectTime)
{
GCHandle gch = GCHandle.Alloc(ImageData, GCHandleType.Pinned);
int stride = 4 * ((24 * imgWidth + 31) / 32);
Bitmap bmp = new Bitmap(imgWidth, imgHeight, stride, PixelFormat.Format24bppRgb, gch.AddrOfPinnedObject());
MemoryStream ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Jpeg);
gch.Free();
return ms;
}
This function works, but is very slow. I wish to optimize my code.
Your ConvertBytestoImageStream works fine for me if i pass it a JPEG buffer. There are however a few things that could be improved. Depending on whether you really want to return a decoder or a bitmap, the method could be written this way:
private BitmapDecoder ConvertBytesToDecoder(byte[] buffer)
{
using (MemoryStream stream = new MemoryStream(buffer))
{
return BitmapDecoder.Create(stream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.OnLoad); // enables closing the stream immediately
}
}
or this way:
private ImageSource ConvertBytesToImage(byte[] buffer)
{
using (MemoryStream stream = new MemoryStream(buffer))
{
BitmapDecoder decoder = BitmapDecoder.Create(stream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.OnLoad); // enables closing the stream immediately
return decoder.Frames[0];
}
}
Note that instead of using JpegBitmapDecoder this code utilizes a static factory method of the abstract base class BitmapDecoder which automatically selects the proper decoder for the provided data stream. Hence this code can be used for all image formats supported by WPF.
Note also that the Stream object is used inside a using block which takes care of disposing it when it is no longer needed. BitmapCacheOption.OnLoad ensures that the whole stream is loaded into the decoder and can be closed afterwards.

How do I simultaneously read and write to a stream for playing media file in Silverlight 4 MediaStreamSource?

BACKGROUND
I have a media file that I am progressively downloading to my Silverlight 4 application, using WebClient.OpenReadAsync/OpenReadCompleted, and Stream.BeginRead/AsyncCallback. The goal is to play the file in a MediaElement by calling the SetSource method, passing in an instance of our custom MediaStreamSource, so that the file can start playing before the entire contents of the file have been downloaded. The media file is using custom encoding/decoding, which is why we are using a custom MediaStreamSource. Our MediaStreamSource is built to accept a Stream and begin parsing track information and play back in a MediaElement. I have confirmed I am progressively downloading the file contents. Here is a summary of the download code:
public void SetSource(string sourceUrl)
{
var uriBuilder = new UriBuilder(sourceUrl);
WebClient webClient = new WebClient();
// AllowReadStreamBuffering = false allows us to get the stream
// before it's finished writing to it.
webClient.AllowReadStreamBuffering = false;
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
webClient.OpenReadAsync(uriBuilder.Uri);
}
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
_inboundVideoStream = e.Result;
BeginReadingFromStream();
}
private void BeginReadingFromStream()
{
if (_inboundVideoStream.CanRead)
{
_chunk = new byte[_chunkSize];
_inboundVideoStream.BeginRead(_chunk, 0, _chunk.Length, new AsyncCallback(BeginReadCallback), _inboundVideoStream);
}
}
private void BeginReadCallback(IAsyncResult asyncResult)
{
Stream stream = asyncResult.AsyncState as Stream;
int bytesRead = stream.EndRead(asyncResult);
_totalBytesRead += bytesRead;
if (_playableStream == null)
_playableStream = new MemoryStream();
_playableStream.Write(_chunk, 0, _chunk.Length);
if (!_initializedMediaStream && _playableStream.Length >= _minimumToStartPlayback)
{
_initializedMediaStream = true;
// Problem: we can't hand the stream source a stream that's still being written to
// It's Position is at the end. Can I read and write from the same stream or is there another way
MP4MediaStreamSource streamSource = new MP4MediaStreamSource(_playableStream);
this.Dispatcher.BeginInvoke(() =>
{
mediaElement1.SetSource(streamSource);
});
}
if (_totalBytesRead < _fileSize)
{
ReadFromDownloadStream();
}
else
{
// Finished downloading
}
}
I've tried both writing/reading to a MemoryStream simultaneously, as listed above, as well as writing to an IsolatedStorageFile and reading from that file as I'm writing to it. So far I can't find a way to make either approach work.
QUESTION:
Is there a way to read and write to the same stream? Or is there a standard way to implement this with a stream and MediaStreamSource?
Thanks
The way I did it in my MediaStreamSource implementation is to have 2 streams in it: one for reading and one for writing.
I dispose and re-create the reading stream using the buffer of the writing stream every time GetSampleAsync() is called. Another way to do it I guess is to use a negative offset when creating a MediaStreamSample to pass to ReportGetSampleCompleted() since the position of the stream will always be at the end, but you have to make sure that the position is at the end otherwise this will not work, to keep it simple I just used 2 streams

How to get Memory Stream/Base64 String from Image.Source?

I have a dynamically created Image control that is populated via a OpenFileDialog like:
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == true)
{
using (FileStream stream = dialog.File.OpenRead())
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(stream);
myImage.Source = bmp;
}
}
I want to send the image back to the server in a separate function call, as string via a web service.
How do I get a memory stream / base64 string from myImage.Source
Here's an alternative which should work (without BmpBitmapEncoder). It's uses the FileStream stream to create the byte array that is then converted to a Base64 string. This assumes you want to do this within the scope of the current code.
Byte[] bytes = new Byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Convert.ToBase64String(bytes);
Make sure you have http://imagetools.codeplex.com/
Then you can do this:
ImageSource myStartImage;
var image = ((WriteableBitmap) myStartImage).ToImage();
var encoder = new PngEncoder( false );
MemoryStream stream = new MemoryStream();
encoder.Encode( image, stream );
var myStartImageByteStream = stream.GetBuffer();
Then for Base64:
string encodedData = Convert.ToBase64String(myStartImageByteStream);

Using httpwebrequest to get image from website to byte[]

I want to read the raw binary of a PNG file on a website and store it into a byte[], so far I have something like this:
Uri imageUri = new Uri("http://www.example.com/image.png");
// Create a HttpWebrequest object to the desired URL.
HttpWebRequest imgRequest = (HttpWebRequest)WebRequest.Create(imageUri);
using (HttpWebResponse imgResponse = (HttpWebResponse)imgRequest.GetResponse())
{
using (BinaryReader lxBR = new BinaryReader(imgResponse.GetResponseStream()))
{
using (MemoryStream lxMS = new MemoryStream())
{
lnBuffer = lxBR.ReadBytes(1024);
while (lnBuffer.Length > 0)
{
lxMS.Write(lnBuffer, 0, lnBuffer.Length);
lnBuffer = lxBR.ReadBytes(1024);
}
lnFile = new byte[(int)lxMS.Length];
lxMS.Position = 0;
lxMS.Read(lnFile, 0, lnFile.Length);
}
}
}
but I can't use GetResponse on Silverlight because it is not Asynchronous (I think that's the reason) so instead I should be using BeginGetResponse, but I'm not completely clear on how to go about it. This is what I have so far:
HttpWebResponse imgResponse = (HttpWebResponse)imgRequest.BeginGetResponse(new AsyncCallback(WebComplete), imgRequest);
using (imgResponse)
{
using (BinaryReader lxBR = new BinaryReader(imgResponse.GetResponseStream()))
{
/*Same*/
}
}
and
void WebComplete(IAsyncResult a)
{
HttpWebRequest req = (HttpWebRequest)a.AsyncState;
HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(a);
//...? Do I need something else here?
}
can someone explain me a little bit how to use the BeginGetResponse property and how do I use the AsyncCallback.
Thanks!
Note:
I'm new to silverlight and I've been following tutorials and borrowing from other responses here on StackOverflow:
(stackoverflow responce) what I need to do but not in silverlight
tutorial
WebRequest_in_Silverlight
is this valid Silverlight code?
HttpWebResponse imgResponse = (HttpWebResponse)imgRequest.BeginGetResponse(new AsyncCallback(WebComplete), imgRequest);
Got it working, want to post it here in case anyone needs it.
I need to get this image and then modify it (byte level) Silverlight didn't let me save the image directly to a WriteableBitmap and thus I had to get the image with a WebClient as a stream and then save it to a byte[]
this is how I get the image (I already have the specific Uri):
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(uri)
so when the image is loaded the wc_OpenReadCompleted method is called and it does something like this:
int lengthInBytes = Convert.ToInt32(e.Result.Length);
BinaryReader br = new BinaryReader(e.Result);
byte[] buffer = new byte[lengthInBytes];
using (br)
{
for (int i = 0; i < lengthInBytes; i++)
{
buffer[i] = br.ReadByte();
}
}
at the end the buffer[] has all the bytes of the image (what I wanted)
I'm sure there are better ways of doing this but this is working for me ! )
note: at some point I need to convert the byte[] to a BitmapImage (that was easier than expected):
//imageInBytes is a byte[]
if (imageInBytes != null)
{
MemoryStream rawBytesStream = new MemoryStream(imageInBytes);
BitmapImage img = new BitmapImage();
img.SetSource(rawBytesStream);
return img;
}
I hope this helps anyone.
Use the OpenReadAsync method of the WebClient object. Attach to the OpenReadCompleted event of the WebClient. Use the Stream provided by the Result property of the event args.
Consider setting AllowReadStreamBuffering, this will fill the entire stream before raising the OpenReadCompleted. In either case its likely you can use this stream to complete you real task rather than coping it into a MemoryStream.

Resources