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

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

dschmidt commented on code in PR #3095:
URL: https://github.com/apache/tika/pull/3095#discussion_r3892318747


##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/WMFParser.java:
##########
@@ -32,25 +32,56 @@
 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.config.ParseContextConfig;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.TikaInputStream;
 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.parser.Parser;
+import org.apache.tika.parser.RenderingParser;
+import org.apache.tika.renderer.Renderer;
 import org.apache.tika.sax.XHTMLContentHandler;
 
 /**
  * This parser offers a very rough capability to extract text if there
  * is text stored in the WMF files.
  */

Review Comment:
   Merged into one.



##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/MetafileRendering.java:
##########
@@ -0,0 +1,135 @@
+/*
+ * 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.microsoft;
+
+import java.io.IOException;
+
+import org.xml.sax.SAXException;
+
+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.renderer.RenderResult;
+import org.apache.tika.renderer.RenderResults;
+import org.apache.tika.renderer.Renderer;
+import org.apache.tika.renderer.microsoft.POIMetafileRenderer;
+import org.apache.tika.sax.EmbeddedContentHandler;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Shared by {@link EMFParser} and {@link WMFParser}: renders a parsed
+ * metafile through a {@link Renderer} and emits the result as an embedded
+ * document, the way the PDF parser emits page renderings. The rendering of
+ * a {@link TikaCoreProperties.EmbeddedResourceType#THUMBNAIL} is itself a
+ * THUMBNAIL (it is the same picture in a form a client can display); any
+ * other rendering is a {@link 
TikaCoreProperties.EmbeddedResourceType#RENDERING}.
+ */
+final class MetafileRendering {
+
+    private MetafileRendering() {
+    }
+
+    /**
+     * @param injected the renderer set on the parser, or null
+     * @param picture  the parsed {@code HemfPicture} or {@code HwmfPicture}
+     */
+    static void render(Renderer injected, MetafileParserConfig config, 
MediaType type,
+                       Object picture, XHTMLContentHandler xhtml, Metadata 
metadata,
+                       ParseContext context) throws IOException, SAXException {
+        //like the PDF parser: the injected renderer if it handles the type,
+        //the default one otherwise
+        Renderer renderer = injected != null && 
injected.getSupportedTypes(context).contains(type)
+                ? injected : defaultRenderer(config);
+        Metadata renderMetadata = Metadata.newInstance(context);
+        renderMetadata.set(TikaCoreProperties.TYPE, type.toString());
+        EmbeddedDocumentExtractor extractor =
+                EmbeddedDocumentUtil.getEmbeddedDocumentExtractor(context);
+        try (TikaInputStream pictureStream = TikaInputStream.get(new byte[0]);
+             RenderResults results = render(renderer, pictureStream, picture, 
renderMetadata,
+                     context)) {
+            if (results == null) {
+                return;
+            }

Review Comment:
   It is recorded on the metafile's metadata now.



##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/renderer/microsoft/POIMetafileRenderer.java:
##########
@@ -0,0 +1,259 @@
+/*
+ * 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.renderer.microsoft;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Dimension2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.imageio.ImageIO;
+
+import org.apache.poi.hemf.usermodel.HemfPicture;
+import org.apache.poi.hwmf.record.HwmfFill;
+import org.apache.poi.hwmf.record.HwmfRecord;
+import org.apache.poi.hwmf.usermodel.HwmfPicture;
+
+import org.apache.tika.annotation.TikaComponent;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.io.TemporaryResources;
+import org.apache.tika.io.TikaInputStream;
+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;
+import org.apache.tika.renderer.RenderRequest;
+import org.apache.tika.renderer.RenderResult;
+import org.apache.tika.renderer.RenderResults;
+import org.apache.tika.renderer.Renderer;
+import org.apache.tika.renderer.RenderingTracker;
+
+/**
+ * Renders EMF and WMF images to a raster image through POI's HEMF and HWMF,
+ * the way {@code PDFBoxRenderer} renders PDF pages. The rendering has the
+ * configured width, its height follows the image's aspect ratio, and it is
+ * drawn on a white canvas. Metafiles have no pages, so the render requests
+ * are ignored and a single result is returned.
+ * <p>
+ * The WMF thumbnails that Word stores in the SummaryInformation of a .doc
+ * consist of a window extent and a single {@code dibStretchBlt} record, for
+ * which POI cannot compute bounds; those are rendered from the record's
+ * bitmap directly.
+ */
+@TikaComponent(name = "poi-metafile-renderer")
+public class POIMetafileRenderer implements Renderer {
+
+    public static final String RENDERED_BY = "poi-metafile-renderer";
+
+    public static final MediaType EMF = MediaType.image("emf");
+    public static final MediaType WMF = MediaType.image("wmf");
+
+    private static final Set<MediaType> SUPPORTED_TYPES =
+            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(EMF, 
WMF)));
+
+    private static final int MAX_WIDTH = 10000;
+
+    private int width = 800;
+    private String imageFormatName = "png";
+
+    @Override
+    public Set<MediaType> getSupportedTypes(ParseContext context) {
+        return SUPPORTED_TYPES;
+    }
+
+    /**
+     * Renders the metafile in the stream, or the {@link HemfPicture} or
+     * {@link HwmfPicture} set as the stream's open container. The metadata's
+     * {@link TikaCoreProperties#TYPE} tells EMF from WMF when a stream is
+     * parsed; it defaults to EMF.
+     */
+    @Override
+    public RenderResults render(TikaInputStream tis, Metadata metadata, 
ParseContext parseContext,
+                                RenderRequest... requests) throws IOException, 
TikaException {
+        Object picture = tis.getOpenContainer();
+        if (!(picture instanceof HemfPicture) && !(picture instanceof 
HwmfPicture)) {
+            picture = 
WMF.toString().equals(metadata.get(TikaCoreProperties.TYPE))
+                    ? new HwmfPicture(tis) : new HemfPicture(tis);
+        }
+        RenderingTracker tracker = parseContext.get(RenderingTracker.class);
+        if (tracker == null) {
+            tracker = new RenderingTracker();
+            parseContext.set(RenderingTracker.class, tracker);
+        }
+        int id = tracker.getNextId();
+        Metadata renderingMetadata = Metadata.newInstance(parseContext);
+        renderingMetadata.set(TikaCoreProperties.EMBEDDED_RESOURCE_TYPE,
+                TikaCoreProperties.EmbeddedResourceType.RENDERING.name());
+        RenderResults results = new RenderResults(new TemporaryResources());
+        try {
+            long start = System.currentTimeMillis();
+            BufferedImage image = picture instanceof HemfPicture
+                    ? draw((HemfPicture) picture) : draw((HwmfPicture) 
picture);
+            Path tmpFile = write(image, id);
+            renderingMetadata.set(Rendering.RENDERED_MS, 
System.currentTimeMillis() - start);
+            renderingMetadata.add(Rendering.RENDERED_BY, RENDERED_BY);
+            renderingMetadata.set(HttpHeaders.CONTENT_TYPE, "image/" + 
imageFormatName);
+            results.add(new RenderResult(RenderResult.STATUS.SUCCESS, id, 
tmpFile,
+                    renderingMetadata));
+        } catch (SecurityException e) {
+            throw e;
+        } catch (Exception e) {
+            results.add(new RenderResult(RenderResult.STATUS.EXCEPTION, id, 
null,
+                    renderingMetadata));
+        }

Review Comment:
   Recorded, like PDFBoxRenderer does.



##########
CHANGES.txt:
##########
@@ -1,5 +1,16 @@
 Release 4.1.0 - unreleased
 
+   * Raster previews for the vector thumbnails of Office documents: the new
+     poi-metafile-renderer draws EMF and WMF images through POI (a PNG of
+     a configurable width; Word's bitmap-in-WMF thumbnails from the bitmap
+     directly), EMFParser and WMFParser are RenderingParsers that emit the
+     rendering as a RENDERING embedded document with "emf-parser" /
+     "wmf-parser": {"renderImage": true, "renderWidth": 800}, off by
+     default and restrictable to e.g. THUMBNAIL embedded documents with
+     "renderOnlyEmbeddedResourceTypes", and OfficeParser emits the 
SummaryInformation thumbnail of the
+     OLE2 formats (a WMF) as a THUMBNAIL embedded document, as the OOXML
+     parsers do with the docProps thumbnail (TIKA-4855).

Review Comment:
   Wrapped.



##########
tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/EMFParser.java:
##########
@@ -62,12 +68,39 @@
  * We'd have to do something like what PDFBox or XPS do to sort the
  * runs and then put the cow back together from the hamburger...lol...
  */
+/**
+ * Extracts the text of an EMF image and its embedded WMF and multi-format

Review Comment:
   Merged into one.





> Render EMF/WMF images to raster previews and emit the OLE2 SummaryInformation 
> thumbnail
> ---------------------------------------------------------------------------------------
>
>                 Key: TIKA-4855
>                 URL: https://issues.apache.org/jira/browse/TIKA-4855
>             Project: Tika
>          Issue Type: Improvement
>            Reporter: Dominik Schmidt
>            Priority: Major
>
> Office documents carry their preview image as a vector metafile: the OOXML 
> docProps/thumbnail.emf of Word (an EMF wrapping a WMF) and thumbnail.wmf of 
> Excel, and the SummaryInformation thumbnail (PIDSI_THUMBNAIL, 
> CF_METAFILEPICT, a WMF) of the OLE2 formats, which PowerPoint writes almost 
> always and Word/Excel on request. Neither is usable as a preview outside 
> Windows, and outside the JVM there is no maintained EMF/WMF rasterizer. POI's 
> HEMF/HWMF can draw both and Tika already bundles them.
> Proposal, following the PDF parser's rendering design:
> 1. A Renderer for image/emf and image/wmf (POI HemfPicture/HwmfPicture drawn 
> onto a white canvas, a PNG of a configurable width, the height following the 
> aspect ratio). The WMF thumbnails Word writes consist of a setWindowExt and a 
> dibStretchBlt record only, for which POI cannot compute bounds; for those the 
> renderer emits the record's bitmap.
> 2. EMFParser and WMFParser implement RenderingParser and, with "emf-parser" / 
> "wmf-parser": {"renderImage": true, "renderWidth": 800} (off by default), 
> emit the rendering as a RENDERING embedded document named after the image, 
> the way the PDF parser emits page renderings. An injected renderer is used 
> when it supports the type, the POI one otherwise.
> 3. OfficeParser emits the SummaryInformation thumbnail of the OLE2 formats as 
> a THUMBNAIL embedded document (image/wmf, named thumbnail.wmf), consistent 
> with the docProps thumbnail of the OOXML parsers. Existing tests that count 
> the embedded documents of .ppt fixtures gain one.
> With that, a client that asks for THUMBNAIL and RENDERING embedded documents 
> gets a raster preview for docx, xlsx, doc, xls and ppt files that carry a 
> thumbnail, with the same request it uses for every other format. Verified 
> against tika-server with /unpack: each of these yields the thumbnail at depth 
> 1 and its PNG rendering at depth 2.
> Note for clients: with rendering enabled every embedded metafile is rendered, 
> e.g. the picture of an OLE object, so the preview is the RENDERING under the 
> THUMBNAIL, not the first RENDERING.



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

Reply via email to