/* * Copyright (C) 2000 - 2011 TagServlet Ltd * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://openbd.org/ * $Id: ImageResize.java 1839 2011-11-29 12:48:45Z alan $ * * Notes: * - scaleToSize() method tweeked by Heath Provost */ package com.naryx.tagfusion.expression.function.image; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.image.BufferedImage; import com.naryx.tagfusion.cfm.engine.cfArgStructData; import com.naryx.tagfusion.cfm.engine.cfBooleanData; import com.naryx.tagfusion.cfm.engine.cfData; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; public class ImageResize extends ImageInfo { private static final long serialVersionUID = 1L; public ImageResize() { min = 2; max = 4; setNamedParams( new String[]{ "name", "width", "height", "quality" } ); } public String[] getParamInfo() { return new String[] { "the image object", "width of the new image, can be a percentage value (add %) (blank/missing if to be scaled in proportion to height)", "height of the new image, can be a percentage value (add %) (blank/missing if to be scaled in proportion to width)", "values: bicubic (default), bilinear, nearest" }; } public java.util.Map getInfo(){ return makeInfo( "image", "Resizes the image to the values accordingly", ReturnType.BOOLEAN ); } public cfData execute( cfSession _session, cfArgStructData argStruct ) throws cfmRunTimeException{ cfImageData im = getImage( _session, argStruct ); String sw = getNamedStringParam(argStruct, "width", "" ).trim(); String sh = getNamedStringParam(argStruct, "height", "" ).trim(); if ( sw.length() == 0 && sh.length() == 0 ) { throwException(_session, "missing both width and height parameters. Specify at least one" ); } int targetWidth = -1, targetHeight = -1; if ( sw.length() != 0 ){ if ( sw.endsWith("%") ){ int percentage = Integer.valueOf( sw.substring(0,sw.length()-1) ).intValue(); targetWidth = (int)((double)im.getWidth() * (double)((double)percentage/100.0)); }else{ targetWidth = Integer.valueOf( sw ).intValue(); } } if ( sh.length() != 0 ){ if ( sh.endsWith("%") ){ int percentage = Integer.valueOf( sh.substring(0,sh.length()-1) ).intValue(); targetHeight = (int)((double)im.getHeight() * (double)((double)percentage/100.0)); }else{ targetHeight = Integer.valueOf( sh ).intValue(); } } if ( targetWidth == -1 ){ //this is now a scale of the target height double scale = (double)im.getWidth() / (double)im.getHeight(); targetWidth = (int)((double)targetHeight * scale); } if ( targetHeight == -1 ){ //this is now a scale of the target height double scale = (double)im.getWidth() / (double)im.getHeight(); targetHeight = (int)((double)targetWidth / scale); } String quality = getNamedStringParam(argStruct, "quality", "bicubic" ).toLowerCase(); Object rh = RenderingHints.VALUE_INTERPOLATION_BICUBIC; if ( quality.equals("bilinear") ){ rh = RenderingHints.VALUE_INTERPOLATION_BILINEAR; }else if ( quality.equals("nearest") ){ rh = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; } im.setImage( scaleToSize( im.getImage(), targetWidth, targetHeight, rh ) ); return cfBooleanData.TRUE; } private BufferedImage scaleToSize(BufferedImage img, int targetWidth, int targetHeight, Object interpolation) { if (targetWidth == img.getWidth() && targetHeight == img.getHeight()) { return img; } boolean higherQuality = ( // Set flag to use multi-step technique only if the // target size is less than 50% of the original size // and the interpolation mode is bilinear or bicubic (targetWidth < (int)(img.getWidth() * 0.5)) && ( (interpolation == RenderingHints.VALUE_INTERPOLATION_BILINEAR) || (interpolation == RenderingHints.VALUE_INTERPOLATION_BICUBIC) ) ); int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; BufferedImage ret = (BufferedImage) img; int w, h; if (higherQuality) { // Use multi-step technique: start with original size, then // scale down in multiple passes with drawImage() // until the target size is reached w = img.getWidth(); h = img.getHeight(); } else { // Use one-step technique: scale directly from original // size to target size with a single drawImage() call w = targetWidth; h = targetHeight; } do { if (higherQuality && w > targetWidth) { w /= 2; if (w < targetWidth) { w = targetWidth; } } if (higherQuality && h > targetHeight) { h /= 2; if (h < targetHeight) { h = targetHeight; } } BufferedImage tmp = new BufferedImage(w, h, type); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, interpolation ); g2.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY ); g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; } while (w != targetWidth || h != targetHeight); return ret; } }