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.image.*; 020import java.util.*; 021 022/** 023 * A filter which adds random noise into an image. 024 */ 025public class NoiseFilter extends PointFilter { 026 027 /** 028 * Gaussian distribution for the noise. 029 */ 030 public final static int GAUSSIAN = 0; 031 032 /** 033 * Uniform distribution for the noise. 034 */ 035 public final static int UNIFORM = 1; 036 037 private int amount = 25; 038 private int distribution = UNIFORM; 039 private boolean monochrome = false; 040 private float density = 1; 041 private Random randomNumbers = new Random(); 042 043 public NoiseFilter() { 044 } 045 046 /** 047 * Set the amount of effect. 048 * @param amount the amount 049 * @min-value 0 050 * @max-value 1 051 * @see #getAmount 052 */ 053 public void setAmount(int amount) { 054 this.amount = amount; 055 } 056 057 /** 058 * Get the amount of noise. 059 * @return the amount 060 * @see #setAmount 061 */ 062 public int getAmount() { 063 return amount; 064 } 065 066 /** 067 * Set the distribution of the noise. 068 * @param distribution the distribution 069 * @see #getDistribution 070 */ 071 public void setDistribution( int distribution ) { 072 this.distribution = distribution; 073 } 074 075 /** 076 * Get the distribution of the noise. 077 * @return the distribution 078 * @see #setDistribution 079 */ 080 public int getDistribution() { 081 return distribution; 082 } 083 084 /** 085 * Set whether to use monochrome noise. 086 * @param monochrome true for monochrome noise 087 * @see #getMonochrome 088 */ 089 public void setMonochrome(boolean monochrome) { 090 this.monochrome = monochrome; 091 } 092 093 /** 094 * Get whether to use monochrome noise. 095 * @return true for monochrome noise 096 * @see #setMonochrome 097 */ 098 public boolean getMonochrome() { 099 return monochrome; 100 } 101 102 /** 103 * Set the density of the noise. 104 * @param density the density 105 * @see #getDensity 106 */ 107 public void setDensity( float density ) { 108 this.density = density; 109 } 110 111 /** 112 * Get the density of the noise. 113 * @return the density 114 * @see #setDensity 115 */ 116 public float getDensity() { 117 return density; 118 } 119 120 private int random(int x) { 121 x += (int)(((distribution == GAUSSIAN ? randomNumbers.nextGaussian() : 2*randomNumbers.nextFloat() - 1)) * amount); 122 if (x < 0) 123 x = 0; 124 else if (x > 0xff) 125 x = 0xff; 126 return x; 127 } 128 129 public int filterRGB(int x, int y, int rgb) { 130 if ( randomNumbers.nextFloat() <= density ) { 131 int a = rgb & 0xff000000; 132 int r = (rgb >> 16) & 0xff; 133 int g = (rgb >> 8) & 0xff; 134 int b = rgb & 0xff; 135 if (monochrome) { 136 int n = (int)(((distribution == GAUSSIAN ? randomNumbers.nextGaussian() : 2*randomNumbers.nextFloat() - 1)) * amount); 137 r = PixelUtils.clamp(r+n); 138 g = PixelUtils.clamp(g+n); 139 b = PixelUtils.clamp(b+n); 140 } else { 141 r = random(r); 142 g = random(g); 143 b = random(b); 144 } 145 return a | (r << 16) | (g << 8) | b; 146 } 147 return rgb; 148 } 149 150 public String toString() { 151 return "Stylize/Add Noise..."; 152 } 153}