I am trying to add some text on top of a photo take by the camera, and here is the method I am using, but unfortunately I either get a closedStream error, or that there is cross-thread access when I try use the dispatcher. Could someone please explain me what is going wrong?
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
DateTime dt = DateTime.Now;
string fileName = dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Second.ToString() + ".jpg";
try
{
// Save picture to the library camera roll.
library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// load photo to writable bitmap
WriteableBitmap writeableBitmap = PictureDecoder.DecodeJpeg(e.ImageStream);
writeableBitmap.Invalidate();
var renderText = new TextBlock
{
Text = "Hello World",
FontSize = 72,
Foreground = new SolidColorBrush(Colors.White),
FontWeight = FontWeights.Black,
Width = 500,
Height = 100
};
writeableBitmap.Render(renderText, new TranslateTransform() { X = 100, Y = 300 });
writeableBitmap.Invalidate();
using (var ms = new MemoryStream())
{
writeableBitmap.SaveJpeg(ms, 1024, 768, 0, 100);
ms.Seek(0, SeekOrigin.Begin);
library.SavePicture("x" + fileName, ms);
}
// e.ImageStream.Close();
});
// 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);
}
}
}
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
With the code above I get the following error: Cannot access a closed Stream.
If i remove the Dispatcher, I get this error: Invalid cross-thread access.
Thanks.
place ui less code outside dispatcher scope.
or save your e.ImageStream to other stream can be gotted in dispatcher scope.
First, what is occurring?
Dispatcher.BeginInvoke postpones your code and tells the UI thread to execute it whenever it's available. Therefore, your e.ImageStream.Close(); line is executed before the code inside of the BeginInvoke. So when you're trying to read the contents of the stream, it's already closed.
Two ways to solve that:
Remove the e.ImageStream.Close(); from the finally block. But I don't know if the stream will remain open anyway.
If 1. doesn't work, copy the contents of the stream to a MemoryStream, then use this stream to create the WriteableBitmap:
var stream = new MemoryStream();
e.ImageStream.CopyTo(stream);
In both case, don't forget to close the stream when you're done creating the WriteableBitmap.
Related
I have a Windows 10 UWP app that will run on Windows 10 Mobile. A requirement I have is to capture a signature from the user. So far, I am simply using an InkCanvas in XAML and have it wired up to my code behind.
I then have a button that when clicked, will take the signature on the InkCanvas and send it to the server via a WCF call. The server and WCF service is already existing. It takes in the signature image as a base64 serialized string.
I know how to get the base64 once I have either an image or a byte array. However, in my many hours of reading, I am finding that articles/examples were either written for WPF or Windows 8.1 and do not work on Windows 10 UWP. Also, of the examples that I have found that will work, it seems my only option is to save the signature to file as a GIF.
I see that I can call GetStrokes() like this
var strokeCollection = cvsSignature.InkPresenter.StrokeContainer.GetStrokes();
Which will return me a read only list of InkStroke. I guess I can iterate that list and build a byte array? How would I do that? It seems this is not efficient?
Otherwise, I thought I could just change the stream from a file stream to a memory stream but I guess either this is not possible or I am missing something. I am trying this
using (var inkMemStream = new MemoryStream())
{
await cvsSignature.InkPresenter.StrokeContainer.SaveAsync(inkMemStream);
}
But with this type of approach I get an exception that I cannot convert from System.IO.MemoryStream to Windows.Storage.Streams.IOutputStream
Thanks!
I found a way, if you don't want to save your InkCanvas to a file or as a GIF, to manipulate it in memory. I actually have three options below. Note, for some of this, you will need to add a reference to Win2D.uwp, which can be found on NuGet by searching that exact name. It is provided by Microsoft.
Convert the InkCanvas to a byte array:
private byte[] ConvertInkCanvasToByteArray()
{
//First, we need to get all of the strokes in the canvas
var canvasStrokes = myCanvas.InkPresenter.StrokeContainer.GetStrokes();
//Just as a check, make sure to only do work if there are actually strokes (ie not empty)
if (canvasStrokes.Count > 0)
{
var width = (int)myCanvas.ActualWidth;
var height = (int)myCanvas.ActualHeight;
var device = CanvasDevice.GetSharedDevice();
//Create a new renderTarget with the same width and height as myCanvas at 96dpi
var renderTarget = new CanvasRenderTarget(device, width,
height, 96);
using (var ds = renderTarget.CreateDrawingSession())
{
//This will clear the renderTarget with a clean slate of a white background.
ds.Clear(Windows.UI.Colors.White);
//Here is where we actually take the strokes from the canvas and draw them on the render target.
ds.DrawInk(myCanvas.InkPresenter.StrokeContainer.GetStrokes());
}
//Finally, this will return the render target as a byte array.
return renderTarget.GetPixelBytes();
}
else
{
return null;
}
}
If all you need is a byte array of the pixels, you are done. However, if you now want to generate an image, you use the WriteableBitmap to do so. Here are sync and async methods that can be called to do this.
private WriteableBitmap GetSignatureBitmapFull()
{
var bytes = ConvertInkCanvasToByteArray();
if (bytes != null)
{
var width = (int)cvsSignature.ActualWidth;
var height = (int)cvsSignature.ActualHeight;
var bmp = new WriteableBitmap(width, height);
using (var stream = bmp.PixelBuffer.AsStream())
{
stream.Write(bytes, 0, bytes.Length);
return bmp;
}
}
else
return null;
}
private async Task<WriteableBitmap> GetSignatureBitmapFullAsync()
{
var bytes = ConvertInkCanvasToByteArray();
if (bytes != null)
{
var width = (int)cvsSignature.ActualWidth;
var height = (int)cvsSignature.ActualHeight;
var bmp = new WriteableBitmap(width, height);
using (var stream = bmp.PixelBuffer.AsStream())
{
await stream.WriteAsync(bytes, 0, bytes.Length);
return bmp;
}
}
else
return null;
}
Finally, here is an async method that I am using to be able to do a crop on the bitmap if you want to do that. The key thing with this method is notice how with this approach, you don't have to get the pixel bytes as an array first. You just get the strokes from the canvas and then it is saved directly into a memory stream
private async Task<WriteableBitmap> GetSignatureBitmapCropped()
{
try
{
var canvasStrokes = cvsSignature.InkPresenter.StrokeContainer.GetStrokes();
if (canvasStrokes.Count > 0)
{
var bounds = cvsSignature.InkPresenter.StrokeContainer.BoundingRect;
var xOffset = (uint)Math.Round(bounds.X);
var yOffset = (uint)Math.Round(bounds.Y);
var pixelWidth = (int)Math.Round(bounds.Width);
var pixelHeight = (int)Math.Round(bounds.Height);
using (var memStream = new InMemoryRandomAccessStream())
{
await cvsSignature.InkPresenter.StrokeContainer.SaveAsync(memStream);
var decoder = await BitmapDecoder.CreateAsync(memStream);
var transform = new BitmapTransform();
var newBounds = new BitmapBounds();
newBounds.X = 0;
newBounds.Y = 0;
newBounds.Width = (uint)pixelWidth;
newBounds.Height = (uint)pixelHeight;
transform.Bounds = newBounds;
var pdp = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Straight,
transform,
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
var pixels = pdp.DetachPixelData();
var cropBmp = new WriteableBitmap(pixelWidth, pixelHeight);
using (var stream = cropBmp.PixelBuffer.AsStream())
{
await stream.WriteAsync(pixels, 0, pixels.Length);
}
return cropBmp;
}
}
else
{
return null;
}
}
catch (Exception ex)
{
return null;
}
}
Hope this helps provide some alternatives when using InkCanvas in Windows 10 Universal.
it seems my only option is to save the signature to file as a GIF.
GIF is not the only choice. The official sample just show GIF, but you can also save the InkStokes collection to JPG and PNG. Code as follows:
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add("Gif,JPG,PNG", new System.Collections.Generic.List<string> { ".jpg" ,".gif",".png"});
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
But with this type of approach I get an exception that I cannot convert from System.IO.MemoryStream to Windows.Storage.Streams.IOutputStream
As you see, it cannot convert from System.IO.MemoryStream to Windows.Storage.Streams.IOutputStream directly. You need to read the image file you just saved as ImageSource. As you known how to get the base64 once you have either an image or a byte array. So what we just need is to get an image or a byte array from the image file.
Read the image file as byte array and then a memory stream as follows
if (inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count > 0)
{
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add("Gif,JPG,PNG", new System.Collections.Generic.List<string> { ".jpg", ".gif", ".png" });
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
if (null != file)
{
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(stream);
}
using (IRandomAccessStream streamforread = await file.OpenAsync(FileAccessMode.Read))
{
WriteableBitmap inkimagesource = new WriteableBitmap(50, 50);
inkimagesource.SetSource(streamforread);
byte[] imageBuffer = inkimagesource.PixelBuffer.ToArray();
MemoryStream ms = new MemoryStream(imageBuffer);
}
}
}
Read the file as image source just need to change the file reading code as follows:
using (IRandomAccessStream streamforread = await file.OpenAsync(FileAccessMode.Read)
{
var bitmap = new BitmapImage();
bitmap.SetSource(streamforread);
}
I guess I can iterate that list and build a byte array? How would I do that? It seems this is not efficient?
It seems like currently there is no API can build the InkStroke collections as byte array directly. SaveAsync() method has already help you save the InkStroke collection to a stream, you can use code above for using it.
I am developing an application which has many images & i want to implement that on clicking "save button" the Image should be stored to Photo Album.
Please reply i am new to app dev.
To work with this function you just need to pass needed Image as parameter in SaveImageToPhotoHub function.
private bool SaveImageToPhotoHub(WriteableBitmap bmp)
{
using (var mediaLibrary = new MediaLibrary())
{
using (var stream = new MemoryStream())
{
var fileName = string.Format("Gs{0}.jpg", Guid.NewGuid());
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
var picture = mediaLibrary.SavePicture(fileName, stream);
if (picture.Name.Contains(fileName)) return true;
}
}
return false;
}
Heres more to it http://www.codeproject.com/Articles/747273/How-to-Save-Image-in-Local-Photos-album-of-Windows
Try this code. This is in VB.Net but I am sure you can convert it yourself or through online tools for C#:
' Create a file name for the JPEG file in isolated storage.
Dim tempJPEG As String = "dummyImage1"
' Create a virtual store and file stream. Check for duplicate tempJPEG files.
Dim myStore = IsolatedStorageFile.GetUserStoreForApplication()
If myStore.FileExists(tempJPEG) Then
myStore.DeleteFile(tempJPEG)
End If
Dim myFileStream As IsolatedStorageFileStream = myStore.CreateFile(tempJPEG)
' Create a stream out of the sample JPEG file.
' For [Application Name] in the URI, use the project name that you entered
' in the previous steps. Also, TestImage.jpg is an example;
' you must enter your JPEG file name if it is different.
Dim sri As StreamResourceInfo = Nothing
Dim uri As New Uri("/projectName;component/Assets/1.jpg", UriKind.Relative)
sri = Application.GetResourceStream(uri)
' Create a new WriteableBitmap object and set it to the JPEG stream.
Dim bitmap As New BitmapImage()
bitmap.CreateOptions = BitmapCreateOptions.None
bitmap.SetSource(sri.Stream)
Dim wb As New WriteableBitmap(bitmap)
' Encode WriteableBitmap object to a JPEG stream.
wb.SaveJpeg(myFileStream, wb.PixelWidth, wb.PixelHeight, 0, 85)
myFileStream.Close()
' Create a new stream from isolated storage, and save the JPEG file to the media library on Windows Phone.
myFileStream = myStore.OpenFile(tempJPEG, FileMode.Open, FileAccess.Read)
' Save the image to the camera roll or saved pictures album.
Dim library As New MediaLibrary()
' Save the image to the saved pictures album.
Dim pic As Picture = library.SavePicture("dummyImage1.jpg", myFileStream)
MessageBox.Show("Image saved to saved pictures album")
myFileStream.Close()
I found on something like that:source https://msdn.microsoft.com.
// Informs when full resolution photo has been taken, saves to local media library and the local folder.
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 photo.";
});
// Save photo to the media library camera roll.
library.SavePictureToCameraRoll(fileName, e.ImageStream);
// Write message to the UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Photo has been saved to camera roll.";
});
// Set the position of the stream back to start
e.ImageStream.Seek(0, SeekOrigin.Begin);
// Save photo as JPEG to the local folder.
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 the local folder.
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 = "Photo has been saved to the local folder.";
});
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
// Informs when thumbnail photo has been taken, saves to the local folder
// User will select this image in the Photos Hub to bring up the full-resolution.
public void cam_CaptureThumbnailAvailable(object sender, ContentReadyEventArgs e)
{
string fileName = savedCounter + "_th.jpg";
try
{
// Write message to UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Captured image available, saving thumbnail.";
});
// Save thumbnail as JPEG to the local folder.
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 thumbnail to the local folder.
while ((bytesRead = e.ImageStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
// Write message to UI thread.
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
txtDebug.Text = "Thumbnail has been saved to the local folder.";
});
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
I am developing one windows phone application which useful for upload images to web server. I am selecting all images from my device into one List object. I am converting all bitmap image to byte[] one by one.
My code
public byte[] ConvertToBytes(BitmapImage bitmapImage)
{
byte[] data = null;
WriteableBitmap wBitmap = null;
using (MemoryStream stream = new MemoryStream())
{
wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
//data = stream.GetBuffer();
data = stream.ToArray();
DisposeImage(bitmapImage);
return data;
}
}
public void DisposeImage(BitmapImage image)
{
if (image != null)
{
try
{
using (MemoryStream ms = new MemoryStream(new byte[] { 0x0 }))
{
image.SetSource(ms);
}
}
catch (Exception ex)
{
}
}
}
Conversion from bitmap to byte
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (!store.DirectoryExists("ImagesZipFolder"))
{
//MediaImage mediaImage = new MediaImage();
//mediaImage.ImageFile = decodeImage(new byte[imgStream[0].Length]);
//lstImages.Items.Add(mediaImage);
store.CreateDirectory("ImagesZipFolder");
for (int i = 0; i < imgname.Count(); i++)
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(#"ImagesZipFolder\" + imgname[i], FileMode.CreateNew,store))
//using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(#"ImagesZipFolder\text.txt" , System.IO.FileMode.OpenOrCreate, store))
{
// byte[] bytes = new byte[imgStream[i].Length];
byte[] bytes = ConvertToBytes(ImgCollection[i]);
stream.Write(bytes, 0, bytes.Length);
}
}
}
else {
directory = true;
}
}
I have 91 images in my emulator. When I am converting all these bitmap images into byte[], get's following error on line wBitmap = new WriteableBitmap(bitmapImage);
An exception of type 'System.OutOfMemoryException' occurred in System.Windows.ni.dll but was not handled in user code
What can I do to solve this error?
Web Service
If we are sending huge file to web service, is it gives error like
An exception of type 'System.OutOfMemoryException' occurred in System.ServiceModel.ni.dll but was not handled in user code
What can I do to solve this error?
Change the way you do things, to use less memory.
For instance, instead of converting every picture then uploading them, convert a picture, upload it, convert the next, and so on.
If you really want to process all the pictures at once, you can store the byte arrays in the isolated storage rather than keeping them in memory, and read them back when needed.
Basically, rethink your process and use the storage to use less memory at a given time.
That or ask Microsoft to lift the memory limit on Windows Phone, but it may be a tad trickier.
The problem lies within how the GC and bitmap images work together as described in this bug report: https://connect.microsoft.com/VisualStudio/feedback/details/679802/catastrophic-failure-exception-thrown-after-loading-too-many-bitmapimage-objects-from-a-stream#details
From the report:
When Silverlight loads an image, the framework keeps a reference and
caches the decoded image until flow control is returned to the UI
thread dispatcher. When you load images in a tight loop like that,
even though your application doesn't retain a reference, the GC can't
free the image until we release our reference when flow control is
returned.
After processing 20 or so images, you could stop and queue the next
set using Dispatcher.BeginInvoke just to break up the work that is
processed in one batch. This will allow us to free images that aren't
retained by your application.
I understand with the current decode behavior it's not obvious that
Silverlight is retaining these references, but changing the decoder
design could impact other areas, so for now I recommend processing
images like this in batches.
Now, if you're actually trying to load 500 images and retain them, you
are still likely to run out of memory depending on image size. If
you're dealing with a multi-page document, you may want to instead
load pages on demand in the background and release them when out of
view with a few pages of buffer so that at no point do you exceed
reasonable texture memory limits.
Fix:
private List<BitmapImage> Images = .....;
private List<BitmapImage>.Enumerator iterator;
private List<byte[]> bytesData = new List<byte[]>();
public void ProcessImages()
{
if(iterator == null)
iterator = Images.GetEnumerator();
if(iterator.MoveNext())
{
bytesData.Add(ConvertToBytes(iterator.Current));
//load next images
Dispatcher.BeginInvoke(() => ProcessImages());
}else{
//all images done
}
}
public static byte[] ConvertToBytes(BitmapImage bitmapImage)
{
using (MemoryStream stream = new MemoryStream())
{
var wBitmap = new WriteableBitmap(bitmapImage);
wBitmap.SaveJpeg(stream, wBitmap.PixelWidth, wBitmap.PixelHeight, 0, 100);
stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
}
}
I have found new way to convert Bitmap Image to byte[] array. There is no need to write image in memory.
Hare is code
public byte[] GetBytes(BitmapImage bi)
{
WriteableBitmap wbm = new WriteableBitmap(bi);
return ToByteArray(wbm);
}
public byte[] ToByteArray(WriteableBitmap bmp)
{
// Init buffer
int w = bmp.PixelWidth;
int h = bmp.PixelHeight;
int[] p = bmp.Pixels;
int len = p.Length;
byte[] result = new byte[4 * w * h];
// Copy pixels to buffer
for (int i = 0, j = 0; i < len; i++, j += 4)
{
int color = p[i];
result[j + 0] = (byte)(color >> 24); // A
result[j + 1] = (byte)(color >> 16); // R
result[j + 2] = (byte)(color >> 8); // G
result[j + 3] = (byte)(color); // B
}
return result;
}
I have tried to convert binary data to Image. here is my code:
Byte[] bytes = (byte[])(reader["Avatar"]);
fs1.Write(bytes, 0, bytes.Length);
pictureBox1.Image = Image.FromFile("image.jpg");
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Refresh();
but the wrong is out of bound memory exception in line : "pictureBox1.Image = Image.FromFile("image.jpg");"
I do not know why this happen, please help me
Try with this method:
public Image ImageFromBytes(byte[] bytes)
{
using(var ms = new MemoryStream(bytes))
{
return Image.FromStream(ms);
}
}
If fs1 is a stream you probably should close it before you access that file in the next line.
Note that you can also create the image in memory and avoid the file system completely.
You mast Close and Dispose your stream:
fs1.Write(bytes, 0, bytes.Length);
//Make sure you closed your stream
fs1.Close();
// You should call Dispose too.
fs1.Dispose();
pictureBox1.Image = Image.FromFile("image.jpg");
or enclose your writing file procces in using block:
using (Stream fs1 ...)
{
...
fs1.Write(bytes, 0, bytes.Length);
}
I am trying to reduce the size of an Image I am taking from the camera before I save it to Isolated Storage. I already have it reduced to the lowest resolution (640x480) How can I reduce the bytes to 100kb instead of what they are coming out at almost 1mb.
void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
string fileName = folderName+"\\MyImage" + savedCounter + ".jpg";
try
{
// 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);
}
}
}
}
finally
{
// Close image stream
e.ImageStream.Close();
}
}
I have nothing about Windows Phone, but maybe this link will help you:
http://msdn.microsoft.com/en-us/library/ff769549(v=vs.92).aspx
1) load your jpeg
2) copy to bitmap
3) save as bitmap with quality settings
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.extensions.savejpeg(v=vs.92).aspx