I am writing a Windows Phone 8.1 (WINRT) App . I have a code given by @Sergio0694 which is running good on Windows Phone 8.0 /Silverlight. It compresses user photo picked from gallery and then converts to base64 string.
Its not working on Windows Phone 8.1. Can anyone help me ?
public static async Task<String> ToCompressedBase64(this StorageFile imageFile, Page localPage)
{
//Get the stream from the StorageFile
IRandomAccessStream imageStream = await imageFile.OpenAsync(FileAccessMode.Read);
System.Diagnostics.Debug.WriteLine("Original size ---> " + imageStream.ToFileSize());
//Compresses the image if it exceedes the maximum file size
imageStream.Seek(0);
BitmapDecoder compressDecoder = await BitmapDecoder.CreateAsync(imageStream);
PixelDataProvider compressionData = await compressDecoder.GetPixelDataAsync();
byte[] compressionBytes = compressionData.DetachPixelData();
//Set target compression quality
BitmapPropertySet propertySet = new BitmapPropertySet();
BitmapTypedValue qualityValue = new BitmapTypedValue(0.5, PropertyType.Single);
propertySet.Add("ImageQuality", qualityValue);
imageStream.Seek(0);
imageStream = new InMemoryRandomAccessStream();
BitmapEncoder compressionEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, imageStream, propertySet);
compressionEncoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight,
compressDecoder.PixelWidth, compressDecoder.PixelHeight,
compressDecoder.DpiX, compressDecoder.DpiY, compressionBytes);
await compressionEncoder.FlushAsync();
//Create a BitmapDecoder from the stream
BitmapDecoder resizeDecoder = await BitmapDecoder.CreateAsync(imageStream);
#if DEBUG
System.Diagnostics.Debug.WriteLine("Old height and width ---> " + resizeDecoder.PixelHeight + " * " + resizeDecoder.PixelWidth + "\nCompressed size ---> " + imageStream.ToFileSize());
#endif
//Resize the image if needed
TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>();
localPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
const int maxImageWidth = 48;
if (resizeDecoder.PixelWidth > maxImageWidth)
{
//Resize the image if it exceedes the maximum width
int newHeight = (int)(maxImageWidth * resizeDecoder.PixelHeight / resizeDecoder.PixelWidth);
WriteableBitmap tempBitmap = new WriteableBitmap((int)resizeDecoder.PixelWidth, (int)resizeDecoder.PixelHeight);
imageStream.Seek(0);
await tempBitmap.SetSourceAsync(imageStream);
WriteableBitmap resizedImage = tempBitmap.Resize(maxImageWidth, newHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
//Assign to imageStream the resized WriteableBitmap
InMemoryRandomAccessStream resizedStream = new InMemoryRandomAccessStream();
await resizedImage.ToStream(resizedStream, BitmapEncoder.JpegEncoderId);
imageStream = resizedStream;
}
completionSource.SetResult(true);
}).Forget();
await completionSource.Task;
//Converts the final image into a Base64 String
imageStream.Seek(0);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);
PixelDataProvider pixels = await decoder.GetPixelDataAsync();
#if DEBUG
System.Diagnostics.Debug.WriteLine("New height and width ---> " + decoder.PixelHeight + " * " + decoder.PixelWidth + "\nSize after resize ---> " + imageStream.ToFileSize());
#endif
byte[] bytes = pixels.DetachPixelData();
//Encode image
InMemoryRandomAccessStream encoded = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, encoded);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, decoder.PixelWidth, decoder.PixelHeight, decoder.DpiX, decoder.DpiY, bytes);
await encoder.FlushAsync();
encoded.Seek(0);
//Read bytes
byte[] outBytes = new byte[encoded.Size];
await encoded.AsStream().ReadAsync(outBytes, 0, outBytes.Length);
//Create Base64
return Convert.ToBase64String(outBytes);
}
When using TaskCompletionSource
and awaiting on it, in addition to setting the result with TaskCompletionSource.SetResult
you should also handle any exception that may occur that will not be bubbled up when you await on TaskCompletionSource.Task
by calling TaskCompletionSource.SetException
.
It's very likely that when you were dealing with a big file an exception was being thrown and thus your await completionSource.Task
would then hang due to SetResult
not being called.
To illustrate this here's an example of code that does what you're trying to do with the dispatcher w/o your logic but also handles the exception as explained above:
public async Task<string> TestTaskCompletionSource(CoreDispatcher dispatcher)
{
TaskCompletionSource<bool> completionSource = new TaskCompletionSource<bool>();
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
try
{
Debug.WriteLine("Before delay");
await Task.Delay(100);
Debug.WriteLine("After delay and before exception");
throw new Exception("Test");
#pragma warning disable 162
completionSource.SetResult(true);
#pragma warning restore 162
}
catch (Exception e)
{
completionSource.SetException(e);
}
});
await completionSource.Task;
return "Test";
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.