[
https://issues.apache.org/jira/browse/TIKA-4980?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Dominik Schmidt updated TIKA-4980:
----------------------------------
Description:
RawTiffParser (TIKA-4851, TIKA-4861) extracts the camera-generated JPEG
previews of
TIFF-based raw formats: Nikon NEF/NRW, Sony ARW/SRF/SR2, Pentax PEF/PTX,
Samsung SRW,
Adobe DNG and Canon CR2. Five further TIFF containers yield nothing, each for a
reason of
its own, although every one of them carries a usable preview.
h3. 1. Olympus ORF
Detected correctly as image/x-raw-olympus by the magic entry in
tika-mimetypes.xml, but no
parser declares the type, and RawTiffParser would refuse the file anyway: an
ORF carries
its own magic number (0x4F52 for "IIRO" and "MMOR", 0x5352 for "IIRS") where a
TIFF has
42, so locateJpegPreviews() throws "bad TIFF magic number".
The previews are not in the IFD chain either. IFD0 holds the sensor image; the
previews
hang in the MakerNote, whose offsets count from its own first byte:
{code}
Exif IFD (0x8769) -> MakerNote (0x927C), header "OLYMPUS\0" + its own byte
order marker
0x0100 camera thumbnail (UNDEFINED, count = length)
0x2020 CameraSettings sub-IFD
0x0101/0x0102 PreviewImageStart / PreviewImageLength
{code}
The byte order marker inside the MakerNote is the MakerNote's own and does not
have to
repeat the file's.
h3. 2. Panasonic RW2
Detected correctly as image/x-raw-panasonic, same two blockers: no parser
declares the
type, and the magic number is 0x0055 ("IIU\0"). The preview sits in the private
tag 0x002E
(JpgFromRaw), while the standard strip tags are placeholders (StripOffsets =
0xFFFFFFFF,
StripByteCounts = 0), so a reader that trusts them finds a strip of no length
where the
preview should be.
h3. 3. Epson ERF
Not recognized as a raw at all. RawTiffDetector has no Epson entry, so the file
is detected
as image/tiff and handled by TiffParser. Declaring the type does not help
either, because
image/x-raw-epson has no sub-class-of in tika-mimetypes.xml: MimeTypes only
accepts a
declared type that is a descendant of what it detected, so the hint is dropped:
{code}
hint image/x-raw-epson -> detected image/tiff (hint discarded)
hint image/x-raw-adobe -> detected image/x-raw-adobe (hint accepted: it is a
descendant)
{code}
The raw IFD of an R-D1 file has Compression 32769 (Epson's own code, as
ExifTool lists it)
and PhotometricInterpretation 32803 (CFA), and IFD0 carries Make "SEIKO EPSON
CORP.",
which is what RawTiffDetector already keys on for the other vendors.
The preview is harder to see than in the other formats, and a search for the
JPEG SOI
marker misses it twice over. There is no JPEG in any IFD of an ERF: the preview
is named in
the MakerNote, which ExifTool's Olympus.pm documents as tag 0x0280
(PreviewImage, "found in
ERF and JPG images from some Epson models"), its offset counts from the start
of the file
rather than from the MakerNote, and its first byte is not the JPEG's. All three
R-D1
generations write 0xEE there, where the SOI begins; the rest is a regular
baseline JPEG that
ends with FFD9. Put the byte back and it decodes:
{code}
MakerNote @708, 586 bytes, header "EPSON\0" + version, its IFD at +8, file byte
order
tag 0x0280 BYTE count=55150 value=9903844 -> ee d8 ff db ... -> JPEG
640x424
{code}
ExifTool restores that byte as well, without documenting it: {{exiftool -b
-PreviewImage}}
returns the same 55150 bytes, beginning with FFD8.
h3. 4. Kodak KDC
A plain little-endian TIFF that points at its preview with the standard tags,
which
RawTiffParser already reads for CR2 and NEF:
{code}
100_3710.KDC (Kodak P880)
IFD0 Compression 7 (JPEG), PhotometricInterpretation 6 (YCbCr)
JPEGInterchangeFormat 12150832, JPEGInterchangeFormatLength 1677970
Tika today: image/tiff, no embedded resources
{code}
Nothing has to be read differently here; the type is simply not connected to
the parser.
Handing the same bytes to it under a type it is bound to shows what is there:
{code}
as 100_3710.KDC -> image/tiff no previews
as probe.pef -> image/x-raw-pentax THUMBNAIL 3264x2448, 1677970 bytes
{code}
Detection by content is a separate matter and stays unsolved: the SubIFD has
Compression 1
and neither PhotometricInterpretation nor BitsPerSample, so none of
RawTiffDetector's raw
markers fire and a KDC without a file name stays image/tiff.
h3. 5. Leaf MOS
A big-endian TIFF whose IFD0 has Compression 99, which is no TIFF value, and no
preview
tags of the standard kind. The preview sits in the Leaf data block, tag 0x8606,
a chain of
named blocks:
{code}
"PKTS" + 4-byte version + 40-byte NUL-padded name + 4-byte length + payload
JPEG_preview_info 12 bytes "8 332 244 1"
JPEG_preview_data 24132 bytes -> a complete baseline JPEG, 332x244
{code}
The bytes decode as they are stored, with no patching. Note that tag 0x8606 is
typed ASCII,
so a reader that takes it for a string damages what it holds: {{exiftool -b
-PreviewImage}}
returns 24132 bytes of which 136 differ from the file, every 0x0A turned into
0x20, and the
result no longer decodes. Reading the block's bytes gives the JPEG unharmed.
h3. Proposed fix
* RawTiffDetector: Epson by compression code 32769 and by Make "SEIKO
EPSON"/"EPSON".
* tika-mimetypes.xml: sub-class-of image/tiff for image/x-raw-epson,
image/x-raw-kodak and
image/x-raw-leaf, so the types are TIFFs for the registry, a declared type
can refine to
them, and the parser lookup has something to fall back on.
* RawTiffParser: accept the ORF and RW2 magic numbers as classic TIFF layouts;
read the
Panasonic JpgFromRaw tag ahead of the standard tags, which an RW2 fills with
placeholders;
follow the Exif IFD of a classic TIFF to its MakerNote and read it by the
name it begins
with, the Olympus one in the byte order its own marker names and the Epson
one at the
offset it gives from the start of the file, restoring the SOI as the bytes
are handed on;
read the Leaf data block for its JPEG_preview_data; and add
image/x-raw-olympus,
image/x-raw-panasonic, image/x-raw-epson, image/x-raw-kodak and
image/x-raw-leaf to the
supported types.
* Reading previews from three more places reshapes the walk TIKA-4851 added:
the candidates
of an IFD are collected before they are checked, and the per-file budget
moves into a
collector, so a preview from a MakerNote or a vendor block passes the same
limits as one
from the IFD chain.
* The existing rule picks the resource type: the largest preview by JPEG length
becomes the
THUMBNAIL, the smaller ones INLINE images.
Verified against CC0 samples from raw.pixls.us:
{code}
P3180165.ORF (E-M10) image/x-raw-olympus THUMBNAIL 3200x2400
INLINE 160x120
_7061961_copy.ORF (E-5) image/x-raw-olympus THUMBNAIL 3200x2400
INLINE 160x120
RAW_PANASONIC_DMC-GX-7_11 image/x-raw-panasonic THUMBNAIL 1920x1920
Lumix_DMC-LX100_1.RW2 image/x-raw-panasonic THUMBNAIL 1920x1440
epson-r-d1.erf image/x-raw-epson THUMBNAIL 640x424
55150 bytes
epson-r-d1s.erf image/x-raw-epson THUMBNAIL 640x424
189141 bytes
epson-r-d1x.erf image/x-raw-epson THUMBNAIL 640x424
82817 bytes
100_3710.KDC (P880) image/x-raw-kodak THUMBNAIL 3264x2448
1677970 bytes
L_003172.mos (Aptus 22) image/x-raw-leaf THUMBNAIL 332x244
24132 bytes
{code}
Every one of those previews is byte for byte what the file holds. Make, model
and dimensions
are extracted for all of them, and none records a parse exception. The tests
use hand-built
files in the style of the existing raw test documents, each under a kilobyte.
h3. Not covered
Canon CRW (CIFF), Sigma X3F (FOVb) and Minolta MRW keep their previews in
containers that
are not TIFF; each needs a reader of its own. The TIFF raws that carry no JPEG
whatsoever
(Hasselblad 3FR and FFF, Kodak DCR, Sinar STI, Kodak DC120) have nothing to
extract and keep
answering with metadata only. Also out: the older Olympus "OLYMP\0" MakerNote
header, Fuji
RAF (not a TIFF container), and the vendor-level mime entries that carry no
sub-class-of
because they span several containers (image/x-raw-canon covers CRW, CR2 and
CR3).
was:
RawTiffParser (TIKA-4851, TIKA-4861) extracts the camera-generated JPEG
previews of
TIFF-based raw formats: Nikon NEF/NRW, Sony ARW/SRF/SR2, Pentax PEF/PTX,
Samsung SRW,
Adobe DNG and Canon CR2. Three further TIFF-based formats yield nothing, each
for a
different reason, although all three carry a preview.
h3. 1. Olympus ORF
Detected correctly as image/x-raw-olympus by the magic entry in
tika-mimetypes.xml, but
no parser declares the type, and RawTiffParser would refuse the file anyway: an
ORF
carries its own magic number (0x4F52 for "IIRO" and "MMOR", 0x5352 for "IIRS")
where a
TIFF has 42, so locateJpegPreviews() throws "bad TIFF magic number".
The previews are not in the IFD chain either. IFD0 holds the sensor image; the
previews
hang in the MakerNote, whose offsets count from its own first byte:
{code}
Exif IFD (0x8769) -> MakerNote (0x927C), header "OLYMPUS\0" + its own byte
order marker
0x0100 camera thumbnail (UNDEFINED, count = length)
0x2020 CameraSettings sub-IFD
0x0101/0x0102 PreviewImageStart / PreviewImageLength
{code}
The byte order marker inside the MakerNote is the MakerNote's own and does not
have to
repeat the file's.
h3. 2. Panasonic RW2
Detected correctly as image/x-raw-panasonic, same two blockers: no parser
declares the
type, and the magic number is 0x0055 ("IIU\0"). The preview sits in the private
tag
0x002E (JpgFromRaw) of the IFD, while the standard strip tags are placeholders
(StripOffsets = 0xFFFFFFFF, StripByteCounts = 0), so a reader that trusts them
finds a
strip of no length where the preview should be.
h3. 3. Epson ERF
Not recognized as a raw at all. RawTiffDetector has no Epson entry, so the file
is
detected as image/tiff and handled by TiffParser. Declaring the type does not
help
either, because image/x-raw-epson has no sub-class-of in tika-mimetypes.xml:
MimeTypes
only accepts a declared type that is a descendant of what it detected, so the
hint is
dropped. Measured against an Epson R-D1 file:
{code}
hint image/x-raw-epson -> detected image/tiff (hint discarded)
hint image/x-raw-adobe -> detected image/x-raw-adobe (hint accepted: it is a
descendant)
{code}
The raw IFD of that file has Compression 32769 (Epson's own code, as ExifTool
lists it)
and PhotometricInterpretation 32803 (CFA), and IFD0 carries Make "SEIKO EPSON
CORP.",
which is what RawTiffDetector already keys on for the other vendors.
The preview is harder to see than in the other two formats, and a search for
the JPEG
SOI marker misses it twice over. There is no JPEG in any IFD of an ERF: the
preview is
named in the MakerNote, which ExifTool's Olympus.pm documents as tag 0x0280
(PreviewImage, "found in ERF and JPG images from some Epson models"), its
offset counts
from the start of the file rather than from the MakerNote, and its first byte
is not the
JPEG's. All three R-D1 generations write 0xEE there, where the SOI begins; the
rest is a
regular baseline JPEG that ends with FFD9. Put the byte back and it decodes:
{code}
MakerNote @708, 586 bytes, header "EPSON\0" + version, its IFD at +8, file byte
order
tag 0x0280 BYTE count=55150 value=9903844 -> ee d8 ff db ... -> JPEG
640x424
{code}
h3. Proposed fix
* RawTiffDetector: Epson by compression code 32769 and by Make "SEIKO
EPSON"/"EPSON".
* tika-mimetypes.xml: sub-class-of image/tiff for image/x-raw-epson, so the
type is a
TIFF for the registry, a declared type can refine to it, and the parser
lookup has
something to fall back on.
* RawTiffParser: accept the ORF and RW2 magic numbers as classic TIFF layouts;
read the
Panasonic JpgFromRaw tag before the strip tags it writes placeholders into;
read the
MakerNote for both vendors, the Olympus one in the byte order its own marker
names and
the Epson one at the offset it gives from the start of the file, restoring
the SOI as
the bytes are handed on; add image/x-raw-olympus, image/x-raw-panasonic and
image/x-raw-epson to the supported types.
* The existing rule picks the resource type: the largest preview by JPEG length
becomes
the THUMBNAIL, the smaller ones INLINE images.
Verified against CC0 samples from raw.pixls.us, which are all the ORF, RW2 and
ERF
samples it has for these cameras:
{code}
P3180165.ORF (E-M10) image/x-raw-olympus THUMBNAIL 3200x2400
INLINE 160x120
_7061961_copy.ORF (E-5) image/x-raw-olympus THUMBNAIL 3200x2400
INLINE 160x120
RAW_PANASONIC_DMC-GX-7_11 image/x-raw-panasonic THUMBNAIL 1920x1920
Lumix_DMC-LX100_1.RW2 image/x-raw-panasonic THUMBNAIL 1920x1440
epson-r-d1.erf image/x-raw-epson THUMBNAIL 640x424
55150 bytes
epson-r-d1s.erf image/x-raw-epson THUMBNAIL 640x424
189141 bytes
epson-r-d1x.erf image/x-raw-epson THUMBNAIL 640x424
82817 bytes
{code}
Make, model and dimensions are extracted for all of them, and none records a
parse
exception. The tests use hand-built files in the style of the existing raw test
documents, each under a kilobyte.
Not covered: the older Olympus "OLYMP\0" MakerNote header, Fuji RAF (not a TIFF
container), and the vendor-level mime entries that exist without a sub-class-of
because
they span several containers (image/x-raw-canon covers CRW, CR2 and CR3).
> Extract previews from Olympus ORF, Panasonic RW2 and Epson ERF
> --------------------------------------------------------------
>
> Key: TIKA-4980
> URL: https://issues.apache.org/jira/browse/TIKA-4980
> Project: Tika
> Issue Type: Improvement
> Components: parser
> Reporter: Dominik Schmidt
> Priority: Major
>
> RawTiffParser (TIKA-4851, TIKA-4861) extracts the camera-generated JPEG
> previews of
> TIFF-based raw formats: Nikon NEF/NRW, Sony ARW/SRF/SR2, Pentax PEF/PTX,
> Samsung SRW,
> Adobe DNG and Canon CR2. Five further TIFF containers yield nothing, each for
> a reason of
> its own, although every one of them carries a usable preview.
> h3. 1. Olympus ORF
> Detected correctly as image/x-raw-olympus by the magic entry in
> tika-mimetypes.xml, but no
> parser declares the type, and RawTiffParser would refuse the file anyway: an
> ORF carries
> its own magic number (0x4F52 for "IIRO" and "MMOR", 0x5352 for "IIRS") where
> a TIFF has
> 42, so locateJpegPreviews() throws "bad TIFF magic number".
> The previews are not in the IFD chain either. IFD0 holds the sensor image;
> the previews
> hang in the MakerNote, whose offsets count from its own first byte:
> {code}
> Exif IFD (0x8769) -> MakerNote (0x927C), header "OLYMPUS\0" + its own byte
> order marker
> 0x0100 camera thumbnail (UNDEFINED, count = length)
> 0x2020 CameraSettings sub-IFD
> 0x0101/0x0102 PreviewImageStart / PreviewImageLength
> {code}
> The byte order marker inside the MakerNote is the MakerNote's own and does
> not have to
> repeat the file's.
> h3. 2. Panasonic RW2
> Detected correctly as image/x-raw-panasonic, same two blockers: no parser
> declares the
> type, and the magic number is 0x0055 ("IIU\0"). The preview sits in the
> private tag 0x002E
> (JpgFromRaw), while the standard strip tags are placeholders (StripOffsets =
> 0xFFFFFFFF,
> StripByteCounts = 0), so a reader that trusts them finds a strip of no length
> where the
> preview should be.
> h3. 3. Epson ERF
> Not recognized as a raw at all. RawTiffDetector has no Epson entry, so the
> file is detected
> as image/tiff and handled by TiffParser. Declaring the type does not help
> either, because
> image/x-raw-epson has no sub-class-of in tika-mimetypes.xml: MimeTypes only
> accepts a
> declared type that is a descendant of what it detected, so the hint is
> dropped:
> {code}
> hint image/x-raw-epson -> detected image/tiff (hint discarded)
> hint image/x-raw-adobe -> detected image/x-raw-adobe (hint accepted: it is a
> descendant)
> {code}
> The raw IFD of an R-D1 file has Compression 32769 (Epson's own code, as
> ExifTool lists it)
> and PhotometricInterpretation 32803 (CFA), and IFD0 carries Make "SEIKO EPSON
> CORP.",
> which is what RawTiffDetector already keys on for the other vendors.
> The preview is harder to see than in the other formats, and a search for the
> JPEG SOI
> marker misses it twice over. There is no JPEG in any IFD of an ERF: the
> preview is named in
> the MakerNote, which ExifTool's Olympus.pm documents as tag 0x0280
> (PreviewImage, "found in
> ERF and JPG images from some Epson models"), its offset counts from the start
> of the file
> rather than from the MakerNote, and its first byte is not the JPEG's. All
> three R-D1
> generations write 0xEE there, where the SOI begins; the rest is a regular
> baseline JPEG that
> ends with FFD9. Put the byte back and it decodes:
> {code}
> MakerNote @708, 586 bytes, header "EPSON\0" + version, its IFD at +8, file
> byte order
> tag 0x0280 BYTE count=55150 value=9903844 -> ee d8 ff db ... -> JPEG
> 640x424
> {code}
> ExifTool restores that byte as well, without documenting it: {{exiftool -b
> -PreviewImage}}
> returns the same 55150 bytes, beginning with FFD8.
> h3. 4. Kodak KDC
> A plain little-endian TIFF that points at its preview with the standard tags,
> which
> RawTiffParser already reads for CR2 and NEF:
> {code}
> 100_3710.KDC (Kodak P880)
> IFD0 Compression 7 (JPEG), PhotometricInterpretation 6 (YCbCr)
> JPEGInterchangeFormat 12150832, JPEGInterchangeFormatLength 1677970
> Tika today: image/tiff, no embedded resources
> {code}
> Nothing has to be read differently here; the type is simply not connected to
> the parser.
> Handing the same bytes to it under a type it is bound to shows what is there:
> {code}
> as 100_3710.KDC -> image/tiff no previews
> as probe.pef -> image/x-raw-pentax THUMBNAIL 3264x2448, 1677970 bytes
> {code}
> Detection by content is a separate matter and stays unsolved: the SubIFD has
> Compression 1
> and neither PhotometricInterpretation nor BitsPerSample, so none of
> RawTiffDetector's raw
> markers fire and a KDC without a file name stays image/tiff.
> h3. 5. Leaf MOS
> A big-endian TIFF whose IFD0 has Compression 99, which is no TIFF value, and
> no preview
> tags of the standard kind. The preview sits in the Leaf data block, tag
> 0x8606, a chain of
> named blocks:
> {code}
> "PKTS" + 4-byte version + 40-byte NUL-padded name + 4-byte length + payload
> JPEG_preview_info 12 bytes "8 332 244 1"
> JPEG_preview_data 24132 bytes -> a complete baseline JPEG, 332x244
> {code}
> The bytes decode as they are stored, with no patching. Note that tag 0x8606
> is typed ASCII,
> so a reader that takes it for a string damages what it holds: {{exiftool -b
> -PreviewImage}}
> returns 24132 bytes of which 136 differ from the file, every 0x0A turned into
> 0x20, and the
> result no longer decodes. Reading the block's bytes gives the JPEG unharmed.
> h3. Proposed fix
> * RawTiffDetector: Epson by compression code 32769 and by Make "SEIKO
> EPSON"/"EPSON".
> * tika-mimetypes.xml: sub-class-of image/tiff for image/x-raw-epson,
> image/x-raw-kodak and
> image/x-raw-leaf, so the types are TIFFs for the registry, a declared type
> can refine to
> them, and the parser lookup has something to fall back on.
> * RawTiffParser: accept the ORF and RW2 magic numbers as classic TIFF
> layouts; read the
> Panasonic JpgFromRaw tag ahead of the standard tags, which an RW2 fills
> with placeholders;
> follow the Exif IFD of a classic TIFF to its MakerNote and read it by the
> name it begins
> with, the Olympus one in the byte order its own marker names and the Epson
> one at the
> offset it gives from the start of the file, restoring the SOI as the bytes
> are handed on;
> read the Leaf data block for its JPEG_preview_data; and add
> image/x-raw-olympus,
> image/x-raw-panasonic, image/x-raw-epson, image/x-raw-kodak and
> image/x-raw-leaf to the
> supported types.
> * Reading previews from three more places reshapes the walk TIKA-4851 added:
> the candidates
> of an IFD are collected before they are checked, and the per-file budget
> moves into a
> collector, so a preview from a MakerNote or a vendor block passes the same
> limits as one
> from the IFD chain.
> * The existing rule picks the resource type: the largest preview by JPEG
> length becomes the
> THUMBNAIL, the smaller ones INLINE images.
> Verified against CC0 samples from raw.pixls.us:
> {code}
> P3180165.ORF (E-M10) image/x-raw-olympus THUMBNAIL 3200x2400
> INLINE 160x120
> _7061961_copy.ORF (E-5) image/x-raw-olympus THUMBNAIL 3200x2400
> INLINE 160x120
> RAW_PANASONIC_DMC-GX-7_11 image/x-raw-panasonic THUMBNAIL 1920x1920
> Lumix_DMC-LX100_1.RW2 image/x-raw-panasonic THUMBNAIL 1920x1440
> epson-r-d1.erf image/x-raw-epson THUMBNAIL 640x424
> 55150 bytes
> epson-r-d1s.erf image/x-raw-epson THUMBNAIL 640x424
> 189141 bytes
> epson-r-d1x.erf image/x-raw-epson THUMBNAIL 640x424
> 82817 bytes
> 100_3710.KDC (P880) image/x-raw-kodak THUMBNAIL 3264x2448
> 1677970 bytes
> L_003172.mos (Aptus 22) image/x-raw-leaf THUMBNAIL 332x244
> 24132 bytes
> {code}
> Every one of those previews is byte for byte what the file holds. Make, model
> and dimensions
> are extracted for all of them, and none records a parse exception. The tests
> use hand-built
> files in the style of the existing raw test documents, each under a kilobyte.
> h3. Not covered
> Canon CRW (CIFF), Sigma X3F (FOVb) and Minolta MRW keep their previews in
> containers that
> are not TIFF; each needs a reader of its own. The TIFF raws that carry no
> JPEG whatsoever
> (Hasselblad 3FR and FFF, Kodak DCR, Sinar STI, Kodak DC120) have nothing to
> extract and keep
> answering with metadata only. Also out: the older Olympus "OLYMP\0" MakerNote
> header, Fuji
> RAF (not a TIFF container), and the vendor-level mime entries that carry no
> sub-class-of
> because they span several containers (image/x-raw-canon covers CRW, CR2 and
> CR3).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)