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}