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.*; 020 021/** 022 * A filter which subtracts Gaussian blur from an image, sharpening it. 023 * @author Jerry Huxtable 024 */ 025public class UnsharpFilter extends GaussianFilter { 026 027 private float amount = 0.5f; 028 private int threshold = 1; 029 030 public UnsharpFilter() { 031 radius = 2; 032 } 033 034 /** 035 * Set the threshold value. 036 * @param threshold the threshold value 037 * @see #getThreshold 038 */ 039 public void setThreshold( int threshold ) { 040 this.threshold = threshold; 041 } 042 043 /** 044 * Get the threshold value. 045 * @return the threshold value 046 * @see #setThreshold 047 */ 048 public int getThreshold() { 049 return threshold; 050 } 051 052 /** 053 * Set the amount of sharpening. 054 * @param amount the amount 055 * @min-value 0 056 * @max-value 1 057 * @see #getAmount 058 */ 059 public void setAmount( float amount ) { 060 this.amount = amount; 061 } 062 063 /** 064 * Get the amount of sharpening. 065 * @return the amount 066 * @see #setAmount 067 */ 068 public float getAmount() { 069 return amount; 070 } 071 072 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 073 int width = src.getWidth(); 074 int height = src.getHeight(); 075 076 if ( dst == null ) 077 dst = createCompatibleDestImage( src, null ); 078 079 int[] inPixels = new int[width*height]; 080 int[] outPixels = new int[width*height]; 081 src.getRGB( 0, 0, width, height, inPixels, 0, width ); 082 083 if ( radius > 0 ) { 084 convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, alpha && premultiplyAlpha, false, CLAMP_EDGES); 085 convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, false, alpha && premultiplyAlpha, CLAMP_EDGES); 086 } 087 088 src.getRGB( 0, 0, width, height, outPixels, 0, width ); 089 090 float a = 4*amount; 091 092 int index = 0; 093 for ( int y = 0; y < height; y++ ) { 094 for ( int x = 0; x < width; x++ ) { 095 int rgb1 = outPixels[index]; 096 int r1 = (rgb1 >> 16) & 0xff; 097 int g1 = (rgb1 >> 8) & 0xff; 098 int b1 = rgb1 & 0xff; 099 100 int rgb2 = inPixels[index]; 101 int r2 = (rgb2 >> 16) & 0xff; 102 int g2 = (rgb2 >> 8) & 0xff; 103 int b2 = rgb2 & 0xff; 104 105 if ( Math.abs( r1 - r2 ) >= threshold ) 106 r1 = PixelUtils.clamp( (int)((a+1) * (r1-r2) + r2) ); 107 if ( Math.abs( g1 - g2 ) >= threshold ) 108 g1 = PixelUtils.clamp( (int)((a+1) * (g1-g2) + g2) ); 109 if ( Math.abs( b1 - b2 ) >= threshold ) 110 b1 = PixelUtils.clamp( (int)((a+1) * (b1-b2) + b2) ); 111 112 inPixels[index] = (rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1; 113 index++; 114 } 115 } 116 117 dst.setRGB( 0, 0, width, height, inPixels, 0, width ); 118 return dst; 119 } 120 121 public String toString() { 122 return "Blur/Unsharp Mask..."; 123 } 124}