001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.img; 020 021import java.awt.image.BufferedImage; 022import java.awt.image.ColorModel; 023import java.awt.image.IndexColorModel; 024import java.io.IOException; 025 026import javax.imageio.stream.ImageInputStream; 027 028import lucee.commons.io.IOUtil; 029import lucee.commons.io.res.Resource; 030import lucee.commons.io.res.util.ResourceUtil; 031import lucee.commons.lang.ExceptionUtil; 032import lucee.commons.lang.StringUtil; 033import lucee.runtime.img.coder.Coder; 034 035import org.apache.commons.codec.binary.Base64; 036 037public class ImageUtil { 038 039 private static Coder coder; 040 041 static { 042 coder = Coder.getInstance(); 043 } 044 045 046 047 public static String[] getWriterFormatNames() { 048 return coder.getWriterFormatNames(); 049 } 050 public static String[] getReaderFormatNames() { 051 return coder.getReaderFormatNames(); 052 } 053 054 055 /** 056 * translate a file resource to a buffered image 057 * @param res 058 * @return 059 * @throws IOException 060 */ 061 public static BufferedImage toBufferedImage(Resource res,String format) throws IOException { 062 return coder.toBufferedImage(res, format); 063 } 064 065 /** 066 * translate a binary array to a buffered image 067 * @param binary 068 * @return 069 * @throws IOException 070 */ 071 public static BufferedImage toBufferedImage(byte[] bytes,String format) throws IOException { 072 return coder.toBufferedImage(bytes, format); 073 } 074 075 076 077 078 079 public static byte[] readBase64(String b64str, StringBuilder mimetype) throws IOException { 080 if(StringUtil.isEmpty(b64str)) 081 throw new IOException("base64 string is empty"); 082 083 // data:image/png;base64, 084 int index = b64str.indexOf("base64,"); 085 if(index!=-1){ 086 int semiIndex=b64str.indexOf(";"); 087 if(mimetype!=null && semiIndex<index && StringUtil.startsWithIgnoreCase(b64str, "data:")){ 088 mimetype.append(b64str.substring(5,semiIndex).trim()); 089 } 090 091 b64str=b64str.substring(index + 7); 092 } 093 094 return Base64.decodeBase64(b64str.getBytes()); 095 } 096 097 public static String getFormat(Resource res) throws IOException { 098 String ext=getFormatFromExtension(res,null); 099 if(ext!=null) return ext; 100 String mt=ResourceUtil.getMimeType(res, null); 101 if(mt==null) return null;//throw new IOException("can't extract mimetype from ["+res+"]"); 102 return getFormatFromMimeType(mt); 103 } 104 105 public static String getFormat(byte[] binary) throws IOException { 106 return getFormatFromMimeType(IOUtil.getMimeType(binary, "")); 107 } 108 109 public static String getFormat(byte[] binary,String defaultValue) { 110 return getFormatFromMimeType(IOUtil.getMimeType(binary, ""),defaultValue); 111 } 112 113 public static String getFormatFromExtension(Resource res, String defaultValue) { 114 String ext=ResourceUtil.getExtension(res,null); 115 if("gif".equalsIgnoreCase(ext))return "gif"; 116 if("jpg".equalsIgnoreCase(ext))return "jpg"; 117 if("jpe".equalsIgnoreCase(ext))return "jpg"; 118 if("jpeg".equalsIgnoreCase(ext))return "jpg"; 119 if("png".equalsIgnoreCase(ext))return "png"; 120 if("tiff".equalsIgnoreCase(ext))return "tiff"; 121 if("tif".equalsIgnoreCase(ext))return "tiff"; 122 if("bmp".equalsIgnoreCase(ext))return "bmp"; 123 if("bmp".equalsIgnoreCase(ext))return "bmp"; 124 if("wbmp".equalsIgnoreCase(ext))return "wbmp"; 125 if("ico".equalsIgnoreCase(ext))return "bmp"; 126 if("wbmp".equalsIgnoreCase(ext))return "wbmp"; 127 if("psd".equalsIgnoreCase(ext))return "psd"; 128 if("fpx".equalsIgnoreCase(ext))return "fpx"; 129 130 if("pnm".equalsIgnoreCase(ext))return "pnm"; 131 if("pgm".equalsIgnoreCase(ext))return "pgm"; 132 if("pbm".equalsIgnoreCase(ext))return "pbm"; 133 if("ppm".equalsIgnoreCase(ext))return "ppm"; 134 return defaultValue; 135 } 136 137 138 139 140 public static String getFormatFromMimeType(String mt) throws IOException { 141 String format = getFormatFromMimeType(mt, null); 142 if(format!=null) return format; 143 144 if(StringUtil.isEmpty(mt))throw new IOException("cannot find Format of given image");//31 145 throw new IOException("can't find Format ("+mt+") of given image"); 146 } 147 148 public static String getFormatFromMimeType(String mt, String defaultValue) { 149 if("image/gif".equals(mt)) return "gif"; 150 if("image/gi_".equals(mt)) return "gif"; 151 152 if("image/jpeg".equals(mt)) return "jpg"; 153 if("image/jpg".equals(mt)) return "jpg"; 154 if("image/jpe".equals(mt)) return "jpg"; 155 if("image/pjpeg".equals(mt)) return "jpg"; 156 if("image/vnd.swiftview-jpeg".equals(mt)) return "jpg"; 157 if("image/pipeg".equals(mt)) return "jpg"; 158 if("application/x-jpg".equals(mt)) return "jpg"; 159 if("application/jpg".equals(mt)) return "jpg"; 160 if("image/jp_".equals(mt)) return "jpg"; 161 162 if("image/png".equals(mt)) return "png"; 163 if("image/x-png".equals(mt))return "png"; 164 if("application/x-png".equals(mt)) return "png"; 165 if("application/png".equals(mt)) return "png"; 166 167 if("image/tiff".equals(mt)) return "tiff"; 168 if("image/tif".equals(mt)) return "tiff"; 169 if("image/x-tif".equals(mt)) return "tiff"; 170 if("image/x-tiff".equals(mt)) return "tiff"; 171 if("application/tif".equals(mt)) return "tiff"; 172 if("application/x-tif".equals(mt)) return "tiff"; 173 if("application/tiff".equals(mt)) return "tiff"; 174 if("application/x-tiff".equals(mt)) return "tiff"; 175 176 if("image/bmp".equals(mt)) return "bmp"; 177 if("image/vnd.wap.wbmp".equals(mt)) return "wbmp"; 178 179 if("image/fpx".equals(mt)) return "fpx"; 180 if("image/x-fpx".equals(mt)) return "fpx"; 181 if("image/vnd.fpx".equals(mt)) return "fpx"; 182 if("image/vnd.netfpx".equals(mt)) return "fpx"; 183 if("image/vnd.fpx".equals(mt)) return "fpx"; 184 if("application/vnd.netfpx".equals(mt)) return "fpx"; 185 if("application/vnd.fpx".equals(mt)) return "fpx"; 186 187 if("image/x-portable-anymap".equals(mt)) return "pnm"; 188 if("image/x-portable/anymap".equals(mt)) return "pnm"; 189 if("image/x-pnm".equals(mt)) return "pnm"; 190 if("image/pnm".equals(mt)) return "pnm"; 191 192 if("image/x-portable-graymap".equals(mt)) return "pgm"; 193 if("image/x-portable/graymap".equals(mt)) return "pgm"; 194 if("image/x-pgm".equals(mt)) return "pgm"; 195 if("image/pgm".equals(mt)) return "pgm"; 196 197 if("image/portable bitmap".equals(mt)) return "pbm"; 198 if("image/x-portable-bitmap".equals(mt)) return "pbm"; 199 if("image/x-portable/bitmap".equals(mt)) return "pbm"; 200 if("image/x-pbm".equals(mt)) return "pbm"; 201 if("image/pbm".equals(mt)) return "pbm"; 202 203 if("image/x-portable-pixmap".equals(mt)) return "ppm"; 204 if("application/ppm".equals(mt)) return "ppm"; 205 if("application/x-ppm".equals(mt)) return "ppm"; 206 if("image/x-p".equals(mt)) return "ppm"; 207 if("image/x-ppm".equals(mt)) return "ppm"; 208 if("image/ppm".equals(mt)) return "ppm"; 209 210 if("image/ico".equals(mt)) return "ico"; 211 if("image/x-icon".equals(mt)) return "ico"; 212 if("application/ico".equals(mt)) return "ico"; 213 if("application/x-ico".equals(mt)) return "ico"; 214 215 if("image/photoshop".equals(mt)) return "psd"; 216 if("image/x-photoshop".equals(mt)) return "psd"; 217 if("image/psd".equals(mt)) return "psd"; 218 if("application/photoshop".equals(mt)) return "psd"; 219 if("application/psd".equals(mt)) return "psd"; 220 if("zz-application/zz-winassoc-psd".equals(mt)) return "psd"; 221 222 // can not terminate this types exactly 223 // image/x-xbitmap 224 // application/x-win-bitmap 225 // image/x-win-bitmap 226 // application/octet-stream 227 return defaultValue; 228 } 229 230 231 public static String getMimeTypeFromFormat(String mt) throws IOException { 232 if("gif".equals(mt)) return "image/gif"; 233 if("jpeg".equals(mt)) return "image/jpg"; 234 if("jpg".equals(mt)) return "image/jpg"; 235 if("jpe".equals(mt)) return "image/jpg"; 236 if("png".equals(mt)) return "image/png"; 237 if("tiff".equals(mt)) return "image/tiff"; 238 if("tif".equals(mt)) return "image/tiff"; 239 if("bmp".equals(mt)) return "image/bmp"; 240 if("bmp".equals(mt)) return "image/bmp"; 241 if("wbmp".equals(mt)) return "image/vnd.wap.wbmp"; 242 if("fpx".equals(mt)) return "image/fpx"; 243 244 if("pgm".equals(mt)) return "image/x-portable-graymap"; 245 if("pnm".equals(mt)) return "image/x-portable-anymap"; 246 if("pbm".equals(mt)) return "image/x-portable-bitmap"; 247 if("ppm".equals(mt)) return "image/x-portable-pixmap"; 248 249 if("ico".equals(mt)) return "image/ico"; 250 if("psd".equals(mt)) return "image/psd"; 251 252 if(StringUtil.isEmpty(mt))throw new IOException("can't find Format of given image");//31 253 throw new IOException("can't find Format ("+mt+") of given image"); 254 } 255 256 public static void closeEL(ImageInputStream iis) { 257 try { 258 if(iis!=null)iis.close(); 259 } 260 catch (Throwable t) { 261 ExceptionUtil.rethrowIfNecessary(t); 262 } 263 264 265 } 266 267 public static BufferedImage createBufferedImage(BufferedImage image, int columns, int rows) { 268 ColorModel colormodel = image.getColorModel(); 269 BufferedImage newImage; 270 if(colormodel instanceof IndexColorModel) { 271 if(colormodel.getTransparency() != 1) 272 newImage = new BufferedImage(columns, rows, 2); 273 else 274 newImage = new BufferedImage(columns, rows, 1); 275 } 276 else { 277 newImage = new BufferedImage(colormodel, image.getRaster().createCompatibleWritableRaster(columns, rows), colormodel.isAlphaPremultiplied(), null); 278 } 279 return newImage; 280 } 281 282 public static BufferedImage createBufferedImage(BufferedImage image) { 283 return createBufferedImage(image, image.getWidth(), image.getHeight()); 284 } 285}