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

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

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


##########
tika-pipes/tika-pipes-core/src/main/java/org/apache/tika/pipes/core/extractor/ThumbnailUnpackSelector.java:
##########
@@ -0,0 +1,92 @@
+/*
+ * 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.pipes.core.extractor;
+
+import java.util.Locale;
+import java.util.Set;
+
+import org.apache.tika.annotation.TikaComponent;
+import org.apache.tika.config.TransientParseState;
+import org.apache.tika.extractor.UnpackSelector;
+import org.apache.tika.metadata.HttpHeaders;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.Rendering;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.mime.MediaType;
+import org.apache.tika.parser.ParseContext;
+
+/**
+ * Unpacks the one embedded document a client would show as the document's 
thumbnail and
+ * nothing else. A candidate is a raster image that is a {@code THUMBNAIL} at 
depth 1 (stored
+ * thumbnail), a rendered {@code THUMBNAIL} at depth 2 (the rasterized vector 
thumbnail of an
+ * Office document; {@code tk:rendering:rendered-by} marks it), or a {@code 
RENDERING} at
+ * depth 1 (the first page of a PDF); the first candidate of a parse wins. The 
thumbnail of a
+ * document inside an archive is that document's, not the archive's, and is 
not a candidate.
+ * Pair it with parser config that renders only those, as the catalog preset 
{@code thumbnails}
+ * does; clients reading {@code /rmeta} apply the same rule.
+ *
+ * @since Apache Tika 4.1.0
+ */
+@TikaComponent
+public class ThumbnailUnpackSelector implements UnpackSelector {
+
+    private static final Set<String> VECTOR_TYPES = Set.of("image/emf", 
"image/x-emf",
+            "image/wmf", "image/x-wmf", "image/svg+xml");
+
+    /** Marks a parse whose thumbnail is taken; the selector itself may be 
shared. */
+    private static final class Taken implements TransientParseState {
+    }
+
+    @Override
+    public boolean select(Metadata metadata) {
+        return isCandidate(metadata);
+    }
+
+    /** The stateless rule; {@code /rmeta} clients pick the first embedded 
document it accepts. */
+    public static boolean isCandidate(Metadata metadata) {
+        String type = metadata.get(TikaCoreProperties.EMBEDDED_RESOURCE_TYPE);
+        Integer depth = metadata.getInt(TikaCoreProperties.EMBEDDED_DEPTH);
+        if (type == null || depth == null || !isRaster(metadata)) {
+            return false;
+        }
+        if 
(TikaCoreProperties.EmbeddedResourceType.THUMBNAIL.name().equals(type)) {
+            return depth == 1
+                    || (depth == 2 && metadata.get(Rendering.RENDERED_BY) != 
null);
+        }
+        return 
TikaCoreProperties.EmbeddedResourceType.RENDERING.name().equals(type)
+                && depth == 1;
+    }
+
+    @Override
+    public boolean select(Metadata metadata, ParseContext context) {
+        if (context.get(Taken.class) != null || !isCandidate(metadata)) {
+            return false;
+        }
+        context.set(Taken.class, new Taken());

Review Comment:
   Because `Taken` is stored in the `ParseContext` and is never cleared, 
reusing one context for a second top-level parse permanently rejects every 
later candidate. `ParseContext` is allowed to survive later parses (for 
example, `CompositeParser` explicitly caches state on reused contexts), so this 
per-parse overload does not actually reset at a parse boundary; bind the marker 
to the current parse lifecycle or clear it when the top-level parse starts, and 
add a reuse test.



##########
tika-pipes/tika-pipes-core/src/main/resources/org/apache/tika/pipes/core/presets/thumbnails.json:
##########
@@ -0,0 +1,17 @@
+{
+  // one raster thumbnail per document, nothing else; the rule is in 
ThumbnailUnpackSelector
+  "thumbnail-unpack-selector": {},

Review Comment:
   This selector only filters bytes when `UnpackExtractor` stores an 
already-parsed child; it does not stop the embedded parser from traversing 
later siblings or descendants. Because this preset leaves `EmbeddedLimits` at 
its unlimited defaults, a large/deep archive can still parse and render its 
entire tree (including every PDF's first page) before discarding all but one 
image, which conflicts with the documented bounded/cheap preset behavior. Add 
explicit embedded depth/count limits that still allow the direct depth-2 
vector-thumbnail render, or add an equivalent traversal short-circuit.





> /unpack/thumbnail: return the document thumbnail with its metadata
> ------------------------------------------------------------------
>
>                 Key: TIKA-4856
>                 URL: https://issues.apache.org/jira/browse/TIKA-4856
>             Project: Tika
>          Issue Type: New Feature
>            Reporter: Dominik Schmidt
>            Priority: Major
>
> With TIKA-4850 through TIKA-4855 every container format that carries a 
> thumbnail emits it as a THUMBNAIL embedded document, the PDF parser renders 
> pages as RENDERING documents, and the EMF/WMF renderer turns the vector 
> thumbnails of Office documents into raster ones. Getting "the thumbnail of 
> this file" out of that still takes format knowledge on the client: the 
> THUMBNAIL of a Word or Excel file is an EMF/WMF whose usable form is the 
> RENDERING underneath it, a PDF has no THUMBNAIL but a page RENDERING, the 
> THUMBNAIL of a DOCX inside a ZIP is not the ZIP's, and with rendering enabled 
> the picture of an embedded OLE object is a RENDERING too. Plus the request 
> config that switches the renderers on.
> Proposal: POST /unpack/thumbnail next to /unpack and /unpack/all, multipart 
> like them. It runs the usual forked parse in unpack mode with a fixed parse 
> context (PDF page 1 rendered, EMF/WMF rendered) and picks, in this order: the 
> raster THUMBNAIL at depth 1; the rendering of that thumbnail; the depth-1 
> RENDERING of PDF page 1. The endpoint extracts what the document carries; it 
> does not resize, convert or generate previews.
> The response is JSON: the /rmeta metadata object of the selected embedded 
> document, and the image as base64. Thumbnails are small, so the encoding 
> overhead does not matter, and the caller gets type, dimensions, origin 
> (stored thumbnail or rendering, tk:rendering:rendered-by) and path in one 
> round trip without unpacking a zip. 204 when the document has no thumbnail.
> {
>   "metadata": {
>     "Content-Type": "image/png",
>     "Content-Length": "8459",
>     "tiff:ImageWidth": "800",
>     "tiff:ImageLength": "1131",
>     "tk:embedded-resource-type": "RENDERING",
>     "tk:embedded-resource-path": "/thumbnail.emf/thumbnail.png",
>     "tk:embedded-depth": "2",
>     "tk:rendering:rendered-by": "poi-metafile-renderer",
>     "tk:resource-name": "thumbnail.png"
>   },
>   "image": "iVBORw0KGgoAAAANSUhEUgAA..."
> }
> To keep the selection rule short, the metafile renderer could give the 
> rendering of a THUMBNAIL the THUMBNAIL type as well (its 
> tk:rendering:rendered-by tells it apart), so a raster thumbnail is a 
> THUMBNAIL regardless of whether the document stored it as PNG or as EMF.
> What do you think? 



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

Reply via email to