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 **/ 019/* 020* 021 022Licensed under the Apache License, Version 2.0 (the "License"); 023you may not use this file except in compliance with the License. 024You may obtain a copy of the License at 025 026 http://www.apache.org/licenses/LICENSE-2.0 027 028Unless required by applicable law or agreed to in writing, software 029distributed under the License is distributed on an "AS IS" BASIS, 030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 031See the License for the specific language governing permissions and 032limitations under the License. 033*/ 034 035package lucee.runtime.img.filter;import java.awt.Point; 036import java.awt.Rectangle; 037import java.awt.image.BufferedImage; 038 039import lucee.runtime.engine.ThreadLocalPageContext; 040import lucee.runtime.exp.FunctionException; 041import lucee.runtime.exp.PageException; 042import lucee.runtime.type.KeyImpl; 043import lucee.runtime.type.Struct; 044import lucee.runtime.type.util.CollectionUtil; 045 046/** 047 * A filter which rotates an image. These days this is easier done with Java2D, but this filter remains. 048 */ 049public class RotateFilter extends TransformFilter implements DynFiltering { 050 051 private float angle; 052 private float cos, sin; 053 private boolean resize = true; 054 055 /** 056 * Construct a RotateFilter. 057 */ 058 public RotateFilter() { 059 this(ImageMath.PI); 060 } 061 062 /** 063 * Construct a RotateFilter. 064 * @param angle the angle to rotate 065 */ 066 public RotateFilter(float angle) { 067 this(angle, true); 068 } 069 070 /** 071 * Construct a RotateFilter. 072 * @param angle the angle to rotate 073 * @param resize true if the output image should be resized 074 */ 075 public RotateFilter(float angle, boolean resize) { 076 setAngle(angle); 077 this.resize = resize; 078 } 079 080 /** 081 * Specifies the angle of rotation. 082 * @param angle the angle of rotation. 083 * @angle 084 * @see #getAngle 085 */ 086 public void setAngle(float angle) { 087 this.angle = angle; 088 cos = (float)Math.cos(this.angle); 089 sin = (float)Math.sin(this.angle); 090 } 091 092 /** 093 * Returns the angle of rotation. 094 * @return the angle of rotation. 095 * @see #setAngle 096 */ 097 public float getAngle() { 098 return angle; 099 } 100 101 protected void transformSpace(Rectangle rect) { 102 if (resize) { 103 Point out = new Point(0, 0); 104 int minx = Integer.MAX_VALUE; 105 int miny = Integer.MAX_VALUE; 106 int maxx = Integer.MIN_VALUE; 107 int maxy = Integer.MIN_VALUE; 108 int w = rect.width; 109 int h = rect.height; 110 int x = rect.x; 111 int y = rect.y; 112 113 for (int i = 0; i < 4; i++) { 114 switch (i) { 115 case 0: transform(x, y, out); break; 116 case 1: transform(x + w, y, out); break; 117 case 2: transform(x, y + h, out); break; 118 case 3: transform(x + w, y + h, out); break; 119 } 120 minx = Math.min(minx, out.x); 121 miny = Math.min(miny, out.y); 122 maxx = Math.max(maxx, out.x); 123 maxy = Math.max(maxy, out.y); 124 } 125 126 rect.x = minx; 127 rect.y = miny; 128 rect.width = maxx - minx; 129 rect.height = maxy - miny; 130 } 131 } 132 133 134 135 private void transform(int x, int y, Point out) { 136 out.x = (int)((x * cos) + (y * sin)); 137 out.y = (int)((y * cos) - (x * sin)); 138 } 139 140 protected void transformInverse(int x, int y, float[] out) { 141 out[0] = (x * cos) - (y * sin); 142 out[1] = (y * cos) + (x * sin); 143 } 144 145 public String toString() { 146 return "Rotate "+(int)(angle * 180 / Math.PI); 147 } 148 149 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException { 150 //BufferedImage dst=ImageUtil.createBufferedImage(src,src.getWidth()+400,src.getHeight()+400); 151 Object o; 152 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 153 if((o=parameters.removeEL(KeyImpl.init("EdgeAction")))!=null)setEdgeAction(ImageFilterUtil.toString(o,"EdgeAction")); 154 if((o=parameters.removeEL(KeyImpl.init("Interpolation")))!=null)setInterpolation(ImageFilterUtil.toString(o,"Interpolation")); 155 156 // check for arguments not supported 157 if(parameters.size()>0) { 158 throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+CollectionUtil.getKeyList(parameters,", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Angle, EdgeAction, Interpolation]"); 159 } 160 161 162 163 //Rectangle rect = new Rectangle(0, 0, src.getWidth(), src.getHeight()); 164 //transformSpace(rect); 165 BufferedImage dst=null;//ImageUtil.createBufferedImage(src,rect.width,rect.height); 166 167 return filter(src, dst); 168 } 169}