Working backwords from this code, I was able to write a function to decode a multipage TIFF file using Windows.Graphics.Imaging :
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(); }
}
}
so from the looks of it it seems that i am able to decode the TIFF image (i am getting back the correct number of frames) but since i am receiving a BitmapFrame I used the function to convert it into a SoftImage. I used the BitmapEncoder this time to save the SoftImage as a PNG. This is where i am having my dificulties to use the correct manaer to save a SoftImage as a PNG file!
When you get SoftwareBitmap, you just need to call the OpenAsync method of the StorageFile which you want to save as .png to get a random access stream. Then use the BitmapEncoder.CreateAsync method to get an instance of the BitmapEncoder class for the specified stream and set the SoftwareBitmap in encoder. After that, call FlushAsync to cause the encoder to write the image data to the specified file. For more details about how to save a SoftwareBitmap to a png file, you can refer to this 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();
}
}
}