Reputation: 279
I'm trying to use LibTiff.Net to split a multipage TIFF image into single page TIFF images.
I am building a TIFF splitting intermediary between two systems. I will receive the multipage TIFF image as a stream and then split it up into individual page TIFF image files and return them as a list of byte arrays.
I make a call to a web service that returns the multipage TIFF image as a stream. I need to extract each page as a separate TIFF image to return them as a list of byte arrays. I've seen the TiffCP utility that can split a multipage image on disk into separate TIFF image files on disk. I don't want to write anything to disk during this operation if I can avoid it.
I also don't want to decode any of the image content of the input image because that would waste processing time.
Is this possible with LibTiff.Net?
UPDATED @bobrovsky - thank you for your suggestion.
Here is what I've tried. I took the Copier class out of the source code for TiffCP to use it in my project with zero edits. The code below is how I'm using it. When this code completes execution the MemoryStream objects that should have the entire single page TIFF image inside them are all exactly 1,282 bytes in size. It seems like I'm missing a function call that forces the TIFF image data to be written to the underlying store (in this case the MemoryStream). I've included a call to Flush() to try fixing this issue but it had no affect. Does anyone know what I'm missing?
using (memoryStream)
{
memoryStream.Position = 0;
using (Tiff image = Tiff.ClientOpen("iqdoc", "r", memoryStream, new TiffStream()))
{
int totalPages = image.NumberOfDirectories();
for (int i = 0; i < totalPages; i++)
{
image.SetDirectory((short)i);
using (var ms = new MemoryStream())
using (Tiff page = Tiff.ClientOpen("page", "w", ms, new TiffStream()))
{
var c = new Copier();
c.m_compression = c.m_defcompression; // THIS WAS MISSING
if (!c.Copy(image, page) || !page.WriteDirectory())
throw new ApplicationException("Failed to extract page from document for presentation.");
FieldValue[] field = image.GetField(TiffTag.IMAGEWIDTH);
int width = field[0].ToInt();
field = image.GetField(TiffTag.IMAGELENGTH);
int height = field[0].ToInt();
page.Flush();
pages.Add(new
{
Height = height,
Width = width,
PageBytes = Convert.ToBase64String(ms.ToArray()),
});
c = null;
}
}
}
}
Thanks!
Upvotes: 2
Views: 2341
Reputation: 14236
Yes, it's possible. TiffCP does this.
You can take TiffCP code and adapt it to your needs (change the way it stores output).
You can also come up with other ideas and implement one of those.
You might not get a complete working solution in an answer on this site.
EDIT:
Your code is mostly ok, but you should only access bytes of the memory stream after Tiff
has finished writing to it.
Unfortunately, Tiff
closes memory stream in it's Dispose
and Close
methods. You might try two approaches to overcome the issue:
Tiff.WriteDirectory
before accessing bytes in the memory stream. This should be ok, but you might get an incomplete TIFF in the stream.System.IO.MemoryStream
) which overloads Close
method with an empty implementation and use this stream instead of MemoryStream
. Access bytes in this stream after Tiff
is disposed.Upvotes: 1