[ 
https://issues.apache.org/jira/browse/TIKA-4824?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18105570#comment-18105570
 ] 

ASF GitHub Bot commented on TIKA-4824:
--------------------------------------

Copilot commented on code in PR #3037:
URL: https://github.com/apache/tika/pull/3037#discussion_r3803499821


##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/RawTiffParser.java:
##########
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.parser.image;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.annotation.TikaComponent;
+import org.apache.tika.config.ConfigDeserializer;
+import org.apache.tika.config.JsonConfig;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.extractor.EmbeddedDocumentExtractor;
+import org.apache.tika.extractor.EmbeddedDocumentUtil;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.HttpHeaders;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for TIFF-based camera raw images: Nikon NEF/NRW, Sony ARW/SRF/SR2,
+ * Pentax PEF/PTX, Adobe DNG and Canon CR2.
+ * <p>
+ * These formats are TIFF containers: metadata extraction is inherited from
+ * {@link TiffParser}. In addition, this parser extracts the camera-generated
+ * JPEG preview images embedded in the raw file and hands them to the
+ * {@link EmbeddedDocumentExtractor}. Previews are referenced from the IFD
+ * chain or from SubIFDs, either via the JPEGInterchangeFormat/
+ * JPEGInterchangeFormatLength tags or as a single JPEG-compressed strip
+ * (DNG, CR2). Strips holding raw sensor data are also JPEG-encoded in some
+ * formats (lossless JPEG in CR2 and DNG), so strip candidates are only
+ * accepted for displayable images: PhotometricInterpretation RGB or YCbCr,
+ * or 8 bits per sample when PhotometricInterpretation is absent (CR2).
+ */
+@TikaComponent
+public class RawTiffParser extends TiffParser {
+
+    /**
+     * Serial version UID
+     */
+    private static final long serialVersionUID = 5385105345533384662L;
+
+    private static final Set<MediaType> SUPPORTED_TYPES = 
Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(
+                    MediaType.image("x-raw-nikon"),
+                    MediaType.image("x-raw-sony"),
+                    MediaType.image("x-raw-pentax"),
+                    MediaType.image("x-raw-adobe"),
+                    MediaType.image("x-canon-cr2"))));
+
+    private static final String JPEG_MIME = "image/jpeg";
+
+    private static final int TAG_BITS_PER_SAMPLE = 0x0102;
+    private static final int TAG_COMPRESSION = 0x0103;
+    private static final int TAG_PHOTOMETRIC_INTERPRETATION = 0x0106;
+    private static final int TAG_STRIP_OFFSETS = 0x0111;
+    private static final int TAG_STRIP_BYTE_COUNTS = 0x0117;
+    private static final int TAG_SUB_IFDS = 0x014A;
+    private static final int TAG_JPEG_INTERCHANGE_FORMAT = 0x0201;
+    private static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x0202;
+
+    private static final int COMPRESSION_OLD_JPEG = 6;
+    private static final int COMPRESSION_JPEG = 7;
+    private static final int PHOTOMETRIC_RGB = 2;
+    private static final int PHOTOMETRIC_YCBCR = 6;
+
+    private static final int MAX_IFDS = 32;
+    private static final int MAX_ENTRIES_PER_IFD = 1024;
+    //previews are camera-generated JPEGs, tens of MB is already generous
+    private static final long MAX_PREVIEW_LENGTH_BYTES = 100 * 1024 * 1024;
+
+    private RawTiffParserConfig defaultConfig = new RawTiffParserConfig();
+
+    public RawTiffParser() {
+    }
+
+    public RawTiffParser(RawTiffParserConfig config) {
+        this.defaultConfig = config;
+    }

Review Comment:
   `defaultConfig` is mutable, non-final, and is assigned directly from the 
caller-provided `RawTiffParserConfig`. If the caller retains and mutates that 
config instance while parses are running, behavior can change mid-parse and 
introduce thread-safety issues. Consider copying the needed values into an 
immutable/final field (e.g., store a final boolean), or defensively copying the 
config object in the constructor.



