从多个BitmapImage创建Tiff文件

时间:2016-12-28 05:32:55

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

背景

我正在开发Win 10 Universal App,有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但所有答案都基于{10}库,这在Windows 10 Universal Apps中不受支持,因此您可以在我的代码中看到,我&# 39; m使用System.Drawing对象代替Windows.Ui.Xaml.Media.Imaging.BitmapImage来获取图像。

1 个答案:

答案 0 :(得分: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