From 1aeb476ce7a680346ceacb59cf4596719f82c334 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Fri, 6 Nov 2009 19:08:41 +0000 Subject: [PATCH] release system resources when calling javax.imageio.ImageIO in Picture.resize() git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@833527 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../poi/hssf/usermodel/HSSFPicture.java | 59 +-------- .../org/apache/poi/ss/util/ImageUtils.java | 116 ++++++++++++++++++ .../poi/xssf/usermodel/XSSFPicture.java | 65 ++-------- 4 files changed, 126 insertions(+), 115 deletions(-) create mode 100755 src/java/org/apache/poi/ss/util/ImageUtils.java diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index f30245e365..a5e5baafff 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 48134 - release system resources when using Picture.resize() 48087 - avoid NPE in XSSFChartSheet when calling methods of the superclass 48038 - handle reading HWPF stylesheets from non zero offsets When running the "compile-ooxml-xsds" ant task, also generate the source jar for the OOXML Schemas diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java index 97c2f2ff29..f23fd92097 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFPicture.java @@ -21,6 +21,7 @@ import org.apache.poi.ddf.EscherBSERecord; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.ss.usermodel.Picture; +import org.apache.poi.ss.util.ImageUtils; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -208,29 +209,6 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { return cw == def ? PX_DEFAULT : PX_MODIFIED; } - /** - * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. - * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize - * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. - * - * @return array of two elements: {horisontalPdi, verticalDpi}. - * {96, 96} is the default. - */ - protected int[] getResolution(ImageReader r) throws IOException { - int hdpi=96, vdpi=96; - double mm2inch = 25.4; - - NodeList lst; - Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); - lst = node.getElementsByTagName("HorizontalPixelSize"); - if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - lst = node.getElementsByTagName("VerticalPixelSize"); - if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - return new int[]{hdpi, vdpi}; - } - /** * Return the dimension of this image * @@ -240,39 +218,6 @@ public final class HSSFPicture extends HSSFSimpleShape implements Picture { EscherBSERecord bse = _patriarch._sheet._book.getBSERecord(_pictureIndex); byte[] data = bse.getBlipRecord().getPicturedata(); int type = bse.getBlipTypeWin32(); - Dimension size = new Dimension(); - - switch (type){ - //we can calculate the preferred size only for JPEG and PNG - //other formats like WMF, EMF and PICT are not supported in Java - case HSSFWorkbook.PICTURE_TYPE_JPEG: - case HSSFWorkbook.PICTURE_TYPE_PNG: - case HSSFWorkbook.PICTURE_TYPE_DIB: - try { - //read the image using javax.imageio.* - ImageInputStream iis = ImageIO.createImageInputStream( new ByteArrayInputStream(data) ); - Iterator i = ImageIO.getImageReaders( iis ); - ImageReader r = i.next(); - r.setInput( iis ); - BufferedImage img = r.read(0); - - int[] dpi = getResolution(r); - - //if DPI is zero then assume standard 96 DPI - //since cannot divide by zero - if (dpi[0] == 0) dpi[0] = 96; - if (dpi[1] == 0) dpi[1] = 96; - - size.width = img.getWidth()*96/dpi[0]; - size.height = img.getHeight()*96/dpi[1]; - - } catch (IOException e){ - //silently return if ImageIO failed to read the image - log.log(POILogger.WARN, e); - } - - break; - } - return size; + return ImageUtils.getImageDimension(new ByteArrayInputStream(data), type); } } diff --git a/src/java/org/apache/poi/ss/util/ImageUtils.java b/src/java/org/apache/poi/ss/util/ImageUtils.java new file mode 100755 index 0000000000..76ebc0370c --- /dev/null +++ b/src/java/org/apache/poi/ss/util/ImageUtils.java @@ -0,0 +1,116 @@ +/* ==================================================================== + 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.poi.ss.util; + +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +import javax.imageio.ImageReader; +import javax.imageio.ImageIO; +import javax.imageio.stream.ImageInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.Iterator; + +/** + * @author Yegor Kozlov + */ +public class ImageUtils { + private static final POILogger logger = POILogFactory.getLogger(ImageUtils.class); + + public static final int PIXEL_DPI = 96; + + /** + * Return the dimension of this image + * + * @param is the stream containing the image data + * @param type type of the picture: {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_JPEG}, + * {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_PNG} or {@link org.apache.poi.ss.usermodel.Workbook#PICTURE_TYPE_DIB} + * + * @return image dimension in pixels + */ + public static Dimension getImageDimension(InputStream is, int type){ + Dimension size = new Dimension(); + + switch (type){ + //we can calculate the preferred size only for JPEG, PNG and BMP + //other formats like WMF, EMF and PICT are not supported in Java + case Workbook.PICTURE_TYPE_JPEG: + case Workbook.PICTURE_TYPE_PNG: + case Workbook.PICTURE_TYPE_DIB: + try { + //read the image using javax.imageio.* + ImageInputStream iis = ImageIO.createImageInputStream( is ); + Iterator i = ImageIO.getImageReaders( iis ); + ImageReader r = (ImageReader) i.next(); + r.setInput( iis ); + BufferedImage img = r.read(0); + + int[] dpi = getResolution(r); + + //if DPI is zero then assume standard 96 DPI + //since cannot divide by zero + if (dpi[0] == 0) dpi[0] = PIXEL_DPI; + if (dpi[1] == 0) dpi[1] = PIXEL_DPI; + + size.width = img.getWidth()*PIXEL_DPI/dpi[0]; + size.height = img.getHeight()*PIXEL_DPI/dpi[1]; + + r.dispose(); + iis.close(); + + } catch (IOException e){ + //silently return if ImageIO failed to read the image + logger.log(POILogger.WARN, e); + } + + break; + default: + logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); + } + return size; + } + + /** + * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. + * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize + * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. + * + * @return array of two elements: {horisontalPdi, verticalDpi}. + * {96, 96} is the default. + */ + public static int[] getResolution(ImageReader r) throws IOException { + int hdpi=96, vdpi=96; + double mm2inch = 25.4; + + NodeList lst; + Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); + lst = node.getElementsByTagName("HorizontalPixelSize"); + if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + lst = node.getElementsByTagName("VerticalPixelSize"); + if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); + + return new int[]{hdpi, vdpi}; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java index 72938e92bc..0a0fdf086b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPicture.java @@ -31,6 +31,7 @@ import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.ss.usermodel.Picture; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.ImageUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; @@ -277,65 +278,13 @@ public final class XSSFPicture extends XSSFShape implements Picture { * @return image dimension in pixels */ protected static Dimension getImageDimension(PackagePart part, int type){ - Dimension size = new Dimension(); - - switch (type){ - //we can calculate the preferred size only for JPEG, PNG and BMP - //other formats like WMF, EMF and PICT are not supported in Java - case Workbook.PICTURE_TYPE_JPEG: - case Workbook.PICTURE_TYPE_PNG: - case Workbook.PICTURE_TYPE_DIB: - try { - //read the image using javax.imageio.* - ImageInputStream iis = ImageIO.createImageInputStream( part.getInputStream() ); - Iterator i = ImageIO.getImageReaders( iis ); - ImageReader r = (ImageReader) i.next(); - r.setInput( iis ); - BufferedImage img = r.read(0); - - int[] dpi = getResolution(r); - - //if DPI is zero then assume standard 96 DPI - //since cannot divide by zero - if (dpi[0] == 0) dpi[0] = PIXEL_DPI; - if (dpi[1] == 0) dpi[1] = PIXEL_DPI; - - size.width = img.getWidth()*PIXEL_DPI/dpi[0]; - size.height = img.getHeight()*PIXEL_DPI/dpi[1]; - - } catch (IOException e){ - //silently return if ImageIO failed to read the image - logger.log(POILogger.WARN, e); - } - - break; - default: - logger.log(POILogger.WARN, "Only JPEG, PNG and DIB pictures can be automatically sized"); + try { + return ImageUtils.getImageDimension(part.getInputStream(), type); + } catch (IOException e){ + //return a "singulariry" if ImageIO failed to read the image + logger.log(POILogger.WARN, e); + return new Dimension(); } - return size; - } - - /** - * The metadata of PNG and JPEG can contain the width of a pixel in millimeters. - * Return the the "effective" dpi calculated as 25.4/HorizontalPixelSize - * and 25.4/VerticalPixelSize. Where 25.4 is the number of mm in inch. - * - * @return array of two elements: {horisontalPdi, verticalDpi}. - * {96, 96} is the default. - */ - protected static int[] getResolution(ImageReader r) throws IOException { - int hdpi = PIXEL_DPI, vdpi = PIXEL_DPI; - double mm2inch = 25.4; - - NodeList lst; - Element node = (Element)r.getImageMetadata(0).getAsTree("javax_imageio_1.0"); - lst = node.getElementsByTagName("HorizontalPixelSize"); - if(lst != null && lst.getLength() == 1) hdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - lst = node.getElementsByTagName("VerticalPixelSize"); - if(lst != null && lst.getLength() == 1) vdpi = (int)(mm2inch/Float.parseFloat(((Element)lst.item(0)).getAttribute("value"))); - - return new int[]{hdpi, vdpi}; } /** -- 2.39.5