##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/RawTiffParser.java:
##########
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.parser.image;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.annotation.TikaComponent;
+import org.apache.tika.config.ConfigDeserializer;
+import org.apache.tika.config.JsonConfig;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.extractor.EmbeddedDocumentExtractor;
+import org.apache.tika.extractor.EmbeddedDocumentUtil;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.HttpHeaders;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for TIFF-based camera raw images: Nikon NEF/NRW, Sony ARW/SRF/SR2,
+ * Pentax PEF/PTX, Adobe DNG and Canon CR2.
+ * <p>
+ * These formats are TIFF containers: metadata extraction is inherited from
+ * {@link TiffParser}. In addition, this parser extracts the camera-generated
+ * JPEG preview images embedded in the raw file and hands them to the
+ * {@link EmbeddedDocumentExtractor}. Previews are referenced from the IFD
+ * chain or from SubIFDs, either via the JPEGInterchangeFormat/
+ * JPEGInterchangeFormatLength tags or as a single JPEG-compressed strip
+ * (DNG, CR2). Strips holding raw sensor data are also JPEG-encoded in some
+ * formats (lossless JPEG in CR2 and DNG), so strip candidates are only
+ * accepted for displayable images: PhotometricInterpretation RGB or YCbCr,
+ * or 8 bits per sample when PhotometricInterpretation is absent (CR2).
+ */
+@TikaComponent
+public class RawTiffParser extends TiffParser {
+
+    /**
+     * Serial version UID
+     */
+    private static final long serialVersionUID = 5385105345533384662L;
+
+    private static final Set<MediaType> SUPPORTED_TYPES = 
Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(
+                    MediaType.image("x-raw-nikon"),
+                    MediaType.image("x-raw-sony"),
+                    MediaType.image("x-raw-pentax"),
+                    MediaType.image("x-raw-adobe"),
+                    MediaType.image("x-canon-cr2"))));
+
+    private static final String JPEG_MIME = "image/jpeg";
+
+    private static final int TAG_BITS_PER_SAMPLE = 0x0102;
+    private static final int TAG_COMPRESSION = 0x0103;
+    private static final int TAG_PHOTOMETRIC_INTERPRETATION = 0x0106;
+    private static final int TAG_STRIP_OFFSETS = 0x0111;
+    private static final int TAG_STRIP_BYTE_COUNTS = 0x0117;
+    private static final int TAG_SUB_IFDS = 0x014A;
+    private static final int TAG_JPEG_INTERCHANGE_FORMAT = 0x0201;
+    private static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x0202;
+
+    private static final int COMPRESSION_OLD_JPEG = 6;
+    private static final int COMPRESSION_JPEG = 7;
+    private static final int PHOTOMETRIC_RGB = 2;
+    private static final int PHOTOMETRIC_YCBCR = 6;
+
+    private static final int MAX_IFDS = 32;
+    private static final int MAX_ENTRIES_PER_IFD = 1024;
+    //previews are camera-generated JPEGs, tens of MB is already generous
+    private static final long MAX_PREVIEW_LENGTH_BYTES = 100 * 1024 * 1024;
+
+    private RawTiffParserConfig defaultConfig = new RawTiffParserConfig();
+
+    public RawTiffParser() {
+    }
+
+    public RawTiffParser(RawTiffParserConfig config) {
+        this.defaultConfig = config;
+    }
+
+    public RawTiffParser(JsonConfig jsonConfig) {
+        this(ConfigDeserializer.buildConfig(jsonConfig, 
RawTiffParserConfig.class));
+    }
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return SUPPORTED_TYPES;
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata 
metadata,
+                      ParseContext context) throws IOException, SAXException, 
TikaException {
+        tis.getFile();
+        extractMetadata(tis, handler, metadata, context);
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata, 
context);
+        xhtml.startDocument();
+        if (defaultConfig.isExtractPreviews()) {
+            extractPreviews(tis, xhtml, metadata, context);
+        }
+        xhtml.endDocument();
+    }
+
+    private void extractPreviews(TikaInputStream tis, XHTMLContentHandler 
xhtml, Metadata metadata,
+                                 ParseContext context) throws IOException, 
SAXException {
+        List<long[]> previews;
+        try (RandomAccessFile raf = new RandomAccessFile(tis.getFile(), "r")) {
+            previews = locateJpegPreviews(raf);
+            if (previews.isEmpty()) {
+                return;
+            }
+            EmbeddedDocumentExtractor extractor =
+                    EmbeddedDocumentUtil.getEmbeddedDocumentExtractor(context);
+            int count = 0;
+            for (long[] preview : previews) {
+                Metadata previewMetadata = Metadata.newInstance(context);
+                previewMetadata.set(TikaCoreProperties.EMBEDDED_RESOURCE_TYPE,
+                        
TikaCoreProperties.EmbeddedResourceType.THUMBNAIL.toString());
+                previewMetadata.set(HttpHeaders.CONTENT_TYPE, JPEG_MIME);
+                EmbeddedDocumentUtil.setGeneratedResourceName(previewMetadata,
+                        EmbeddedDocumentUtil.EmbeddedResourcePrefix.THUMBNAIL, 
count, JPEG_MIME);
+                count++;
+                if (!extractor.shouldParseEmbedded(previewMetadata, context)) {
+                    continue;
+                }
+                byte[] data = new byte[(int) preview[1]];
+                raf.seek(preview[0]);
+                raf.readFully(data);
+                try (TikaInputStream previewStream = 
TikaInputStream.get(data)) {
+                    extractor.parseEmbedded(previewStream, xhtml, 
previewMetadata, context, true);
+                }

Review Comment:
   This reads each preview fully into a byte[] before parsing. Since previews 
can be large (up to 100MB by current cap) and multiple previews can exist per 
file, this can create significant heap pressure and increase OOM risk under 
concurrent parsing. Prefer streaming from the underlying file with a 
bounded/offset-limited stream (e.g., seek to the offset and wrap a stream 
limited to `jpegLength`) so extraction does not require loading the entire 
preview into memory.



##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/RawTiffParser.java:
##########
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.parser.image;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import org.apache.tika.annotation.TikaComponent;
+import org.apache.tika.config.ConfigDeserializer;
+import org.apache.tika.config.JsonConfig;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.extractor.EmbeddedDocumentExtractor;
+import org.apache.tika.extractor.EmbeddedDocumentUtil;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.HttpHeaders;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Parser for TIFF-based camera raw images: Nikon NEF/NRW, Sony ARW/SRF/SR2,
+ * Pentax PEF/PTX, Adobe DNG and Canon CR2.
+ * <p>
+ * These formats are TIFF containers: metadata extraction is inherited from
+ * {@link TiffParser}. In addition, this parser extracts the camera-generated
+ * JPEG preview images embedded in the raw file and hands them to the
+ * {@link EmbeddedDocumentExtractor}. Previews are referenced from the IFD
+ * chain or from SubIFDs, either via the JPEGInterchangeFormat/
+ * JPEGInterchangeFormatLength tags or as a single JPEG-compressed strip
+ * (DNG, CR2). Strips holding raw sensor data are also JPEG-encoded in some
+ * formats (lossless JPEG in CR2 and DNG), so strip candidates are only
+ * accepted for displayable images: PhotometricInterpretation RGB or YCbCr,
+ * or 8 bits per sample when PhotometricInterpretation is absent (CR2).
+ */
+@TikaComponent
+public class RawTiffParser extends TiffParser {
+
+    /**
+     * Serial version UID
+     */
+    private static final long serialVersionUID = 5385105345533384662L;
+
+    private static final Set<MediaType> SUPPORTED_TYPES = 
Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(
+                    MediaType.image("x-raw-nikon"),
+                    MediaType.image("x-raw-sony"),
+                    MediaType.image("x-raw-pentax"),
+                    MediaType.image("x-raw-adobe"),
+                    MediaType.image("x-canon-cr2"))));
+
+    private static final String JPEG_MIME = "image/jpeg";
+
+    private static final int TAG_BITS_PER_SAMPLE = 0x0102;
+    private static final int TAG_COMPRESSION = 0x0103;
+    private static final int TAG_PHOTOMETRIC_INTERPRETATION = 0x0106;
+    private static final int TAG_STRIP_OFFSETS = 0x0111;
+    private static final int TAG_STRIP_BYTE_COUNTS = 0x0117;
+    private static final int TAG_SUB_IFDS = 0x014A;
+    private static final int TAG_JPEG_INTERCHANGE_FORMAT = 0x0201;
+    private static final int TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = 0x0202;
+
+    private static final int COMPRESSION_OLD_JPEG = 6;
+    private static final int COMPRESSION_JPEG = 7;
+    private static final int PHOTOMETRIC_RGB = 2;
+    private static final int PHOTOMETRIC_YCBCR = 6;
+
+    private static final int MAX_IFDS = 32;
+    private static final int MAX_ENTRIES_PER_IFD = 1024;
+    //previews are camera-generated JPEGs, tens of MB is already generous
+    private static final long MAX_PREVIEW_LENGTH_BYTES = 100 * 1024 * 1024;
+
+    private RawTiffParserConfig defaultConfig = new RawTiffParserConfig();
+
+    public RawTiffParser() {
+    }
+
+    public RawTiffParser(RawTiffParserConfig config) {
+        this.defaultConfig = config;
+    }
+
+    public RawTiffParser(JsonConfig jsonConfig) {
+        this(ConfigDeserializer.buildConfig(jsonConfig, 
RawTiffParserConfig.class));
+    }
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return SUPPORTED_TYPES;
+    }
+
+    @Override
+    public void parse(TikaInputStream tis, ContentHandler handler, Metadata 
metadata,
+                      ParseContext context) throws IOException, SAXException, 
TikaException {
+        tis.getFile();
+        extractMetadata(tis, handler, metadata, context);
+        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata, 
context);
+        xhtml.startDocument();
+        if (defaultConfig.isExtractPreviews()) {
+            extractPreviews(tis, xhtml, metadata, context);
+        }
+        xhtml.endDocument();
+    }
+
+    private void extractPreviews(TikaInputStream tis, XHTMLContentHandler 
xhtml, Metadata metadata,
+                                 ParseContext context) throws IOException, 
SAXException {
+        List<long[]> previews;
+        try (RandomAccessFile raf = new RandomAccessFile(tis.getFile(), "r")) {
+            previews = locateJpegPreviews(raf);
+            if (previews.isEmpty()) {
+                return;
+            }
+            EmbeddedDocumentExtractor extractor =
+                    EmbeddedDocumentUtil.getEmbeddedDocumentExtractor(context);
+            int count = 0;
+            for (long[] preview : previews) {
+                Metadata previewMetadata = Metadata.newInstance(context);
+                previewMetadata.set(TikaCoreProperties.EMBEDDED_RESOURCE_TYPE,
+                        
TikaCoreProperties.EmbeddedResourceType.THUMBNAIL.toString());
+                previewMetadata.set(HttpHeaders.CONTENT_TYPE, JPEG_MIME);
+                EmbeddedDocumentUtil.setGeneratedResourceName(previewMetadata,
+                        EmbeddedDocumentUtil.EmbeddedResourcePrefix.THUMBNAIL, 
count, JPEG_MIME);
+                count++;
+                if (!extractor.shouldParseEmbedded(previewMetadata, context)) {
+                    continue;
+                }
+                byte[] data = new byte[(int) preview[1]];
+                raf.seek(preview[0]);
+                raf.readFully(data);
+                try (TikaInputStream previewStream = 
TikaInputStream.get(data)) {
+                    extractor.parseEmbedded(previewStream, xhtml, 
previewMetadata, context, true);
+                }
+            }
+        } catch (TiffStructureException e) {
+            EmbeddedDocumentUtil.recordException(e, metadata);
+        }
+    }
+
+    /**
+     * Walks the TIFF IFD chain plus one level of SubIFDs and returns
+     * {offset, length} pairs of embedded JPEG previews.
+     */
+    private List<long[]> locateJpegPreviews(RandomAccessFile raf)
+            throws IOException, TiffStructureException {
+        long fileLength = raf.length();
+        if (fileLength < 8) {
+            throw new TiffStructureException("file too short for a TIFF 
header");
+        }
+        raf.seek(0);
+        int b0 = raf.read();
+        int b1 = raf.read();
+        boolean bigEndian;
+        if (b0 == 'M' && b1 == 'M') {
+            bigEndian = true;
+        } else if (b0 == 'I' && b1 == 'I') {
+            bigEndian = false;
+        } else {
+            throw new TiffStructureException("not a TIFF byte order marker");
+        }
+        if (readUInt16(raf, bigEndian) != 42) {
+            throw new TiffStructureException("bad TIFF magic number");
+        }
+
+        List<long[]> previews = new ArrayList<>();
+        Set<Long> visited = new HashSet<>();
+        List<Long> toVisit = new ArrayList<>();
+        toVisit.add(readUInt32(raf, bigEndian));
+
+        while (!toVisit.isEmpty() && visited.size() < MAX_IFDS) {
+            long ifdOffset = toVisit.remove(0);

Review Comment:
   `toVisit.remove(0)` on an `ArrayList` is O(n) due to shifting elements. Even 
though `MAX_IFDS` is currently small, switching `toVisit` to a queue structure 
(e.g., `ArrayDeque`) avoids the quadratic pattern and makes the intent (FIFO 
traversal) clearer.





> Extract embedded JPEG previews from TIFF-based raw images (NEF, ARW, PEF, 
> DNG, CR2)
> -----------------------------------------------------------------------------------
>
>                 Key: TIKA-4824
>                 URL: https://issues.apache.org/jira/browse/TIKA-4824
>             Project: Tika
>          Issue Type: New Feature
>            Reporter: Dominik Schmidt
>            Priority: Major
>
> TIFF-based camera raw files embed camera-generated JPEG previews, often at 
> full resolution. Tika currently gives no access to them: the x-raw-* types 
> are glob-only (not sub-classes of image/tiff), no parser claims them, and 
> nothing extracts the preview bytes. For consumers that cannot decode raw 
> sensor data, the embedded JPEG is the only practical way to render a raw file 
> (analogous to TIKA-4801 for audio cover art).
> The previews are stored in two ways:
> - Nikon NEF/NRW, Sony ARW/SRF/SR2, Pentax PEF/PTX: 
> JPEGInterchangeFormat/-Length tags in the IFD chain or in SubIFDs
> - Adobe DNG, Canon CR2: a single JPEG-compressed strip (Compression 6/7)
> Proposal:
> - New RawTiffParser in tika-parser-image-module claiming 
> image/x-raw-{nikon,sony,pentax,adobe} and image/x-canon-cr2: TIFF/EXIF/XMP 
> metadata via TiffParser, walks the IFD chain plus SubIFDs and emits each 
> preview through the EmbeddedDocumentExtractor (image/jpeg, THUMBNAIL); 
> configurable via "raw-tiff-parser": {"extractPreviews": false}
> - Strip candidates need a safety rule: raw sensor data in CR2/DNG is lossless 
> JPEG and also starts with an SOI marker. Strips are only accepted for 
> displayable images (PhotometricInterpretation RGB/YCbCr, or 8 bits per sample 
> when it is absent, as in CR2's preview IFD)
> - Make image/x-raw-{nikon,sony,pentax,adobe} sub-classes of image/tiff so 
> name+data detection resolves them (they have no reliable magic; data-only 
> detection stays image/tiff)
> - Synthetic ~2KB test fixtures mirroring the real IFD layouts, unit and 
> detection tests
> Evaluated and excluded: Epson ERF (preview lives in the MakerNote), Olympus 
> ORF and Panasonic RW2 (non-standard TIFF magic), Fuji RAF (not TIFF), Canon 
> CR3 (ISO-BMFF). Verified against CC0 samples from raw.pixls.us (NEX-6, 
> DSC-R1, K-7, EOS 7D, K-x and GR DNGs) plus real Nikon D80/D3000 files.
> PR to follow.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to