001 /* 002 * 003 004 Licensed under the Apache License, Version 2.0 (the "License"); 005 you may not use this file except in compliance with the License. 006 You may obtain a copy of the License at 007 008 http://www.apache.org/licenses/LICENSE-2.0 009 010 Unless required by applicable law or agreed to in writing, software 011 distributed under the License is distributed on an "AS IS" BASIS, 012 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 See the License for the specific language governing permissions and 014 limitations under the License. 015 */ 016 017 package railo.runtime.img.filter;import java.awt.image.BufferedImage; 018 import java.awt.image.ColorModel; 019 import java.awt.image.WritableRaster; 020 021 import railo.runtime.engine.ThreadLocalPageContext; 022 import railo.runtime.exp.FunctionException; 023 import railo.runtime.exp.PageException; 024 import railo.runtime.img.ImageUtil; 025 import railo.runtime.type.KeyImpl; 026 import railo.runtime.type.List; 027 import railo.runtime.type.Struct; 028 029 /** 030 * A filter which flips images or rotates by multiples of 90 degrees. 031 */ 032 public class FlipFilter extends AbstractBufferedImageOp implements DynFiltering { 033 034 /** 035 * Flip the image horizontally. 036 */ 037 public static final int FLIP_H = 1; 038 039 /** 040 * Flip the image vertically. 041 */ 042 public static final int FLIP_V = 2; 043 044 /** 045 * Flip the image horizontally and vertically. 046 */ 047 public static final int FLIP_HV = 3; 048 049 /** 050 * Rotate the image 90 degrees clockwise. 051 */ 052 public static final int FLIP_90CW = 4; 053 054 /** 055 * Rotate the image 90 degrees counter-clockwise. 056 */ 057 public static final int FLIP_90CCW = 5; 058 059 /** 060 * Rotate the image 180 degrees. 061 */ 062 public static final int FLIP_180 = 6; 063 064 private int operation; 065 private int width, height; 066 private int newWidth, newHeight; 067 068 /** 069 * Construct a FlipFilter which flips horizontally and vertically. 070 */ 071 public FlipFilter() { 072 this(FLIP_HV); 073 } 074 075 /** 076 * Construct a FlipFilter. 077 * @param operation the filter operation 078 */ 079 public FlipFilter(int operation) { 080 this.operation = operation; 081 } 082 083 /** 084 * Set the filter operation. 085 * @param operation the filter operation 086 * @see #getOperation 087 */ 088 public void setOperation(int operation) { 089 this.operation = operation; 090 } 091 092 /** 093 * Get the filter operation. 094 * @return the filter operation 095 * @see #setOperation 096 */ 097 public int getOperation() { 098 return operation; 099 } 100 101 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 102 int width = src.getWidth(); 103 int height = src.getHeight(); 104 int type = src.getType(); 105 WritableRaster srcRaster = src.getRaster(); 106 107 int[] inPixels = getRGB( src, 0, 0, width, height, null ); 108 109 int x = 0, y = 0; 110 int w = width; 111 int h = height; 112 113 int newX = 0; 114 int newY = 0; 115 int newW = w; 116 int newH = h; 117 switch (operation) { 118 case FLIP_H: 119 newX = width - (x + w); 120 break; 121 case FLIP_V: 122 newY = height - (y + h); 123 break; 124 case FLIP_HV: 125 newW = h; 126 newH = w; 127 newX = y; 128 newY = x; 129 break; 130 case FLIP_90CW: 131 newW = h; 132 newH = w; 133 newX = height - (y + h); 134 newY = x; 135 break; 136 case FLIP_90CCW: 137 newW = h; 138 newH = w; 139 newX = y; 140 newY = width - (x + w); 141 break; 142 case FLIP_180: 143 newX = width - (x + w); 144 newY = height - (y + h); 145 break; 146 } 147 148 int[] newPixels = new int[newW * newH]; 149 150 for (int row = 0; row < h; row++) { 151 for (int col = 0; col < w; col++) { 152 int index = row * width + col; 153 int newRow = row; 154 int newCol = col; 155 switch (operation) { 156 case FLIP_H: 157 newCol = w - col - 1; 158 break; 159 case FLIP_V: 160 newRow = h - row - 1; 161 break; 162 case FLIP_HV: 163 newRow = col; 164 newCol = row; 165 break; 166 case FLIP_90CW: 167 newRow = col; 168 newCol = h - row - 1;; 169 break; 170 case FLIP_90CCW: 171 newRow = w - col - 1; 172 newCol = row; 173 break; 174 case FLIP_180: 175 newRow = h - row - 1; 176 newCol = w - col - 1; 177 break; 178 } 179 int newIndex = newRow * newW + newCol; 180 newPixels[newIndex] = inPixels[index]; 181 } 182 } 183 184 if ( dst == null ) { 185 ColorModel dstCM = src.getColorModel(); 186 dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(newW, newH), dstCM.isAlphaPremultiplied(), null); 187 } 188 WritableRaster dstRaster = dst.getRaster(); 189 setRGB( dst, 0, 0, newW, newH, newPixels ); 190 191 return dst; 192 } 193 194 public String toString() { 195 switch (operation) { 196 case FLIP_H: 197 return "Flip Horizontal"; 198 case FLIP_V: 199 return "Flip Vertical"; 200 case FLIP_HV: 201 return "Flip Diagonal"; 202 case FLIP_90CW: 203 return "Rotate 90"; 204 case FLIP_90CCW: 205 return "Rotate -90"; 206 case FLIP_180: 207 return "Rotate 180"; 208 } 209 return "Flip"; 210 } 211 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 212 Object o; 213 if((o=parameters.removeEL(KeyImpl.init("Operation")))!=null)setOperation(ImageFilterUtil.toIntValue(o,"Operation")); 214 215 // check for arguments not supported 216 if(parameters.size()>0) { 217 throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+List.arrayToList(parameters.keysAsString(),", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Operation]"); 218 } 219 220 return filter(src, dst); 221 } 222 }