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.Rectangle; 018 import java.awt.image.BufferedImage; 019 020 import railo.runtime.engine.ThreadLocalPageContext; 021 import railo.runtime.exp.FunctionException; 022 import railo.runtime.exp.PageException; 023 import railo.runtime.img.ImageUtil; 024 import railo.runtime.type.KeyImpl; 025 import railo.runtime.type.Struct; 026 import railo.runtime.type.util.CollectionUtil; 027 028 public class ShearFilter extends TransformFilter implements DynFiltering { 029 030 private float xangle = 0.0f; 031 private float yangle = 0.0f; 032 private float shx = 0.0f; 033 private float shy = 0.0f; 034 private float xoffset = 0.0f; 035 private float yoffset = 0.0f; 036 private boolean resize = true; 037 038 public ShearFilter() { 039 } 040 041 public void setResize(boolean resize) { 042 this.resize = resize; 043 } 044 045 public boolean isResize() { 046 return resize; 047 } 048 049 public void setXAngle(float xangle) { 050 this.xangle = xangle; 051 initialize(); 052 } 053 054 public float getXAngle() { 055 return xangle; 056 } 057 058 public void setYAngle(float yangle) { 059 this.yangle = yangle; 060 initialize(); 061 } 062 063 public float getYAngle() { 064 return yangle; 065 } 066 067 private void initialize() { 068 shx = (float)Math.sin(xangle); 069 shy = (float)Math.sin(yangle); 070 } 071 072 protected void transformSpace(Rectangle r) { 073 float tangent = (float)Math.tan(xangle); 074 xoffset = -r.height * tangent; 075 if (tangent < 0.0) 076 tangent = -tangent; 077 r.width = (int)(r.height * tangent + r.width + 0.999999f); 078 tangent = (float)Math.tan(yangle); 079 yoffset = -r.width * tangent; 080 if (tangent < 0.0) 081 tangent = -tangent; 082 r.height = (int)(r.width * tangent + r.height + 0.999999f); 083 } 084 085 /* 086 public void imageComplete(int status) { 087 try { 088 if (status == IMAGEERROR || status == IMAGEABORTED) { 089 consumer.imageComplete(status); 090 return; 091 } 092 093 int width = originalSpace.width; 094 int height = originalSpace.height; 095 096 float tangent = Math.tan(angle); 097 if (tangent < 0.0) 098 tangent = -tangent; 099 int newWidth = (int)(height * tangent + width + 0.999999); 100 int[] outPixels = new int[height*newWidth]; 101 int inIndex = 0; 102 int yOffset = 0; 103 for (int y = 0; y < height; y++) { 104 float newCol; 105 if (angle >= 0.0) 106 newCol = y * tangent; 107 else 108 newCol = (height-y) * tangent; 109 int iNewCol = (int)newCol; 110 float f = newCol - iNewCol; 111 f = 1.0 - f; 112 113 int outIndex = yOffset+iNewCol; 114 int lastRGB = inPixels[inIndex]; 115 for (int x = 0; x < width; x++) { 116 int rgb = inPixels[inIndex]; 117 outPixels[outIndex] = ImageMath.mixColors(f, lastRGB, rgb); 118 lastRGB = rgb; 119 inIndex++; 120 outIndex++; 121 } 122 outPixels[outIndex] = ImageMath.mixColors(f, lastRGB, 0); 123 yOffset += newWidth; 124 } 125 consumer.setPixels(0, 0, newWidth, height, defaultRGBModel, outPixels, 0, newWidth); 126 consumer.imageComplete(status); 127 inPixels = null; 128 } 129 catch (Exception e) { 130 131 } 132 } 133 */ 134 135 protected void transformInverse(int x, int y, float[] out) { 136 out[0] = x + xoffset + (y * shx); 137 out[1] = y + yoffset + (x * shy); 138 } 139 140 public String toString() { 141 return "Distort/Shear..."; 142 } 143 144 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 145 Object o; 146 if((o=parameters.removeEL(KeyImpl.init("Resize")))!=null)setResize(ImageFilterUtil.toBooleanValue(o,"Resize")); 147 if((o=parameters.removeEL(KeyImpl.init("XAngle")))!=null)setXAngle(ImageFilterUtil.toFloatValue(o,"XAngle")); 148 if((o=parameters.removeEL(KeyImpl.init("YAngle")))!=null)setYAngle(ImageFilterUtil.toFloatValue(o,"YAngle")); 149 if((o=parameters.removeEL(KeyImpl.init("EdgeAction")))!=null)setEdgeAction(ImageFilterUtil.toString(o,"EdgeAction")); 150 if((o=parameters.removeEL(KeyImpl.init("Interpolation")))!=null)setInterpolation(ImageFilterUtil.toString(o,"Interpolation")); 151 152 // check for arguments not supported 153 if(parameters.size()>0) { 154 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 [Resize, XAngle, YAngle, EdgeAction, Interpolation]"); 155 } 156 157 return filter(src, dst); 158 } 159 }