【问题标题】:Create Tiff File from multiple BitmapImage从多个 BitmapImage 创建 Tiff 文件
【发布时间】:2016-12-28 05:32:55
【问题描述】:

背景:

我正在开发 Win 10 通用应用,有 BitmapImage 列表:

List<BitmapImage> ImagesList = new List<BitmapImage>();

每个列表项都是通过以下代码将byte[] 转换为BitmapImage 创建的:

 public async Task<BitmapImage> GetBitmapImage(byte[] array)
        {
            using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
            {
                using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
                {
                    writer.WriteBytes(array);
                    await writer.StoreAsync();
                }
                BitmapImage image = new BitmapImage();
                List<BitmapImage> ImagesList = new List<BitmapImage>();
                await image.SetSourceAsync(stream);
                return image;
            }
        }

问题:

如何将此列表转换为单个多页 Tiff 文件?

注意事项:

我找到了许多相关答案,例如 this,但所有答案都基于 Windows 10 通用应用程序不支持的 System.Drawing 库,因此您可以在我的代码中看到,我使用的是 Windows.Ui.Xaml.Media.Imaging.BitmapImage 对象而不是System.Drawing.Bitmap 来获取图像。

【问题讨论】:

  • 想知道您采用了什么解决方案
  • 我相信我使用了下面的答案,但目前无法确认,因为我无法再访问源代码了。

标签: c# bitmap uwp windows-10-universal tiff


【解决方案1】:

如何将此列表转换为单个多页 Tiff 文件

在 UWP 应用中,我们可以使用 BitmapEncoder 将 Tiff 图像文件编码为包含多个帧。 BitmapEncoder.SetPixelData 方法可以用于在一帧上设置像素数据,然后BitmapEncoder.GoToNextFrameAsync 可以异步提交当前帧数据并附加一个新的空帧进行编辑。所以Tiff图像可以通过多张图像来创建。

假设我想从位于我的本地文件夹中的三个图像创建一个 Tiff 图像文件,我从它们解码和读取像素数据并设置为 Tiff 图像。示例代码如下:

 private async void btnConvert_Click(object sender, RoutedEventArgs e)
 {
     StorageFolder localfolder = ApplicationData.Current.LocalFolder;
     StorageFile image1 = await localfolder.GetFileAsync("caffe1.jpg");
     StorageFile image2 = await localfolder.GetFileAsync("caffe2.jpg");
     StorageFile image3 = await localfolder.GetFileAsync("caffe3.jpg");
     StorageFile targettiff = await localfolder.CreateFileAsync("temp.tiff", CreationCollisionOption.ReplaceExisting);
     WriteableBitmap writeableimage1;
     WriteableBitmap writeableimage2;
     WriteableBitmap writeableimage3;
     using (IRandomAccessStream stream = await image1.OpenAsync(FileAccessMode.Read))
     {
         SoftwareBitmap softwareBitmap;
         BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
         softwareBitmap = await decoder.GetSoftwareBitmapAsync();
         writeableimage1 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
         writeableimage1.SetSource(stream);
     }
     using (IRandomAccessStream stream = await image2.OpenAsync(FileAccessMode.Read))
     {
         SoftwareBitmap softwareBitmap;
         BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
         softwareBitmap = await decoder.GetSoftwareBitmapAsync();
         writeableimage2 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
         writeableimage2.SetSource(stream);
     }
     using (IRandomAccessStream stream = await image3.OpenAsync(FileAccessMode.Read))
     {
         SoftwareBitmap softwareBitmap;
         BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
         softwareBitmap = await decoder.GetSoftwareBitmapAsync();
         writeableimage3 = new WriteableBitmap(softwareBitmap.PixelWidth, softwareBitmap.PixelHeight);
         writeableimage3.SetSource(stream);
     }

     using (IRandomAccessStream ras = await targettiff.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.None))
     {
         BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.TiffEncoderId, ras);
         var stream = writeableimage1.PixelBuffer.AsStream();
         byte[] buffer = new byte[stream.Length];
         await stream.ReadAsync(buffer, 0, buffer.Length);

         var stream2 = writeableimage2.PixelBuffer.AsStream();
         byte[] buffer2 = new byte[stream2.Length];
         await stream2.ReadAsync(buffer2, 0, buffer2.Length);

         var stream3 = writeableimage3.PixelBuffer.AsStream();
         byte[] buffer3 = new byte[stream3.Length];
         await stream3.ReadAsync(buffer3, 0, buffer3.Length);


         encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage1.PixelWidth, (uint)writeableimage1.PixelHeight, 96.0, 96.0, buffer);
         await encoder.GoToNextFrameAsync();
         encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage2.PixelWidth, (uint)writeableimage2.PixelHeight, 96.0, 96.0, buffer2);
         await encoder.GoToNextFrameAsync();
         encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableimage3.PixelWidth, (uint)writeableimage3.PixelHeight, 96.0, 96.0, buffer3);
         await encoder.FlushAsync();
     }
 }

temp.tiff 将被成功创建。我不确定您是如何获得图像字节数组的,但 BitmapImage 不能直接写入或更新,您需要从字节数组中获取 WriteableBitmap 对象。如果您不知道如何获取WriteableBitmap,请尝试参考以下代码或将BitmapImage 保存到本地文件夹并使用我上面提供的代码。

public async Task<WriteableBitmap> SaveToImageSource(byte[] imageBuffer)
{             
    using (MemoryStream stream = new MemoryStream(imageBuffer))
    {
        var ras = stream.AsRandomAccessStream();
        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, ras);
        var provider = await decoder.GetPixelDataAsync();
        byte[] buffer = provider.DetachPixelData();
        WriteableBitmap ablebitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
        await ablebitmap.PixelBuffer.AsStream().WriteAsync(buffer, 0, buffer.Length);
        return ablebitmap;
    }           
}

更多详情请参考official sample

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 2011-05-20
    • 1970-01-01
    相关资源
    最近更新 更多