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 /** 029 * A filter which allows levels adjustment on an image. 030 */ 031 public class LevelsFilter extends WholeImageFilter implements DynFiltering { 032 033 private int[][] lut; 034 private float lowLevel = 0; 035 private float highLevel = 1; 036 private float lowOutputLevel = 0; 037 private float highOutputLevel = 1; 038 039 public LevelsFilter() { 040 } 041 042 public void setLowLevel( float lowLevel ) { 043 this.lowLevel = lowLevel; 044 } 045 046 public float getLowLevel() { 047 return lowLevel; 048 } 049 050 public void setHighLevel( float highLevel ) { 051 this.highLevel = highLevel; 052 } 053 054 public float getHighLevel() { 055 return highLevel; 056 } 057 058 public void setLowOutputLevel( float lowOutputLevel ) { 059 this.lowOutputLevel = lowOutputLevel; 060 } 061 062 public float getLowOutputLevel() { 063 return lowOutputLevel; 064 } 065 066 public void setHighOutputLevel( float highOutputLevel ) { 067 this.highOutputLevel = highOutputLevel; 068 } 069 070 public float getHighOutputLevel() { 071 return highOutputLevel; 072 } 073 074 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 075 Histogram histogram = new Histogram(inPixels, width, height, 0, width); 076 077 int i, j; 078 079 if (histogram.getNumSamples() > 0) { 080 //float scale = 255.0f / histogram.getNumSamples(); 081 lut = new int[3][256]; 082 083 float low = lowLevel * 255; 084 float high = highLevel * 255; 085 if ( low == high ) 086 high++; 087 for (i = 0; i < 3; i++) { 088 for (j = 0; j < 256; j++) 089 lut[i][j] = PixelUtils.clamp( (int)(255 * (lowOutputLevel + (highOutputLevel-lowOutputLevel) * (j-low)/(high-low))) ); 090 } 091 } else 092 lut = null; 093 094 i = 0; 095 for (int y = 0; y < height; y++) 096 for (int x = 0; x < width; x++) { 097 inPixels[i] = filterRGB(x, y, inPixels[i]); 098 i++; 099 } 100 lut = null; 101 102 return inPixels; 103 } 104 105 public int filterRGB(int x, int y, int rgb) { 106 if (lut != null) { 107 int a = rgb & 0xff000000; 108 int r = lut[Histogram.RED][(rgb >> 16) & 0xff]; 109 int g = lut[Histogram.GREEN][(rgb >> 8) & 0xff]; 110 int b = lut[Histogram.BLUE][rgb & 0xff]; 111 112 return a | (r << 16) | (g << 8) | b; 113 } 114 return rgb; 115 } 116 117 public String toString() { 118 return "Colors/Levels..."; 119 } 120 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 121 Object o; 122 if((o=parameters.removeEL(KeyImpl.init("LowLevel")))!=null)setLowLevel(ImageFilterUtil.toFloatValue(o,"LowLevel")); 123 if((o=parameters.removeEL(KeyImpl.init("HighLevel")))!=null)setHighLevel(ImageFilterUtil.toFloatValue(o,"HighLevel")); 124 if((o=parameters.removeEL(KeyImpl.init("LowOutputLevel")))!=null)setLowOutputLevel(ImageFilterUtil.toFloatValue(o,"LowOutputLevel")); 125 if((o=parameters.removeEL(KeyImpl.init("HighOutputLevel")))!=null)setHighOutputLevel(ImageFilterUtil.toFloatValue(o,"HighOutputLevel")); 126 127 // check for arguments not supported 128 if(parameters.size()>0) { 129 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 [LowLevel, HighLevel, LowOutputLevel, HighOutputLevel]"); 130 } 131 132 return filter(src, dst); 133 } 134 }