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.util.*; 020import java.awt.*; 021import java.awt.image.*; 022import com.jhlabs.math.*; 023 024public class QuiltFilter extends WholeImageFilter { 025 026 private Random randomGenerator; 027 private long seed = 567; 028 private int iterations = 25000; 029 private float a = -0.59f; 030 private float b = 0.2f; 031 private float c = 0.1f; 032 private float d = 0; 033 private int k = 0; 034 private Colormap colormap = new LinearColormap(); 035 036 public QuiltFilter() { 037 randomGenerator = new Random(); 038 } 039 040 public void randomize() { 041 seed = new Date().getTime(); 042 randomGenerator.setSeed(seed); 043 a = randomGenerator.nextFloat(); 044 b = randomGenerator.nextFloat(); 045 c = randomGenerator.nextFloat(); 046 d = randomGenerator.nextFloat(); 047 k = randomGenerator.nextInt() % 20 - 10; 048 } 049 050 /** 051 * Set the number of iterations the effect is performed. 052 * @param iterations the number of iterations 053 * @min-value 0 054 * @see #getIterations 055 */ 056 public void setIterations(int iterations) { 057 this.iterations = iterations; 058 } 059 060 /** 061 * Get the number of iterations the effect is performed. 062 * @return the number of iterations 063 * @see #setIterations 064 */ 065 public int getIterations() { 066 return iterations; 067 } 068 069 public void setA(float a) { 070 this.a = a; 071 } 072 073 public float getA() { 074 return a; 075 } 076 077 public void setB(float b) { 078 this.b = b; 079 } 080 081 public float getB() { 082 return b; 083 } 084 085 public void setC(float c) { 086 this.c = c; 087 } 088 089 public float getC() { 090 return c; 091 } 092 093 public void setD(float d) { 094 this.d = d; 095 } 096 097 public float getD() { 098 return d; 099 } 100 101 public void setK(int k) { 102 this.k = k; 103 } 104 105 public int getK() { 106 return k; 107 } 108 109 /** 110 * Set the colormap to be used for the filter. 111 * @param colormap the colormap 112 * @see #getColormap 113 */ 114 public void setColormap(Colormap colormap) { 115 this.colormap = colormap; 116 } 117 118 /** 119 * Get the colormap to be used for the filter. 120 * @return the colormap 121 * @see #setColormap 122 */ 123 public Colormap getColormap() { 124 return colormap; 125 } 126 127 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 128 int[] outPixels = new int[width * height]; 129 130 int i = 0; 131 int max = 0; 132 133 float x = 0.1f; 134 float y = 0.3f; 135 136 for (int n = 0; n < 20; n++) { 137 float mx = ImageMath.PI*x; 138 float my = ImageMath.PI*y; 139 float smx2 = (float)Math.sin(2*mx); 140 float smy2 = (float)Math.sin(2*my); 141 float x1 = (float)(a*smx2 + b*smx2*Math.cos(2*my) + 142 c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x); 143 x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1; 144 145 float y1 = (float)(a*smy2 + b*smy2*Math.cos(2*mx) + 146 c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y); 147 y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1; 148 x = x1; 149 y = y1; 150 } 151 152 for (int n = 0; n < iterations; n++) { 153 float mx = ImageMath.PI*x; 154 float my = ImageMath.PI*y; 155 float x1 = (float)(a*Math.sin(2*mx) + b*Math.sin(2*mx)*Math.cos(2*my) + 156 c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x); 157 x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1; 158 159 float y1 = (float)(a*Math.sin(2*my) + b*Math.sin(2*my)*Math.cos(2*mx) + 160 c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y); 161 y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1; 162 x = x1; 163 y = y1; 164 int ix = (int)(width*x); 165 int iy = (int)(height*y); 166 if (ix >= 0 && ix < width && iy >= 0 && iy < height) { 167 int t = outPixels[width*iy+ix]++; 168 if (t > max) 169 max = t; 170 } 171 } 172 173 if (colormap != null) { 174 int index = 0; 175 for (y = 0; y < height; y++) { 176 for (x = 0; x < width; x++) { 177 outPixels[index] = colormap.getColor(outPixels[index] / (float)max); 178 index++; 179 } 180 } 181 } 182 return outPixels; 183 } 184 185 public String toString() { 186 return "Texture/Chaotic Quilt..."; 187 } 188 189}