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.geom.*;
021import java.awt.image.*;
022import java.util.*;
023
024public class ScratchFilter extends AbstractBufferedImageOp {
025    private float density = 0.1f;
026    private float angle;
027    private float angleVariation = 1.0f;
028    private float width = 0.5f;
029    private float length = 0.5f;
030    private int color = 0xffffffff;
031    private int seed = 0;
032
033    public ScratchFilter() {
034        }
035        
036        public void setAngle( float angle ) {
037                this.angle = angle;
038        }
039
040        public float getAngle() {
041                return angle;
042        }
043        
044        public void setAngleVariation( float angleVariation ) {
045                this.angleVariation = angleVariation;
046        }
047
048        public float getAngleVariation() {
049                return angleVariation;
050        }
051        
052        public void setDensity( float density ) {
053                this.density = density;
054        }
055
056        public float getDensity() {
057                return density;
058        }
059        
060        public void setLength( float length ) {
061                this.length = length;
062        }
063
064        public float getLength() {
065                return length;
066        }
067        
068        public void setWidth( float width ) {
069                this.width = width;
070        }
071
072        public float getWidth() {
073                return width;
074        }
075        
076        public void setColor( int color ) {
077                this.color = color;
078        }
079
080        public int getColor() {
081                return color;
082        }
083
084        public void setSeed( int seed ) {
085                this.seed = seed;
086        }
087
088        public int getSeed() {
089                return seed;
090        }
091
092    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
093        if ( dst == null )
094            dst = createCompatibleDestImage( src, null );
095
096        int width = src.getWidth();
097        int height = src.getHeight();
098        int numScratches = (int)(density * width * height / 100);
099        float l = length * width;
100        Random random = new Random( seed );
101        Graphics2D g = dst.createGraphics();
102        g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
103        g.setColor( new Color( color ) );
104        g.setStroke( new BasicStroke( this.width ) );
105        for ( int i = 0; i < numScratches; i++ ) {
106            float x = width * random.nextFloat();
107            float y = height * random.nextFloat();
108            float a = angle + ImageMath.TWO_PI * (angleVariation * (random.nextFloat() - 0.5f));
109            float s = (float)Math.sin( a ) * l;
110            float c = (float)Math.cos( a ) * l;
111            float x1 = x-c;
112            float y1 = y-s;
113            float x2 = x+c;
114            float y2 = y+s;
115            g.drawLine( (int)x1, (int)y1, (int)x2, (int)y2 );
116        }
117        g.dispose();
118        
119        return dst;
120    }
121    
122        public String toString() {
123                return "Render/Scratches...";
124        }
125}