【问题标题】:Windows Phone 8.0 To Windows Phone 8.1 AppWindows Phone 8.0 到 Windows Phone 8.1 应用程序
【发布时间】:2015-02-23 06:57:57
【问题描述】:

我正在编写一个 Windows Phone 8.1 (WINRT) 应用程序。我有一个 @Sergio0694 给出的代码,它在 Windows Phone 8.0 /Silverlight 上运行良好。它压缩从图库中挑选的用户照片,然后转换为 base64 字符串。

它不适用于 Windows Phone 8.1。谁能帮帮我?

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);
}

【问题讨论】:

  • “不工作”是指它崩溃,或者什么都不做,或者你甚至不能构建/编译应用程序?
  • 实际上上面的一些方法在windows phone 8.1 中不起作用,比如 .Forget(); ..所以我试图修改它,但它在转换大图像时挂起

标签: c# windows windows-runtime windows-phone-8.1 dispatcher


【解决方案1】:

当使用TaskCompletionSource 并等待它时,除了使用TaskCompletionSource.SetResult 设置结果之外,您还应该通过调用TaskCompletionSource.SetException 来处理在TaskCompletionSource.Task 上等待时不会冒泡的任何可能发生的异常.

当您处理一个大文件时,很可能会引发异常,因此您的await completionSource.Task 将由于SetResult 未被调用而挂起。

为了说明这一点,这里有一个代码示例,它可以在没有逻辑的情况下使用调度程序执行您尝试执行的操作,但也可以按上述说明处理异常:

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";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 2015-02-25
    • 2014-08-28
    • 2014-09-07
    相关资源
    最近更新 更多