001package com.hfg.image; 002 003import java.awt.Dimension; 004import java.awt.Image; 005import java.awt.image.BufferedImage; 006import java.io.File; 007import java.io.FileInputStream; 008import java.io.FileOutputStream; 009import java.io.IOException; 010import java.io.InputStream; 011import java.io.OutputStream; 012import java.util.Iterator; 013import java.util.Locale; 014import javax.imageio.IIOImage; 015import javax.imageio.ImageIO; 016import javax.imageio.ImageReader; 017import javax.imageio.ImageTypeSpecifier; 018import javax.imageio.ImageWriteParam; 019import javax.imageio.ImageWriter; 020import javax.imageio.metadata.IIOMetadata; 021import javax.imageio.plugins.jpeg.JPEGImageWriteParam; 022import javax.imageio.stream.FileImageOutputStream; 023import javax.imageio.stream.ImageOutputStream; 024 025import com.hfg.util.StringUtil; 026 027//------------------------------------------------------------------------------ 028/** 029 * General Image IO functions using ImageIO. 030 * 031 * @author J. Alex Taylor, hairyfatguy.com 032 */ 033//------------------------------------------------------------------------------ 034// com.hfg XML/HTML Coding Library 035// 036// This library is free software; you can redistribute it and/or 037// modify it under the terms of the GNU Lesser General Public 038// License as published by the Free Software Foundation; either 039// version 2.1 of the License, or (at your option) any later version. 040// 041// This library is distributed in the hope that it will be useful, 042// but WITHOUT ANY WARRANTY; without even the implied warranty of 043// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 044// Lesser General Public License for more details. 045// 046// You should have received a copy of the GNU Lesser General Public 047// License along with this library; if not, write to the Free Software 048// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 049// 050// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 051// jataylor@hairyfatguy.com 052//------------------------------------------------------------------------------ 053 054public class ImageIO_Util 055{ 056 public static float DEFAULT_JPG_QUALITY = 0.85f; 057 058 static 059 { 060 ImageIO.scanForPlugins(); 061 } 062 063 //-------------------------------------------------------------------------- 064 public static void writeBufferedImageAsJpeg(BufferedImage inImage, OutputStream inStream) 065 throws IOException 066 { 067 writeBufferedImageAsJpeg(inImage, inStream, DEFAULT_JPG_QUALITY); 068 } 069 070 //-------------------------------------------------------------------------- 071 public static void writeBufferedImageAsJpeg(BufferedImage inBufferedImage, OutputStream inStream, float inJpgQuality) 072 throws IOException 073 { 074 ImageWriter jpegWriter = ImageIO.getImageWritersByFormatName("JPEG").next(); 075 076 ImageWriteParam params = jpegWriter.getDefaultWriteParam(); 077 params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 078 params.setCompressionQuality(inJpgQuality); 079 080 ImageOutputStream out = ImageIO.createImageOutputStream(inStream); 081 jpegWriter.setOutput(out); 082 jpegWriter.write(null, new IIOImage(inBufferedImage,null,null),params); 083 jpegWriter.dispose(); 084 } 085 086 //--------------------------------------------------------------------------- 087 public static Dimension getDimension(File inImgFile) 088 { 089 Dimension dimension; 090 try 091 { 092 BufferedImage image = ImageIO.read(inImgFile); 093 dimension = new Dimension(image.getWidth(), image.getHeight()); 094 } 095 catch (IOException e) 096 { 097 throw new RuntimeException(e); 098 } 099 100 return dimension; 101 } 102 103 //--------------------------------------------------------------------------- 104 public static Dimension getDimension(InputStream inImgStream) 105 { 106 Dimension dimension; 107 try 108 { 109 BufferedImage image = ImageIO.read(inImgStream); 110 dimension = new Dimension(image.getWidth(), image.getHeight()); 111 } 112 catch (IOException e) 113 { 114 throw new RuntimeException(e); 115 } 116 117 return dimension; 118 } 119 120 //--------------------------------------------------------------------------- 121 public static Dimension getDimension(InputStream inImgStream, ImageFormat inFormat) 122 { 123 Dimension dimension; 124 try 125 { 126 Iterator<ImageReader> readerIterator = ImageIO.getImageReadersBySuffix(inFormat.getFileExtension()); 127 ImageReader imgReader = null; 128 if (readerIterator.hasNext()) 129 { 130 imgReader = readerIterator.next(); 131 } 132 133 if (imgReader == null) 134 { 135 throw new RuntimeException("Reader for " + inFormat.name() + " not found."); 136 } 137 138 imgReader.setInput(ImageIO.createImageInputStream(inImgStream), true); 139 140 BufferedImage image = imgReader.read(0); 141 142 dimension = new Dimension(image.getWidth(), image.getHeight()); 143 } 144 catch (IOException e) 145 { 146 throw new RuntimeException(e); 147 } 148 149 return dimension; 150 } 151 152 //-------------------------------------------------------------------------- 153 public static void convertImage(File inOrigImg, File inDestImg, float inCompressionQuality) 154 { 155 ImageFormat destFormat = ImageFormat.guessFormatFromName(inDestImg.getName()); 156 157 try 158 { 159 // Read input image from file 160 BufferedImage srcImage = readImageFile(inOrigImg); 161 162 if (destFormat == ImageFormat.JPEG) 163 { 164 Iterator<ImageWriter> writerIter = ImageIO.getImageWritersBySuffix(destFormat.getFileExtension()); 165 ImageWriteParam param = new JPEGImageWriteParam(Locale.getDefault()); 166 param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 167 param.setCompressionQuality(inCompressionQuality); 168 ImageWriter writer =writerIter.next(); 169 IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(srcImage), param); 170 ImageOutputStream outputStream = new FileImageOutputStream(inDestImg); 171 writer.setOutput(outputStream); 172 writer.write(metadata, new IIOImage(srcImage, null, metadata), param); 173 writer.dispose(); 174 outputStream.close(); 175 } 176 else 177 { 178 FileOutputStream outputStream = null; 179 try 180 { 181 outputStream = new FileOutputStream(inDestImg); 182 // Format to be converted to can be one of: jpeg, png, bmp, wbmp, and gif 183 ImageIO.write(srcImage, destFormat.getFileExtension(), outputStream); 184 } 185 finally 186 { 187 if (outputStream != null) outputStream.close(); 188 } 189 } 190 } 191 catch (IOException e) 192 { 193 throw new RuntimeException(e); 194 } 195 } 196 /* 197 BufferedImage sourceImage = ImageIO.read(inputStream); 198 Image thumbnail = sourceImage.getScaledInstance(width, -1, Image.SCALE_SMOOTH); 199 BufferedImage bufferedThumbnail = new BufferedImage(thumbnail.getWidth(null), 200 thumbnail.getHeight(null), 201 BufferedImage.TYPE_INT_RGB); 202 bufferedThumbnail.getGraphics().drawImage(thumbnail, 0, 0, null); 203 ImageIO.write(bufferedThumbnail, "jpeg", outputStream); 204 */ 205 206 207 //-------------------------------------------------------------------------- 208 209 /** 210 If the destination format is JPG, a default compression quality of 0.7 is used. 211 */ 212 public static void scaleDownImage(File inImgFile, int inMaxDimension, File inDestFile) 213 { 214 scaleDownImage(inImgFile, inMaxDimension, inDestFile, 0.7f); 215 } 216 217 //--------------------------------------------------------------------------- 218 public static void scaleDownImage(File inOrigImgFile, int inMaxDimension, File inDestImgFile, float inCompressionQuality) 219 { 220 if (null == inOrigImgFile) 221 { 222 throw new RuntimeException("No source image was specified!"); 223 } 224 225 ImageFormat destFormat = ImageFormat.guessFormatFromName(inDestImgFile.getName()); 226 227 try 228 { 229 // Read input image from file 230 BufferedImage sourceImage = readImageFile(inOrigImgFile); 231 232 int width = -1; 233 int height = -1; 234 if (sourceImage.getWidth() > sourceImage.getHeight()) 235 { 236 width = inMaxDimension; 237 } 238 else 239 { 240 height = inMaxDimension; 241 } 242 243 Image resizedImage = sourceImage.getScaledInstance(width, height, Image.SCALE_SMOOTH); 244 // Allocate a new BufferedImage 245 BufferedImage bufferedResizedImage = new BufferedImage(resizedImage.getWidth(null), 246 resizedImage.getHeight(null), 247 BufferedImage.TYPE_INT_RGB); 248 // Draw the resized image onto the new BufferedImage 249 bufferedResizedImage.getGraphics().drawImage(resizedImage, 0, 0, null); 250 251 if (destFormat == ImageFormat.JPEG) 252 { 253 Iterator<ImageWriter> writerIter = ImageIO.getImageWritersBySuffix(destFormat.getFileExtension()); 254 ImageWriteParam param = new JPEGImageWriteParam(Locale.getDefault()); 255 param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 256 param.setCompressionQuality(inCompressionQuality); 257 ImageWriter writer =writerIter.next(); 258 IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedResizedImage), param); 259 ImageOutputStream outputStream = new FileImageOutputStream(inDestImgFile); 260 writer.setOutput(outputStream); 261 writer.write(metadata, new IIOImage(bufferedResizedImage, null, metadata), param); 262 writer.dispose(); 263 outputStream.close(); 264 } 265 else 266 { 267 FileOutputStream outputStream = null; 268 try 269 { 270 outputStream = new FileOutputStream(inDestImgFile); 271 // Format to be converted to can be one of: jpeg, png, bmp, wbmp, and gif 272 if (! ImageIO.write(bufferedResizedImage, destFormat.getFileExtension(), outputStream)) 273 { 274 String msg = "The destination image " + StringUtil.singleQuote(inDestImgFile) + " couldn't be written!"; 275 if (destFormat.equals(ImageFormat.TIFF)) 276 { 277 msg += " The jai-imageio-core jar is needed to read/write TIFF format."; 278 } 279 280 throw new RuntimeException(msg); 281 } 282 } 283 finally 284 { 285 if (outputStream != null) outputStream.close(); 286 } 287 } 288 } 289 catch (IOException e) 290 { 291 throw new RuntimeException(e); 292 } 293 } 294 295 296 //-------------------------------------------------------------------------- 297 private static BufferedImage readImageFile(File inSrcImg) 298 throws IOException 299 { 300 BufferedImage srcImage = null; 301 302 ImageFormat srcFormat = ImageFormat.guessFormatFromName(inSrcImg.getName()); 303 304 FileInputStream inputStream = null; 305 try 306 { 307 inputStream = new FileInputStream(inSrcImg); 308 309 // Read input image from file 310 srcImage = ImageIO.read(inputStream); 311 if (null == srcImage) 312 { 313 String msg = "The input image " + StringUtil.singleQuote(inSrcImg) + " couldn't be read!"; 314 if (srcFormat != null 315 && srcFormat.equals(ImageFormat.TIFF)) 316 { 317 msg += " The jai-imageio-core jar is needed to read/write TIFF format."; 318 } 319 320 throw new RuntimeException(msg); 321 } 322 } 323 finally 324 { 325 if (inputStream != null) inputStream.close(); 326 } 327 328 return srcImage; 329 } 330 331}