Create Tiff File from multiple BitmapImage

二次信任 提交于 2021-02-08 03:32:11

问题


Background:

I'm developing Win 10 Universal App, have list of BitmapImage:

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

Each list item is created by converting byte[] to BitmapImage by this code:

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

Question:

How to convert this list to single multi-page Tiff file?

Notes:

I've found many related answers like this but all are based on System.Drawing library which is not supported in Windows 10 Universal Apps, so as you can see in my code, I'm using Windows.Ui.Xaml.Media.Imaging.BitmapImage object instead of System.Drawing.Bitmap to get the image.


回答1:


How to convert this list to single multi-page Tiff file

In UWP app, we can use BitmapEncoder to encode a Tiff image file to contain several frames. BitmapEncoder.SetPixelData method can be used for setting pixel data on one frame and then BitmapEncoder.GoToNextFrameAsync can asynchronously commits the current frame data and appends a new empty frame to be edited. So the Tiff image can be created by multiply images.

Suppose I want to create a Tiff image file from three images that are located on my local folder, I decode and read pixel data from them and set to the Tiff image. Sample code as follows:

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

The temp.tiff will be created successfully. I'm not sure how you got the image byte array, but BitmapImage cannot be directly written to or updated, you need to got WriteableBitmap object from your byte array. If you don't know how to get the WriteableBitmap please try to reference the following code or save the BitmapImage to local folder and using the code I provided above.

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

More details please reference the official sample.



来源:https://stackoverflow.com/questions/41355922/create-tiff-file-from-multiple-bitmapimage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!