【问题标题】:Decode a Multipage TIFF Container解码多页 TIFF 容器
【发布时间】:2019-11-29 11:21:27
【问题描述】:

利用this code 的后记,我能够编写一个函数来使用 Windows.Graphics.Imaging 解码多页 TIFF 文件:

 private async Task TIFHandler( StorageFile file)
 {
   var random = new Random();
   StorageFolder storage = null;
   try
   {
     uint frameCount;
     using (IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.Read, StorageOpenOptions.None))
     {
       Windows.Graphics.Imaging.BitmapDecoder bitmapDecoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(Windows.Graphics.Imaging.BitmapDecoder.TiffDecoderId, randomAccessStream);
       frameCount = bitmapDecoder.FrameCount;
       if (frameCount == 16)
       {
         StorageFolder mainfolder = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync((string)ApplicationData.Current.LocalSettings.Values["DynamicFolder"], CreationCollisionOption.OpenIfExists);
         storage = await mainfolder.CreateFolderAsync(String.Format("{0:X6}", random.Next(0x1000000)), CreationCollisionOption.ReplaceExisting);
       }
       if (storage != null)
       {
         for (int frame = 0; frame < frameCount; frame++)
         {
           var bitmapFrame = await bitmapDecoder.GetFrameAsync(Convert.ToUInt32(frame));
           var softImage = await bitmapFrame.GetSoftwareBitmapAsync();
           byte[] array = null;
           using (var ms = new InMemoryRandomAccessStream())
           {
             Windows.Graphics.Imaging.BitmapEncoder bitmapEncoder = await Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId, ms);
             bitmapEncoder.SetSoftwareBitmap(softImage);
             try
             {
               await bitmapEncoder.FlushAsync();
             }
             catch (Exception ex) { }
             array = new byte[ms.Size];
             WriteableBitmap wb = new WriteableBitmap((int)bitmapDecoder.PixelWidth, (int)bitmapDecoder.PixelHeight);
             using (Stream stream = wb.PixelBuffer.AsStream())
             {
               await stream.WriteAsync(array, 0, array.Length);
             }
             Guid BitmapEncoderGuid = Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId;
             var bmif = await storage.CreateFileAsync($"X{frame}.png", CreationCollisionOption.ReplaceExisting);
             using (IRandomAccessStream stream = await bmif.OpenAsync(FileAccessMode.ReadWrite))
             {
               Windows.Graphics.Imaging.BitmapEncoder encoder = await Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(BitmapEncoderGuid, stream);
               Stream pixelStream = wb.PixelBuffer.AsStream();
               byte[] pixels = new byte[pixelStream.Length];
               await pixelStream.ReadAsync(pixels, 0, pixels.Length);
               encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore,
                                                (uint)wb.PixelWidth,
                                                (uint)wb.PixelHeight,
                                                96.0,
                                                96.0,
                                                pixels);
               await encoder.FlushAsync();
             }
           }
         }
       }
     }
   }
   catch (Exception)
   {
     this.DynamicOperation.Text = "Error Reading TIFF Container";
     ProgressBar.Visibility = Visibility.Collapsed;
     AddTIFButton.IsEnabled = true;
     if (storage != null) { await storage.DeleteAsync(); }
   }
}

所以从外观上看,我似乎能够解码 TIFF 图像(我得到了正确的帧数),但是由于我收到了 BitmapFrame,所以我使用该函数将其转换为 SoftImage。 这次我使用 BitmapEncoder 将 SoftImage 保存为 PNG。这是我很难使用正确的方法将 SoftImage 保存为 PNG 文件的地方!

【问题讨论】:

    标签: c# uwp tiff


    【解决方案1】:

    获取SoftwareBitmap后,只需调用要保存为.png的StorageFile的OpenAsync方法即可获取随机访问流。然后使用 BitmapEncoder.CreateAsync 方法获取指定流的 BitmapEncoder 类的实例,并在编码器中设置 SoftwareBitmap。之后,调用 FlushAsync 使编码器将图像数据写入指定文件。有关如何将 SoftwareBitmap 保存为 png 文件的更多详细信息,您可以参考此document

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        var random = new Random();
        StorageFolder folder = KnownFolders.PicturesLibrary;
        StorageFile MyOriginalfile = await folder.GetFileAsync("file_example_TIFF_1MB.tiff");
    
        StorageFolder storage = null;
        try
        {
            uint frameCount;
            using (IRandomAccessStream randomAccessStream = await MyOriginalfile.OpenAsync(FileAccessMode.Read, StorageOpenOptions.None))
            {
                Windows.Graphics.Imaging.BitmapDecoder bitmapDecoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(Windows.Graphics.Imaging.BitmapDecoder.TiffDecoderId, randomAccessStream);
                frameCount = bitmapDecoder.FrameCount;
                if (frameCount == 16)
                {
                    StorageFolder mainfolder = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFolderAsync("DynamicFolder");
                    storage = await mainfolder.CreateFolderAsync(String.Format("{0:X6}", random.Next(0x1000000)), CreationCollisionOption.ReplaceExisting);
                }
                if (storage != null)
                {
                    for (int frame = 0; frame < frameCount; frame++)
                    {
                        var bitmapFrame = await bitmapDecoder.GetFrameAsync(Convert.ToUInt32(frame));
                        var softImage = await bitmapFrame.GetSoftwareBitmapAsync();
                        var bmif = await storage.CreateFileAsync($"X{frame}.png", CreationCollisionOption.ReplaceExisting);
                        SaveSoftwareBitmapToFile(softImage, bmif);
                    }
                }
            }
        }
        catch { }
    }
    
    private async void SaveSoftwareBitmapToFile(SoftwareBitmap softwareBitmap, StorageFile outputFile)
    {
        using (IRandomAccessStream stream = await outputFile.OpenAsync(FileAccessMode.ReadWrite))
        {
            // Create an encoder with the desired format
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            // Set the software bitmap
            encoder.SetSoftwareBitmap(softwareBitmap);
            encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
            encoder.IsThumbnailGenerated = true;
            try
            {
                await encoder.FlushAsync();
            }
            catch (Exception err)
            {
                const int WINCODEC_ERR_UNSUPPORTEDOPERATION = unchecked((int)0x88982F81);
                switch (err.HResult)
                {
                    case WINCODEC_ERR_UNSUPPORTEDOPERATION:
                        // If the encoder does not support writing a thumbnail, then try again
                        // but disable thumbnail generation.
                        encoder.IsThumbnailGenerated = false;
                        break;
                    default:
                        throw;
                }
            }
            if (encoder.IsThumbnailGenerated == false)
            {
                await encoder.FlushAsync();
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多