Exiv2 / exiv2

Image metadata library and tools
http://www.exiv2.org/
Other
911 stars 280 forks source link

Add support for Fuji RawImageCropTopLeft and RawImageCroppedSize #2165

Open AdamMainsTL opened 2 years ago

AdamMainsTL commented 2 years ago
Is your feature request related to a problem?

We have some Fuji files that contain crop data that is not retrieved by Exiv2. Using exiftool we can see the tags, but there is no similar data when iterating over Exiv2 values. Specifically, the data from exiftool is the following:

  + [Fuji directory with 12 entries]
  | 0)  RawImageFullSize = 4182 6384
  |     - Tag 0x0100 (4 bytes):
  |       2bf5a8: 10 56 18 f0                                     [.V..]
  | 1)  RawImageCropTopLeft = 13 6
  |     - Tag 0x0110 (4 bytes):
  |       2bf5b0: 00 0d 00 06                                     [....]
  | 2)  RawImageCroppedSize = 4160 6240
  |     - Tag 0x0111 (4 bytes):
  |       2bf5b8: 10 40 18 60   
... (snip)

Note: There are also many other tags missing, but I only care about the crop values at the moment.

Describe the solution you would like

Add the data so it is read by the library if possible. I have code I've tried below but it didn't work, so unsure how to continue.

Describe alternatives you have considered

I was going to try to make my own PR for this, but after looking at previous PRs for tags and having a go at it I was unable to get the values to show up on the problem image. I'm not quite sure what I'm doing wrong. Maybe makerTags isn't the right place to look?

Essentially I added this patch to fujimn_int.cpp:

        {0x0110, "RawImageCropTopLeft", N_("Raw Image Crop Top Left"),
                N_("Top left offset of crop"),
                fujiId, makerTags, unsignedShort, 2, printValue},
        {0x0111, "RawImageCroppedSize", N_("Raw Image Cropped Size"),
                N_("Final dimensions of cropped image"),
                fujiId, makerTags, unsignedShort, 2, printValue},
Additional context

You should be able to download the original RAF file from here: https://www.dpreview.com/sample-galleries/4841377113/fujifilm-x100v-sample-gallery/5054212967 (DSCF0640.RAF)

kmilos commented 2 years ago

This is because these are not regular MakerNote IFD tags in MakerNotes directory with 64 entries, but some fields in an unknown RAF binary structure somewhere Fuji directory with 12 entries (location TBD):

https://exiftool.org/TagNames/FujiFilm.html

kmilos commented 2 years ago

It is inside this "CFA" block after the preview we don't do anything with yet:

$ exiv2 -pS Fujifilm\ -\ X100V\ -\ 14bit\ compressed\ \(3_2\).RAF
STRUCTURE OF RAF FILE: Fujifilm - X100V - 14bit compressed (3_2).RAF
  Address |   Length | Payload
        0 |       16 |       magic : FUJIFILMCCD-RAW
       16 |        4 |       data1 : 0201
       20 |        8 |       data2 : FF159504
       28 |       32 |      camera : X100V
       60 |        4 |     version : 0100
       64 |       20 |     unknown : ...................
       84 |        4 | JPEG Offset : 148
       88 |        4 | JPEG Length : 5618448
       92 |        4 |  CFA Offset : 5619104
       96 |        4 |  CFA Length : 22112
      100 |        4 | TIFF Offset : 5641216
      104 |        4 | TIFF Length : 26654144
      148 |  5618448 |        JPEG : ......Exif..II*
  5619104 |    22112 |         CFA : .........V......
  5641216 | 26654144 |        TIFF : II*............

The format seems to be a straightforward serialization:

Big endian assumed 4 bytes of entry count? Then for each entry: 2 bytes for tag ID, 2 bytes for byte count, then the payload

A new parser would need to be added inside https://github.com/Exiv2/exiv2/blob/main/src/rafimage.cpp (see RafImage::printStructure for the offset of this CFA block, and add parser in RafImage::readMetadata)

See also https://libopenraw.freedesktop.org/formats/raf/

AdamMainsTL commented 2 years ago

Thanks for the information. Looking at the code it seems pretty straightforward. As far as I can see:

The only thing I don't know how to do at the moment would be to get that information into exifData_ in a "correct" way. Since this is a defined structure, would it be acceptable to basically do:

exifData["Exif.FujiRAF.RawImageFullSize"] = ...;
exifData["Exif.FujiRAF.RawImageCropTopLeft"] = ...;
// etc

Or is there some other way the project prefers to do this?

kmilos commented 2 years ago

That's the general idea, yes, except that you wouldn't be assigning these explicitly, but just let the parser create those fields as it traverses that buffer and define a corresponding mapping table.

You might be even able to get away with the existing TiffParser - take a look at e.g. some Canon examples that are similarly some binary blobs in the Canon MakerNote but get parsed out as new, independent groups like "movie info" in CanonMv group.

You could potentially even add directly to the existing Exif.Fujifilm group - currently both the data from MakerNote which comes from the Exif IFD embedded in the JPEG preview, and the regular TIFF tags that are Fujifilm specific coming from the actual raw IFD (labeled TIFF in the -pS output above), or you could create a new group indeed, might even be a safer place to start (and easy to change the label/group later)...

kmilos commented 2 years ago

Sorry, CanonMv was a bad example (actually not hooked up at all!), try to follow CanonCf instead...