I couldn't find a good way to parallelize the creation process. Attempting to build an Image from a MemoryStream that was built outside of the Parallel.ForEach only threw a general GDI+ error.
const string tifPath = "14 Page.TIFF";
//extract tiff
var imageFile = Image.FromFile(tifPath);
var imagePageCount = imageFile.GetFrameCount(FrameDimension.Page);
var imageStreams = new Bitmap[imagePageCount];
var rangePartioner = Partitioner.Create(0, imagePageCount);
var frameDimension = new FrameDimension(imageFile.FrameDimensionsList[0]);
imageFile.Dispose();
Parallel.ForEach(rangePartioner, (range, loopState) =>
{
for (var i = range.Item1; i < range.Item2; i++)
{
using (var imageFile2 = Image.FromFile(tifPath))
{
imageFile2.SelectActiveFrame(frameDimension, i);
imageStreams[i] = new Bitmap(imageFile2);
}
}
});
//build tiff
var encoder = Encoder.SaveFlag;
var encoderInfo = ImageCodecInfo.GetImageEncoders().First(i => i.MimeType == "image/tiff");
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(encoder, (long) EncoderValue.MultiFrame);
var stream2 = new MemoryStream();
using(var firstImage = imageStreams[0])
{
firstImage.Save(stream2, encoderInfo, encoderParameters);
encoderParameters.Param[0] = new EncoderParameter(encoder, (long) EncoderValue.FrameDimensionPage);
for (var i = 1; i < imageStreams.Length; i++)
{
firstImage.SaveAdd(imageStreams[i], encoderParameters);
}
encoderParameters.Param[0] = new EncoderParameter(encoder, (long) EncoderValue.Flush);
firstImage.SaveAdd(encoderParameters);
}
This shaved off about 2 seconds. Still hunting for a good way to handle the second half.
EDIT: Added suggested changes of only converting the image and not saving it to a stream. EDIT: Added remainder of fixes.