001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.image;
018
019import java.awt.*;
020import java.awt.image.*;
021
022/**
023 * A filter which allows levels adjustment on an image.
024 */
025public class LevelsFilter extends WholeImageFilter {
026
027        private int[][] lut;
028    private float lowLevel = 0;
029    private float highLevel = 1;
030    private float lowOutputLevel = 0;
031    private float highOutputLevel = 1;
032
033        public LevelsFilter() {
034        }
035
036    public void setLowLevel( float lowLevel ) {
037        this.lowLevel = lowLevel;
038    }
039    
040    public float getLowLevel() {
041        return lowLevel;
042    }
043    
044    public void setHighLevel( float highLevel ) {
045        this.highLevel = highLevel;
046    }
047    
048    public float getHighLevel() {
049        return highLevel;
050    }
051    
052    public void setLowOutputLevel( float lowOutputLevel ) {
053        this.lowOutputLevel = lowOutputLevel;
054    }
055    
056    public float getLowOutputLevel() {
057        return lowOutputLevel;
058    }
059    
060    public void setHighOutputLevel( float highOutputLevel ) {
061        this.highOutputLevel = highOutputLevel;
062    }
063    
064    public float getHighOutputLevel() {
065        return highOutputLevel;
066    }
067    
068        protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
069                Histogram histogram = new Histogram(inPixels, width, height, 0, width);
070
071                int i, j;
072
073                if (histogram.getNumSamples() > 0) {
074                        float scale = 255.0f / histogram.getNumSamples();
075                        lut = new int[3][256];
076
077            float low = lowLevel * 255;
078            float high = highLevel * 255;
079            if ( low == high )
080                high++;
081                        for (i = 0; i < 3; i++) {
082                                for (j = 0; j < 256; j++)
083                                        lut[i][j] = PixelUtils.clamp( (int)(255 * (lowOutputLevel + (highOutputLevel-lowOutputLevel) * (j-low)/(high-low))) );
084                        }
085                } else
086                        lut = null;
087
088                i = 0;
089                for (int y = 0; y < height; y++)
090                        for (int x = 0; x < width; x++) {
091                                inPixels[i] = filterRGB(x, y, inPixels[i]);
092                                i++;
093                        }
094                lut = null;
095                
096                return inPixels;
097        }
098
099        public int filterRGB(int x, int y, int rgb) {
100                if (lut != null) {
101                        int a = rgb & 0xff000000;
102                        int r = lut[Histogram.RED][(rgb >> 16) & 0xff];
103                        int g = lut[Histogram.GREEN][(rgb >> 8) & 0xff];
104                        int b = lut[Histogram.BLUE][rgb & 0xff];
105
106                        return a | (r << 16) | (g << 8) | b;
107                }
108                return rgb;
109        }
110
111        public String toString() {
112                return "Colors/Levels...";
113        }
114}