1 /* 2 * Copyright (c) 2002-2025 Gargoyle Software Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * https://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 package org.htmlunit.platform.image; 16 17 import java.io.IOException; 18 import java.io.InputStream; 19 import java.util.Iterator; 20 21 import javax.imageio.ImageIO; 22 import javax.imageio.ImageReader; 23 import javax.imageio.stream.ImageInputStream; 24 25 import org.htmlunit.platform.geom.IntDimension2D; 26 27 /** 28 * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br> 29 * 30 * Wraps the ImageReader for an HtmlImage. This is necessary because an object with a finalize() 31 * method is only garbage collected after the method has been run. Which causes all referenced 32 * objects to also not be garbage collected until this happens. Because a HtmlImage references a lot 33 * of objects which could all be garbage collected without impacting the ImageReader it is better to 34 * wrap it in another class. 35 * 36 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> 37 * @author David K. Taylor 38 * @author <a href="mailto:cse@dynabean.de">Christian Sell</a> 39 * @author Ahmed Ashour 40 * @author <a href="mailto:knut.johannes.dahle@gmail.com">Knut Johannes Dahle</a> 41 * @author Ronald Brill 42 * @author Frank Danek 43 * @author Carsten Steul 44 * @author Alex Gorbatovsky 45 */ 46 public class ImageIOImageData implements ImageData { 47 48 // private static final Log LOG = LogFactory.getLog(ImageIOImageData.class); 49 50 private final ImageReader imageReader_; 51 52 /** 53 * Ctor. 54 * @param inputStream the {@link InputStream} to read from 55 * @throws IOException in case of error 56 */ 57 public ImageIOImageData(final InputStream inputStream) throws IOException { 58 final ImageInputStream iis = ImageIO.createImageInputStream(inputStream); 59 final Iterator<ImageReader> iter = ImageIO.getImageReaders(iis); 60 if (!iter.hasNext()) { 61 iis.close(); 62 throw new IOException("No image detected in response"); 63 } 64 final ImageReader imageReader = iter.next(); 65 imageReader.setInput(iis); 66 67 imageReader_ = imageReader; 68 69 // dispose all others 70 while (iter.hasNext()) { 71 iter.next().dispose(); 72 } 73 } 74 75 /** 76 * @return the {@link ImageReader} 77 */ 78 public ImageReader getImageReader() { 79 return imageReader_; 80 } 81 82 /** 83 * {@inheritDoc} 84 */ 85 @Override 86 public IntDimension2D getWidthHeight() throws IOException { 87 return new IntDimension2D(imageReader_.getWidth(0), imageReader_.getHeight(0)); 88 } 89 90 /** 91 * {@inheritDoc} 92 */ 93 @Override 94 protected void finalize() throws Throwable { 95 close(); 96 super.finalize(); 97 } 98 99 @Override 100 @SuppressWarnings("PMD.UnusedLocalVariable") 101 public void close() throws IOException { 102 if (imageReader_ != null) { 103 try { 104 try (ImageInputStream stream = (ImageInputStream) imageReader_.getInput()) { 105 // nothing 106 } 107 } 108 finally { 109 imageReader_.setInput(null); 110 imageReader_.dispose(); 111 } 112 } 113 } 114 }