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.util.*; 021import com.jhlabs.math.*; 022 023/** 024 * A filter which applies a crystallizing effect to an image, by producing Voronoi cells filled with colours from the image. 025 */ 026public class CrystallizeFilter extends CellularFilter { 027 028 private float edgeThickness = 0.4f; 029 private boolean fadeEdges = false; 030 private int edgeColor = 0xff000000; 031 032 public CrystallizeFilter() { 033 setScale(16); 034 setRandomness(0.0f); 035 } 036 037 public void setEdgeThickness(float edgeThickness) { 038 this.edgeThickness = edgeThickness; 039 } 040 041 public float getEdgeThickness() { 042 return edgeThickness; 043 } 044 045 public void setFadeEdges(boolean fadeEdges) { 046 this.fadeEdges = fadeEdges; 047 } 048 049 public boolean getFadeEdges() { 050 return fadeEdges; 051 } 052 053 public void setEdgeColor(int edgeColor) { 054 this.edgeColor = edgeColor; 055 } 056 057 public int getEdgeColor() { 058 return edgeColor; 059 } 060 061 public int getPixel(int x, int y, int[] inPixels, int width, int height) { 062 float nx = m00*x + m01*y; 063 float ny = m10*x + m11*y; 064 nx /= scale; 065 ny /= scale * stretch; 066 nx += 1000; 067 ny += 1000; // Reduce artifacts around 0,0 068 float f = evaluate(nx, ny); 069 070 float f1 = results[0].distance; 071 float f2 = results[1].distance; 072 int srcx = ImageMath.clamp((int)((results[0].x-1000)*scale), 0, width-1); 073 int srcy = ImageMath.clamp((int)((results[0].y-1000)*scale), 0, height-1); 074 int v = inPixels[srcy * width + srcx]; 075 f = (f2 - f1) / edgeThickness; 076 f = ImageMath.smoothStep(0, edgeThickness, f); 077 if (fadeEdges) { 078 srcx = ImageMath.clamp((int)((results[1].x-1000)*scale), 0, width-1); 079 srcy = ImageMath.clamp((int)((results[1].y-1000)*scale), 0, height-1); 080 int v2 = inPixels[srcy * width + srcx]; 081 v2 = ImageMath.mixColors(0.5f, v2, v); 082 v = ImageMath.mixColors(f, v2, v); 083 } else 084 v = ImageMath.mixColors(f, edgeColor, v); 085 return v; 086 } 087 088 public String toString() { 089 return "Pixellate/Crystallize..."; 090 } 091 092}