2010.05.11 16:59 "[Tiff] Combining multiple G4 images into a single output image", by Richard Nolde
Thank you Richard.
Yes, i want to combine several images of different size onto a bigger one, so pointing me to tiffcrop was a good idea. After getting a bit deeper into libtiff i guess it would be ok to read (or create) the background image (i call it "the pasteboard") into memory, so it does not matter if the TIFF organization was tiled or striped. Then read one image after the other an paste the lines at the location given. Therefore i need to access the image raster pixel in memory, calc the offset and overwrite the background image data with the read data from each image. The order i read the images is equal to their layer in the
pasteboard. After that i can write out the pasteboard image as a new file.
Now, is it ok (in question of speed) to use TIFFReadScanline or should I use some lower level functions?
If you are going to make a special purpose utility and you are sure that you will never need to access data that is compressed in ways that require access to multiple scanlines at once, the TIFFReadScanline interface should work fine. My first version of tiffcrop used that interface but I changed to a strip oriented reading approach so that I could handle YCbCr compressed data. From what I remember, libtiff is going to read a whole strip anyway and then hand off a scanline at a time as your read from the strip even if you call TIFFReadScanline.
Depending on the size of your final image, you may have to allocate a working buffer that is only as large as a few scanlines, ideally the size of a full strip in the output image rather than creating the full output image in memory before writing any of it out. This assumes all your input images will be pasted into the output buffer from left to right and the final image will be N * the width of the input images but only 1 * the height of the input image. If you have multiple rows and columns of subimages in the output image, you have to calculate the width of the widest subset and pad every scanline to match.
My approach in tiffcrop handles tiled or strip oriented images and always loads them into a single memory block as interleaved RGB/Grayscale/Bilevel samples at depths from 1 to 32 bits per sample without expanding them to a larger sample size for the intermediate processing. After manipulating the data, the image can be written out as tiles or strips regardless of the input formats.
The difference between what you want to do and what tiffcrop does involves your use of multiple input files that are opened concurrently rather than sequentially. It might be possible to add a command line option and an alternative path through the code for opening all the files at once with additional data structures to handle access to all of the TIFF* handles. Most of the code that you need has a counterpart in tiffcrop that you could adapt to deal with multiple input files by keeping track of the read offsets into each input file and updating the write offset after each read. Reading non-byte-aligned samples is required to crop or combine images that are not a multiple of 8 bits per scanline but you will have to track the byte AND bit offsets across multiple input images when you paste the input scanlines into your output buffer. I only have to deal with that within a single source image. If you are reading a scanline at a time, it should not be too hard for Bilevel data.
I am thinking about some code to speed up the masking operation but haven't written anything yet.
Regarding memory mapped files. There may be greater benefit for memory mapping in cases where an image is being rotated since access to the source data will require multiple passes through a given scanline.