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