From d0becd061162e5f7fbfc79682b278243e99f63e0 Mon Sep 17 00:00:00 2001 From: Peter Herweg Date: Sun, 30 Oct 2005 16:55:47 +0000 Subject: Use FOP's wrapper classes to load images. Support 'auto' in fo:external-grapic@height, -@width, -@content-height and -@content-width git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@329590 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/fop/image/EmfImage.java | 72 ++++++++++ src/java/org/apache/fop/image/ImageFactory.java | 6 +- .../org/apache/fop/image/analyser/EMFReader.java | 159 +++++++++++++++++++++ .../fop/image/analyser/ImageReaderFactory.java | 1 + src/java/org/apache/fop/render/rtf/RTFHandler.java | 68 ++++++++- .../rtf/rtflib/rtfdoc/RtfExternalGraphic.java | 48 +++++-- 6 files changed, 332 insertions(+), 22 deletions(-) create mode 100644 src/java/org/apache/fop/image/EmfImage.java create mode 100644 src/java/org/apache/fop/image/analyser/EMFReader.java (limited to 'src/java/org') diff --git a/src/java/org/apache/fop/image/EmfImage.java b/src/java/org/apache/fop/image/EmfImage.java new file mode 100644 index 000000000..bbe3794c5 --- /dev/null +++ b/src/java/org/apache/fop/image/EmfImage.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed 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.fop.image; + +// Java +import java.io.ByteArrayOutputStream; + +import org.apache.commons.io.IOUtils; + +/** + * Enhanced metafile image. + * This supports loading a emf image. + * + * @author Peter Herweg + * @see AbstractFopImage + * @see FopImage + */ +public class EmfImage extends AbstractFopImage { + /** + * Create a bitmap image with the image data. + * + * @param imgInfo the image information + */ + public EmfImage(FopImage.ImageInfo imgInfo) { + super(imgInfo); + } + + /** + * Load the original jpeg data. + * This loads the original jpeg data and reads the color space, + * and icc profile if any. + * + * @return true if loaded false for any error + */ + protected boolean loadOriginalData() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try { + byte[] readBuf = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(readBuf)) != -1) { + baos.write(readBuf, 0, bytesRead); + } + } catch (java.io.IOException ex) { + log.error("Error while loading image (Emf): " + ex.getMessage(), ex); + return false; + } finally { + IOUtils.closeQuietly(inputStream); + inputStream = null; + } + + this.raw = baos.toByteArray(); + + return true; + } +} + diff --git a/src/java/org/apache/fop/image/ImageFactory.java b/src/java/org/apache/fop/image/ImageFactory.java index 8379cda85..d7b73c372 100644 --- a/src/java/org/apache/fop/image/ImageFactory.java +++ b/src/java/org/apache/fop/image/ImageFactory.java @@ -71,6 +71,7 @@ public final class ImageFactory { ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage"); ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage"); ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage"); + ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage"); ImageMimeType imt = new ImageMimeType("image/gif"); imageMimeTypes.put(imt.getMimeType(), imt); @@ -113,7 +114,10 @@ public final class ImageFactory { imt = new ImageMimeType("text/xml"); imageMimeTypes.put(imt.getMimeType(), imt); imt.addProvider(xmlImage); - + + imt = new ImageMimeType("image/emf"); + imageMimeTypes.put(imt.getMimeType(), imt); + imt.addProvider(emfImage); } /** diff --git a/src/java/org/apache/fop/image/analyser/EMFReader.java b/src/java/org/apache/fop/image/analyser/EMFReader.java new file mode 100644 index 000000000..a5c01845f --- /dev/null +++ b/src/java/org/apache/fop/image/analyser/EMFReader.java @@ -0,0 +1,159 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed 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.fop.image.analyser; + +// Java +import java.io.InputStream; +import java.io.IOException; + +// FOP +import org.apache.fop.image.FopImage; +import org.apache.fop.apps.FOUserAgent; + +/** + * ImageReader object for EMF image type. + * + * @author Peter Herweg + */ +public class EMFReader implements ImageReader { + + /** Length of the EMF header */ + protected static final int EMF_SIG_LENGTH = 88; + + /** offset to signature */ + private static final int SIGNATURE_OFFSET = 40; + /** offset to width */ + private static final int WIDTH_OFFSET = 32; + /** offset to height */ + private static final int HEIGHT_OFFSET = 36; + /** offset to horizontal resolution in pixel */ + private static final int HRES_PIXEL_OFFSET = 72; + /** offset to vertical resolution in pixel */ + private static final int VRES_PIXEL_OFFSET = 76; + /** offset to horizontal resolution in mm */ + private static final int HRES_MM_OFFSET = 80; + /** offset to vertical resolution in mm */ + private static final int VRES_MM_OFFSET = 84; + + /** @see org.apache.fop.image.analyser.ImageReader */ + public FopImage.ImageInfo verifySignature(String uri, InputStream bis, + FOUserAgent ua) throws IOException { + byte[] header = getDefaultHeader(bis); + boolean supported = + ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20) + && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45) + && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D) + && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) ); + + if (supported) { + FopImage.ImageInfo info = getDimension(header); + info.originalURI = uri; + info.mimeType = getMimeType(); + info.inputStream = bis; + return info; + } else { + return null; + } + } + + /** + * Returns the MIME type supported by this implementation. + * + * @return The MIME type + */ + public String getMimeType() { + return "image/emf"; + } + + private FopImage.ImageInfo getDimension(byte[] header) { + FopImage.ImageInfo info = new FopImage.ImageInfo(); + long value = 0; + int byte1; + int byte2; + int byte3; + int byte4; + + // little endian notation + + //resolution + byte1 = header[HRES_MM_OFFSET] & 0xff; + byte2 = header[HRES_MM_OFFSET + 1] & 0xff; + byte3 = header[HRES_MM_OFFSET + 2] & 0xff; + byte4 = header[HRES_MM_OFFSET + 3] & 0xff; + long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + byte1 = header[VRES_MM_OFFSET] & 0xff; + byte2 = header[VRES_MM_OFFSET + 1] & 0xff; + byte3 = header[VRES_MM_OFFSET + 2] & 0xff; + byte4 = header[VRES_MM_OFFSET + 3] & 0xff; + long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + byte1 = header[HRES_PIXEL_OFFSET] & 0xff; + byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff; + byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff; + byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff; + long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + byte1 = header[VRES_PIXEL_OFFSET] & 0xff; + byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff; + byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff; + byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff; + long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + + info.dpiHorizontal = hresPixel / (hresMM/25.4); + info.dpiVertical = vresPixel / (vresMM/25.4);; + + //width + byte1 = header[WIDTH_OFFSET] & 0xff; + byte2 = header[WIDTH_OFFSET + 1] & 0xff; + byte3 = header[WIDTH_OFFSET + 2] & 0xff; + byte4 = header[WIDTH_OFFSET + 3] & 0xff; + value = (long) ((byte4 << 24) | (byte3 << 16) + | (byte2 << 8) | byte1); + value = (long) (value / 100f / 25.4 * info.dpiHorizontal); + info.width = (int) (value & 0xffffffff); + + //height + byte1 = header[HEIGHT_OFFSET] & 0xff; + byte2 = header[HEIGHT_OFFSET + 1] & 0xff; + byte3 = header[HEIGHT_OFFSET + 2] & 0xff; + byte4 = header[HEIGHT_OFFSET + 3] & 0xff; + value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1); + value = (long) (value / 100f / 25.4 * info.dpiVertical); + info.height = (int) (value & 0xffffffff); + + return info; + } + + private byte[] getDefaultHeader(InputStream imageStream) + throws IOException { + byte[] header = new byte[EMF_SIG_LENGTH]; + try { + imageStream.mark(EMF_SIG_LENGTH + 1); + imageStream.read(header); + imageStream.reset(); + } catch (IOException ex) { + try { + imageStream.reset(); + } catch (IOException exbis) { + // throw the original exception, not this one + } + throw ex; + } + return header; + } +} diff --git a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java index 826f4b60f..853508761 100644 --- a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java +++ b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java @@ -50,6 +50,7 @@ public class ImageReaderFactory { registerFormat(new PNGReader()); registerFormat(new TIFFReader()); registerFormat(new EPSReader()); + registerFormat(new EMFReader()); // the xml parser through batik closes the stream when finished // so there is a workaround in the SVGReader registerFormat(new SVGReader()); diff --git a/src/java/org/apache/fop/render/rtf/RTFHandler.java b/src/java/org/apache/fop/render/rtf/RTFHandler.java index 4c08d80e7..6487b5394 100644 --- a/src/java/org/apache/fop/render/rtf/RTFHandler.java +++ b/src/java/org/apache/fop/render/rtf/RTFHandler.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.Iterator; +import org.apache.fop.*; // Libs import org.apache.commons.logging.Log; @@ -86,6 +87,8 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.IRtfTableContainer; import org.apache.fop.render.rtf.rtflib.tools.BuilderContext; import org.apache.fop.render.rtf.rtflib.tools.TableContext; import org.apache.fop.fonts.FontSetup; +import org.apache.fop.image.FopImage; +import org.apache.fop.image.ImageFactory; /** * RTF Handler: generates RTF output using the structure events from @@ -938,21 +941,72 @@ public class RTFHandler extends FOEventHandler { final RtfExternalGraphic newGraphic = c.getTextrun().newImage(); - //Property p = null; - - //get source file - newGraphic.setURL(eg.getSrc()); + //set URL + String url = eg.getURL(); + newGraphic.setURL(url); + + //set image data + ImageFactory fact = ImageFactory.getInstance(); + FopImage fopimage = fact.getImage(url, eg.getUserAgent()); + fopimage.load(fopimage.ORIGINAL_DATA); - //get scaling + newGraphic.setImageData(fopimage.getRessourceBytes()); + + //set scaling if (eg.getScaling() == Constants.EN_UNIFORM) { newGraphic.setScaling ("uniform"); } //get width - newGraphic.setWidth(eg.getWidth().getValue() / 1000f + "pt"); + int width = 0; + if (eg.getWidth().getEnum() == Constants.EN_AUTO) { + width = fopimage.getIntrinsicWidth(); + } else { + width = eg.getWidth().getValue(); + } //get height - newGraphic.setHeight(eg.getHeight().getValue() / 1000f + "pt"); + int height = 0; + if (eg.getWidth().getEnum() == Constants.EN_AUTO) { + height = fopimage.getIntrinsicHeight(); + } else { + height = eg.getHeight().getValue(); + } + + //get content-width + int contentwidth = 0; + if (eg.getContentWidth().getEnum() + == Constants.EN_AUTO) { + contentwidth = fopimage.getIntrinsicWidth(); + } else if(eg.getContentWidth().getEnum() + == Constants.EN_SCALE_TO_FIT) { + contentwidth = width; + } else { + //TODO: check, if the value is a percent value + contentwidth = eg.getContentWidth().getValue(); + } + + //get content-width + int contentheight = 0; + if (eg.getContentHeight().getEnum() + == Constants.EN_AUTO) { + + contentheight = fopimage.getIntrinsicHeight(); + + } else if(eg.getContentHeight().getEnum() + == Constants.EN_SCALE_TO_FIT) { + + contentheight = height; + } else { + //TODO: check, if the value is a percent value + contentheight = eg.getContentHeight().getValue(); + } + + //set width in rtf + newGraphic.setWidth((long) (contentwidth / 1000f) + "pt"); + + //set height in rtf + newGraphic.setHeight((long) (contentheight / 1000f) + "pt"); //TODO: make this configurable: // int compression = m_context.m_options.getRtfExternalGraphicCompressionRate (); diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java index c34f19b5f..5f0bb1e3d 100644 --- a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java +++ b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfExternalGraphic.java @@ -105,7 +105,6 @@ public class RtfExternalGraphic extends RtfElement { */ public static FormatBase determineFormat(byte[] data) { - int type = ImageConstants.I_NOT_SUPPORTED; if (FormatPNG.isFormat(data)) { return new FormatPNG(); @@ -361,18 +360,19 @@ public class RtfExternalGraphic extends RtfElement { // getRtfFile ().getLog ().logInfo ("Writing image '" + url + "'."); - imagedata = null; - try { - final InputStream in = url.openStream(); + if (imagedata == null) { try { - imagedata = IOUtils.toByteArray(url.openStream()); - } finally { - IOUtils.closeQuietly(in); - } - } catch (Exception e) { - throw new ExternalGraphicException("The attribute 'src' of " - + " has a invalid value: '" - + url + "' (" + e + ")"); + final InputStream in = url.openStream(); + try { + imagedata = IOUtils.toByteArray(url.openStream()); + } finally { + IOUtils.closeQuietly(in); + } + } catch (Exception e) { + throw new ExternalGraphicException("The attribute 'src' of " + + " has a invalid value: '" + + url + "' (" + e + ")"); + } } if (imagedata == null) { @@ -463,8 +463,18 @@ public class RtfExternalGraphic extends RtfElement { height = ImageUtil.getIntFromByteArray(imagedata, basis, 2, true); } } else if (imageformat.getType() == ImageConstants.I_EMF) { - width = ImageUtil.getIntFromByteArray(imagedata, 151, 4, false); - height = ImageUtil.getIntFromByteArray(imagedata, 155, 4, false); + int i = 0; + + i = ImageUtil.getIntFromByteArray(imagedata, 151, 4, false); + if (i != 0 ) { + width = i; + } + + i = ImageUtil.getIntFromByteArray(imagedata, 155, 4, false); + if (i != 0 ) { + height = i; + } + } } @@ -546,6 +556,16 @@ public class RtfExternalGraphic extends RtfElement { this.scaleUniform = true; } } + + /** + * Sets the binary imagedata of the image. + * + * @param imagedata Binary imagedata as read from file. + * @throws IOException On error + */ + public void setImageData(byte[] imagedata) throws IOException { + this.imagedata = imagedata; + } /** * Sets the url of the image. -- cgit v1.2.3