--- In exiv2@..., "Andreas Huggel" <ahuggel@...> wrote:
Hello Andreas,
> Looks like you've opened the bonnet and are working on the new
> engine. Cool! Don't hesitate to point out if you find anything
> funny there, this code has not seen much review yet.
So far so good! I've been able to convert the LibTIFF + Exiv2 glue
code, and tested it with images which at some point in the past gave
problems (not because of Exiv2). These (still) work fine with the new
code. Also where formerly I had to build an Iop IFD inside an Exif IFD
myself, the IFD chaining is now done automatically by Exiv2 (which
also means a Makernote IFD is included, great!).
> The new API entry point for such requirements is now TiffParser,
> in particular TiffParser::encode. It takes Metadata in Exiv2
> containers and creates a binary TIFF representation for
> it. However, currently that always results in a complete TIFF
> structure, including a TIFF header and an IFD0.
>
> During the implementation I vaguely considered the idea that this
> could at some point be enhanced to serialize only parts of the
> TIFF structure, starting from a particular IFD at a given base
> offset.
Yes, that would be quite a useful helper function.
> But definitely only after 0.18. In the meantime, you could
> try to hack along these lines:
>
> 1) The IFD0 offset should be easy to manipulate and will also determine
> all other offsets. You could pass your own TiffHeader, derived from
> TiffHeaderBase, to TiffParserWorker::encode to achieve 2 things: a)
> not write a TIFF header and b) set the offset (return value of
> TiffHeaderBase::write), adjusted in such a way that the Exif IFD offset
> becomes what you need it to be.
Wouldn't that return value indicate the offset to IFD0? (not to the
Exif IFD)
> 2) Not creating a complete TIFF structure starting from IFD0 is
> more tricky. In TiffParserWorker::encode, the root directory is
> passed to createFct as Tag::root, Group::none and then into the
> encoder in TiffEncoder::add, and TiffCreator::getPath explicitely
> uses Tag::root and Group::none. I'm not sure if these are the
> only places that need attention.
I had overlooked getPath. However letting that return chopped paths
meant that my Exif IFD apparently was treated as a root dir because it
would include IFD0 tags. (Probably related:) there's also a few
instances of code that explicitly check for "tiffPath.size()" (==1).
> It's probably easier to build a
> complete TIFF structure and then skip the header and IFD0 at the
> beginning of the blob and only use the rest.
In the end I settled on a solution quite like that (and this time
there was no need to change Exiv2). Written blobs now contain a
skippable 18 bytes header (2 for tag count, 12 bytes for IFD0 entry
containing an IFD offset, 4 (NULL-)bytes for the next IFD). Currently
I need 2 blobs: one for the Exif (and children) IFD, and another for
the GPS IFD. For each I create a new ExifData list from the original
ExifData containing only relevant tags (I decided to be conservative
about this). For Exif this means tags from Group::exif, Group::iop and
any tags belonging to makernote IFDs are included. I then pass this
through code similar to what's in TiffParserWorker::encode. However I
create the tree using Tag::next, Group::exif as params (in the Exif
IFD case) .
> Of course, if you implement this in the library, that would be
> perfect and I'd be happy to further discuss how the API for this
> should look like. But as always, that's more effort than just
> making it work for your own purposes.
I think what you mentioned (starting from a particular IFD at a given
offset) would be generic enough to be useful for others as well. I'm
not sure as yet how it would fit in the library (probably not as yet
more parameters to TiffParser[Worker]::encode ;) ). Perhaps an extra
function in TiffParser? As you mention it's probably better to look at
new things after 0.18 though.