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 019 import railo.runtime.engine.ThreadLocalPageContext; 020 import railo.runtime.exp.FunctionException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.img.ImageUtil; 023 import railo.runtime.type.KeyImpl; 024 import railo.runtime.type.List; 025 import railo.runtime.type.Struct; 026 027 /** 028 * A filter which subtracts Gaussian blur from an image, sharpening it. 029 * 030 */ 031 public class UnsharpFilter extends GaussianFilter implements DynFiltering { 032 033 private float amount = 0.5f; 034 private int threshold = 1; 035 036 public UnsharpFilter() { 037 radius = 2; 038 } 039 040 /** 041 * Set the threshold value. 042 * @param threshold the threshold value 043 * @see #getThreshold 044 */ 045 public void setThreshold( int threshold ) { 046 this.threshold = threshold; 047 } 048 049 /** 050 * Get the threshold value. 051 * @return the threshold value 052 * @see #setThreshold 053 */ 054 public int getThreshold() { 055 return threshold; 056 } 057 058 /** 059 * Set the amount of sharpening. 060 * @param amount the amount 061 * @min-value 0 062 * @max-value 1 063 * @see #getAmount 064 */ 065 public void setAmount( float amount ) { 066 this.amount = amount; 067 } 068 069 /** 070 * Get the amount of sharpening. 071 * @return the amount 072 * @see #setAmount 073 */ 074 public float getAmount() { 075 return amount; 076 } 077 078 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 079 int width = src.getWidth(); 080 int height = src.getHeight(); 081 082 if ( dst == null ) 083 dst = createCompatibleDestImage( src, null ); 084 085 int[] inPixels = new int[width*height]; 086 int[] outPixels = new int[width*height]; 087 src.getRGB( 0, 0, width, height, inPixels, 0, width ); 088 089 if ( radius > 0 ) { 090 convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, alpha && premultiplyAlpha, false, CLAMP_EDGES); 091 convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, false, alpha && premultiplyAlpha, CLAMP_EDGES); 092 } 093 094 src.getRGB( 0, 0, width, height, outPixels, 0, width ); 095 096 float a = 4*amount; 097 098 int index = 0; 099 for ( int y = 0; y < height; y++ ) { 100 for ( int x = 0; x < width; x++ ) { 101 int rgb1 = outPixels[index]; 102 int r1 = (rgb1 >> 16) & 0xff; 103 int g1 = (rgb1 >> 8) & 0xff; 104 int b1 = rgb1 & 0xff; 105 106 int rgb2 = inPixels[index]; 107 int r2 = (rgb2 >> 16) & 0xff; 108 int g2 = (rgb2 >> 8) & 0xff; 109 int b2 = rgb2 & 0xff; 110 111 if ( Math.abs( r1 - r2 ) >= threshold ) 112 r1 = PixelUtils.clamp( (int)((a+1) * (r1-r2) + r2) ); 113 if ( Math.abs( g1 - g2 ) >= threshold ) 114 g1 = PixelUtils.clamp( (int)((a+1) * (g1-g2) + g2) ); 115 if ( Math.abs( b1 - b2 ) >= threshold ) 116 b1 = PixelUtils.clamp( (int)((a+1) * (b1-b2) + b2) ); 117 118 inPixels[index] = (rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1; 119 index++; 120 } 121 } 122 123 dst.setRGB( 0, 0, width, height, inPixels, 0, width ); 124 return dst; 125 } 126 127 public String toString() { 128 return "Blur/Unsharp Mask..."; 129 } 130 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 131 Object o; 132 if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount")); 133 if((o=parameters.removeEL(KeyImpl.init("Threshold")))!=null)setThreshold(ImageFilterUtil.toIntValue(o,"Threshold")); 134 if((o=parameters.removeEL(KeyImpl.init("Radius")))!=null)setRadius(ImageFilterUtil.toFloatValue(o,"Radius")); 135 if((o=parameters.removeEL(KeyImpl.init("EdgeAction")))!=null)setEdgeAction(ImageFilterUtil.toString(o,"EdgeAction")); 136 if((o=parameters.removeEL(KeyImpl.init("UseAlpha")))!=null)setUseAlpha(ImageFilterUtil.toBooleanValue(o,"UseAlpha")); 137 if((o=parameters.removeEL(KeyImpl.init("PremultiplyAlpha")))!=null)setPremultiplyAlpha(ImageFilterUtil.toBooleanValue(o,"PremultiplyAlpha")); 138 139 // check for arguments not supported 140 if(parameters.size()>0) { 141 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 [Amount, Threshold, Radius, Kernel, EdgeAction, UseAlpha, PremultiplyAlpha]"); 142 } 143 144 return filter(src, dst); 145 } 146 }