如何将此列表转换为单个多页 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。