You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin UWP中BitmapEncoder.FlushAsync()无返回问题求助

PNG转JPEG时encoder.FlushAsync()无响应的问题

在将PNG流转换为JPEG流时,程序卡在encoder.FlushAsync()处无返回、无异常;去掉await调试可通过但生成的图像损坏,添加await则应用冻结。原代码如下:

public async Task<Stream> ConvertPngToJpeg2(Stream s)
{
         byte[] resultArray = null;
           
         //Convert stream into byte array
         byte[] image = new byte[s.Length];
         s.Read(image, 0, image.Length);
           
         //Create An Instance of WriteableBitmap object  
         WriteableBitmap resultBitmap = new WriteableBitmap(1, 1);

         using (IRandomAccessStream ms = new InMemoryRandomAccessStream())
          {
              await ms.WriteAsync(image.AsBuffer());
              ms.Seek(0);
               
               //Set the source for WriteableBitmap  
               resultBitmap.SetSource(ms);
          }

        //Get the image data
        using (IRandomAccessStream ms = new InMemoryRandomAccessStream())
         {
             try
              {
                  byte[] bytes;

                  // Open a stream to copy the image contents to the WriteableBitmap's pixel buffer
                  using (Stream stream = resultBitmap.PixelBuffer.AsStream())
                  {
                      bytes = new byte[(uint)stream.Length];
                      await stream.ReadAsync(bytes, 0, bytes.Length);
                  }

                 // Create an encoder with the Jpeg format
                 BitmapEncoder encoder = await   BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ms);
                   
                 // WriteableBitmap uses BGRA format 
                 encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)resultBitmap.PixelWidth, (uint)resultBitmap.PixelHeight, 96, 96, bytes);

                 //Terminate the encoder bytes
                 await encoder.FlushAsync();
                   
                 resultArray = new byte[ms.AsStream().Length];
                 await ms.AsStream().ReadAsync(resultArray, 0, resultArray.Length);
             }
             catch (Exception e)
             {
                  System.Diagnostics.Debug.WriteLine(e.Message);
             }
         }

         //Store the image into memory stream
         Stream imgStream = new MemoryStream(resultArray);

        //Return the Jpeg image as stream
        return imgStream;
 }

问题原因及修复方案

核心问题点

  1. PNG流读取不完整:同步s.Read无法保证读取全部字节,易导致图像数据缺失。
  2. WriteableBitmap加载逻辑缺陷:SetSource是同步方法,但流写入后未确保操作完全完成,引发后续编码器处理异常。
  3. 编码后流读取未重置位置:FlushAsync执行后流指针停在末尾,直接读取会获取空数据,同时引发编码器内部死锁。

修复后的代码

public async Task<Stream> ConvertPngToJpeg2(Stream s)
{
    byte[] resultArray = null;

    // 异步读取完整PNG流数据
    byte[] image = new byte[s.Length];
    await s.ReadAsync(image, 0, image.Length);

    // 用BitmapDecoder异步加载图像,替代WriteableBitmap同步加载
    BitmapDecoder decoder = null;
    using (IRandomAccessStream ms = new InMemoryRandomAccessStream())
    {
        await ms.WriteAsync(image.AsBuffer());
        ms.Seek(0);
        decoder = await BitmapDecoder.CreateAsync(ms);
    }

    // 处理图像编码
    using (IRandomAccessStream ms = new InMemoryRandomAccessStream())
    {
        try
        {
            BitmapFrame frame = decoder.Frames[0];
            // 直接获取BGRA格式像素数据,适配JPEG编码器要求
            PixelDataProvider pixelData = await frame.GetPixelDataAsync(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Ignore,
                new BitmapTransform(),
                ExifOrientationMode.IgnoreExifOrientation,
                ColorManagementMode.DoNotColorManage);
            byte[] bytes = pixelData.DetachPixelData();

            // 创建JPEG编码器并设置参数
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, ms);
            encoder.SetPixelData(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Ignore,
                (uint)frame.PixelWidth,
                (uint)frame.PixelHeight,
                decoder.DpiX,
                decoder.DpiY,
                bytes);

            // 完成编码操作
            await encoder.FlushAsync();

            // 重置流位置到开头,读取完整编码数据
            ms.Seek(0);
            resultArray = new byte[(uint)ms.Size];
            await ms.ReadAsync(resultArray.AsBuffer(), (uint)ms.Size, InputStreamOptions.None);
        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine(e.Message);
        }
    }

    return new MemoryStream(resultArray);
}

修复说明

  • 改用BitmapDecoder异步加载图像,彻底避免同步加载带来的流状态异常。
  • 所有流操作统一使用异步方法,确保数据读写完整。
  • 编码完成后重置流位置,保证能读取到完整的JPEG数据。

内容的提问来源于stack exchange,提问作者Mannu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:55:14