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 produces a "oil-painting" effect.
024 */
025public class OilFilter extends WholeImageFilter {
026        
027        private int range = 3;
028        private int levels = 256;
029        
030        public OilFilter() {
031        }
032
033    /**
034     * Set the range of the effect in pixels.
035     * @param range the range
036     * @see #getRange
037     */
038        public void setRange( int range ) {
039                this.range = range;
040        }
041        
042    /**
043     * Get the range of the effect in pixels.
044     * @return the range
045     * @see #setRange
046     */
047        public int getRange() {
048                return range;
049        }
050        
051    /**
052     * Set the number of levels for the effect.
053     * @param levels the number of levels
054     * @see #getLevels
055     */
056        public void setLevels( int levels ) {
057                this.levels = levels;
058        }
059        
060    /**
061     * Get the number of levels for the effect.
062     * @return the number of levels
063     * @see #setLevels
064     */
065        public int getLevels() {
066                return levels;
067        }
068        
069        protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
070                int index = 0;
071                int[] rHistogram = new int[levels];
072                int[] gHistogram = new int[levels];
073                int[] bHistogram = new int[levels];
074                int[] rTotal = new int[levels];
075                int[] gTotal = new int[levels];
076                int[] bTotal = new int[levels];
077                int[] outPixels = new int[width * height];
078
079                for (int y = 0; y < height; y++) {
080                        for (int x = 0; x < width; x++) {
081                                for (int i = 0; i < levels; i++)
082                                    rHistogram[i] = gHistogram[i] = bHistogram[i] = rTotal[i] = gTotal[i] = bTotal[i] = 0;
083
084                                for (int row = -range; row <= range; row++) {
085                                        int iy = y+row;
086                                        int ioffset;
087                                        if (0 <= iy && iy < height) {
088                                                ioffset = iy*width;
089                                                for (int col = -range; col <= range; col++) {
090                                                        int ix = x+col;
091                                                        if (0 <= ix && ix < width) {
092                                                                int rgb = inPixels[ioffset+ix];
093                                                                int r = (rgb >> 16) & 0xff;
094                                                                int g = (rgb >> 8) & 0xff;
095                                                                int b = rgb & 0xff;
096                                                                int ri = r*levels/256;
097                                                                int gi = g*levels/256;
098                                                                int bi = b*levels/256;
099                                                                rTotal[ri] += r;
100                                                                gTotal[gi] += g;
101                                                                bTotal[bi] += b;
102                                                                rHistogram[ri]++;
103                                                                gHistogram[gi]++;
104                                                                bHistogram[bi]++;
105                                                        }
106                                                }
107                                        }
108                                }
109                                
110                                int r = 0, g = 0, b = 0;
111                                for (int i = 1; i < levels; i++) {
112                                        if (rHistogram[i] > rHistogram[r])
113                                                r = i;
114                                        if (gHistogram[i] > gHistogram[g])
115                                                g = i;
116                                        if (bHistogram[i] > bHistogram[b])
117                                                b = i;
118                                }
119                                r = rTotal[r] / rHistogram[r];
120                                g = gTotal[g] / gHistogram[g];
121                                b = bTotal[b] / bHistogram[b];
122                                outPixels[index] = (inPixels[index] & 0xff000000) | ( r << 16 ) | ( g << 8 ) | b;
123                                index++;
124                        }
125                }
126                return outPixels;
127        }
128
129        public String toString() {
130                return "Stylize/Oil...";
131        }
132
133}
134