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.Color; 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 /** 029 * An experimental filter which can be used for keying against a clean shot. Given a source image, a clean image and a destination image, 030 * the filter replaces all pixels in the source which nearly equal the equivalent clean pixel by destination pixels. 031 */ 032 public class KeyFilter extends AbstractBufferedImageOp implements DynFiltering { 033 034 private float hTolerance = 0; 035 private float sTolerance = 0; 036 private float bTolerance = 0; 037 private BufferedImage destination; 038 private BufferedImage cleanImage; 039 040 public KeyFilter() { 041 } 042 043 /** 044 * Set the hue tolerance of the image in the range 0..1. 045 * @param hTolerance the tolerance 046 * @see #getHTolerance 047 */ 048 public void setHTolerance( float hTolerance ) { 049 this.hTolerance = hTolerance; 050 } 051 052 /** 053 * Get the hue tolerance. 054 * @return the tolerance 055 * @see #setHTolerance 056 */ 057 public float getHTolerance() { 058 return hTolerance; 059 } 060 061 /** 062 * Set the saturation tolerance of the image in the range 0..1. 063 * @param sTolerance the tolerance 064 * @see #getSTolerance 065 */ 066 public void setSTolerance( float sTolerance ) { 067 this.sTolerance = sTolerance; 068 } 069 070 /** 071 * Get the saturation tolerance. 072 * @return the tolerance 073 * @see #setSTolerance 074 */ 075 public float getSTolerance() { 076 return sTolerance; 077 } 078 079 /** 080 * Set the brightness tolerance of the image in the range 0..1. 081 * @param bTolerance the tolerance 082 * @see #getBTolerance 083 */ 084 public void setBTolerance( float bTolerance ) { 085 this.bTolerance = bTolerance; 086 } 087 088 /** 089 * Get the brightness tolerance. 090 * @return the tolerance 091 * @see #setBTolerance 092 */ 093 public float getBTolerance() { 094 return bTolerance; 095 } 096 097 /** 098 * Set the destination image. 099 * @param destination the destination image 100 * @see #getDestination 101 */ 102 public void setDestination( BufferedImage destination ) { 103 this.destination = destination; 104 } 105 106 /** 107 * Get the destination image. 108 * @return the destination image 109 * @see #setDestination 110 */ 111 public BufferedImage getDestination() { 112 return destination; 113 } 114 115 /** 116 * Get the clean image. 117 * @param cleanImage the clean image 118 * @see #getCleanImage 119 */ 120 public void setCleanImage( BufferedImage cleanImage ) { 121 this.cleanImage = cleanImage; 122 } 123 124 /** 125 * Get the clean image. 126 * @return the clean image 127 * @see #setCleanImage 128 */ 129 public BufferedImage getCleanImage() { 130 return cleanImage; 131 } 132 133 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 134 int width = src.getWidth(); 135 int height = src.getHeight(); 136 //int type = src.getType(); 137 //WritableRaster srcRaster = 138 src.getRaster(); 139 140 if ( dst == null ) 141 dst = createCompatibleDestImage( src, null ); 142 //WritableRaster dstRaster = 143 dst.getRaster(); 144 145 if ( destination != null && cleanImage != null ) { 146 float[] hsb1 = null; 147 float[] hsb2 = null; 148 int[] inPixels = null; 149 int[] outPixels = null; 150 int[] cleanPixels = null; 151 for ( int y = 0; y < height; y++ ) { 152 inPixels = getRGB( src, 0, y, width, 1, inPixels ); 153 outPixels = getRGB( destination, 0, y, width, 1, outPixels ); 154 cleanPixels = getRGB( cleanImage, 0, y, width, 1, cleanPixels ); 155 for ( int x = 0; x < width; x++ ) { 156 int rgb1 = inPixels[x]; 157 int out = outPixels[x]; 158 int rgb2 = cleanPixels[x]; 159 160 int r1 = (rgb1 >> 16) & 0xff; 161 int g1 = (rgb1 >> 8) & 0xff; 162 int b1 = rgb1 & 0xff; 163 int r2 = (rgb2 >> 16) & 0xff; 164 int g2 = (rgb2 >> 8) & 0xff; 165 int b2 = rgb2 & 0xff; 166 hsb1 = Color.RGBtoHSB( r1, b1, g1, hsb1 ); 167 hsb2 = Color.RGBtoHSB( r2, b2, g2, hsb2 ); 168 // int tolerance = (int)(255*tolerance); 169 // return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance; 170 171 // if ( PixelUtils.nearColors( in, clean, (int)(255*tolerance) ) ) 172 if ( Math.abs( hsb1[0] - hsb2[0] ) < hTolerance && Math.abs( hsb1[1] - hsb2[1] ) < sTolerance && Math.abs( hsb1[2] - hsb2[2] ) < bTolerance ) 173 inPixels[x] = out; 174 else 175 inPixels[x] = rgb1; 176 } 177 setRGB( dst, 0, y, width, 1, inPixels ); 178 } 179 } 180 181 return dst; 182 } 183 184 public String toString() { 185 return "Keying/Key..."; 186 } 187 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 188 Object o; 189 if((o=parameters.removeEL(KeyImpl.init("HTolerance")))!=null)setHTolerance(ImageFilterUtil.toFloatValue(o,"HTolerance")); 190 if((o=parameters.removeEL(KeyImpl.init("STolerance")))!=null)setSTolerance(ImageFilterUtil.toFloatValue(o,"STolerance")); 191 if((o=parameters.removeEL(KeyImpl.init("BTolerance")))!=null)setBTolerance(ImageFilterUtil.toFloatValue(o,"BTolerance")); 192 if((o=parameters.removeEL(KeyImpl.init("CleanImage")))!=null)setCleanImage(ImageFilterUtil.toBufferedImage(o,"CleanImage")); 193 if((o=parameters.removeEL(KeyImpl.init("destination")))!=null)setDestination(ImageFilterUtil.toBufferedImage(o,"destination")); 194 195 // check for arguments not supported 196 if(parameters.size()>0) { 197 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 [HTolerance, STolerance, BTolerance, CleanImage]"); 198 } 199 200 return filter(src, dst); 201 } 202 }