I need to extract all the images in a multipage tiff.
I am reading documentation of image - Rust
Then the crate used in : tiff - Rust
But it seems that only the first page is always taken...
Maybe I can also use a pdf converter that convert tiff -> pdf. Then I can get the image from the pdf... But I do not find a tiff -> pdf crate in rust...
Is there someone that already use multipage tiff in rust ?
I try to use the following fuctions to get another image but i have always only the first one.
It seems that there is a bug for plannar config and my image has more that 1 images. I have checked that.
So i used : more_image to check if there are another one.
Then seek_to_image with number of the following page.
And next image.
But when i see read image fonction, it seems that they only take the first image for now...
As I understood, the library build using the iterator pattern. The read_image is always read the current. You need to advance the image using next_image before reading the image again (which you have done, right?).
The next_ifd implementation is one to focus if you can't read the next image:
fn next_ifd(&mut self) -> TiffResult<Directory> {
let Some(next_ifd) = self.next_ifd.take() else {
return Err(TiffError::FormatError(
TiffFormatError::ImageFileDirectoryNotFound,
));
};
let ifd = self.value_reader.read_directory(next_ifd)?;
// Ensure this walk does not get us into a cycle.
self.seen_ifds.insert_next(next_ifd, ifd.next())?;
// Extend the list of known IFD offsets in this chain, if needed.
if self.ifd_offsets.last().copied() == self.current_ifd {
self.ifd_offsets.push(next_ifd);
}
self.current_ifd = Some(next_ifd);
self.next_ifd = ifd.next();
Ok(ifd)
}
Where self.next_ifd = ifd.next(); means it is intentionally supporting multiple image. But we need to figure if any bug actually manifests.
There's also tinytiff crate as a wrapper to TinyTIFF C++ library, which has similar iterator pattern. The downside, you may need to install the C++ lib before compiling the crate.
Hi, maintainer here. You shouldn't really be using both next_image and seek_to_image. Both of these methods consume the IFD that they are referring to. So when you've just opened the image, these are equivalent:
tiff.next_image()?.map(|_img| ())
tiff.seek_to_image(0)
And if you call next_image after seek_to_image(n) you get the (n+1)'th image instead. Example with a two-IFD file:
v-- queried by more_images after new (true)
| v-- queried by more_images at IFD 0 (true)
| | v-- queried by more_images at IFD 1 (false)
tiff header | IFD 0 | IFD 1 |
^-- initial position after new
^-- position after seek_to_image(0)
^-- position after new + next_image
^-- position after seek_to_image(0) + next_image
^-- position after seek_to_image(1)
next_image is really more a utility for the common case where all directories are consumed in their natural order. But it does a bunch of additional computation that others want to avoid when iterating the chain of images. It sounds like you should not be using next_image at all, but rather you'll want to read read the current image with any of read, read_chunk, etc. Also note the comments on those regarding planar configurations which we don't really support. To get the data within planar configurations you may want to manually read tags instead (get_tag or read_directory_tags).
If it's really important and you can spare the time, we'd also appreciate design work and implementation to properly support planes but, fair warning, expect a few rounds of review and a volunteer driven schedule.
Soon I test again this, I will expose my work to help if possible. I need to finish something before but I am sure that I will need this in the few months so I will come back.