001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer.imagery; 003 004import java.awt.image.BufferedImage; 005import java.awt.image.ConvolveOp; 006import java.awt.image.Kernel; 007 008import org.openstreetmap.josm.gui.layer.ImageProcessor; 009 010/** 011 * Sharpens or blurs the image, depending on the sharpen value. 012 * <p> 013 * A positive sharpen level means that we sharpen the image. 014 * <p> 015 * A negative sharpen level let's us blur the image. -1 is the most useful value there. 016 * 017 * @author Michael Zangl 018 * @since 10547 019 */ 020public class SharpenImageProcessor implements ImageProcessor { 021 private float sharpenLevel = 1; 022 private ConvolveOp op; 023 024 private static float[] KERNEL_IDENTITY = new float[] { 025 0, 0, 0, 026 0, 1, 0, 027 0, 0, 0 028 }; 029 030 private static float[] KERNEL_BLUR = new float[] { 031 1f / 16, 2f / 16, 1f / 16, 032 2f / 16, 4f / 16, 2f / 16, 033 1f / 16, 2f / 16, 1f / 16 034 }; 035 036 private static float[] KERNEL_SHARPEN = new float[] { 037 -.5f, -1f, -.5f, 038 -1f, 7, -1f, 039 -.5f, -1f, -.5f 040 }; 041 042 /** 043 * Gets the current sharpen level. 044 * @return The level. 045 */ 046 public float getSharpenLevel() { 047 return sharpenLevel; 048 } 049 050 /** 051 * Sets the sharpening level. 052 * @param sharpenLevel The level. Clamped to be positive or 0. 053 */ 054 public void setSharpenLevel(float sharpenLevel) { 055 if (sharpenLevel < 0) { 056 this.sharpenLevel = 0; 057 } else { 058 this.sharpenLevel = sharpenLevel; 059 } 060 061 if (this.sharpenLevel < 0.95) { 062 op = generateMixed(this.sharpenLevel, KERNEL_IDENTITY, KERNEL_BLUR); 063 } else if (this.sharpenLevel > 1.05) { 064 op = generateMixed(this.sharpenLevel - 1, KERNEL_SHARPEN, KERNEL_IDENTITY); 065 } else { 066 op = null; 067 } 068 } 069 070 private static ConvolveOp generateMixed(float aFactor, float[] a, float[] b) { 071 if (a.length != 9 || b.length != 9) { 072 throw new IllegalArgumentException("Illegal kernel array length."); 073 } 074 float[] values = new float[9]; 075 for (int i = 0; i < values.length; i++) { 076 values[i] = aFactor * a[i] + (1 - aFactor) * b[i]; 077 } 078 return new ConvolveOp(new Kernel(3, 3, values), ConvolveOp.EDGE_NO_OP, null); 079 } 080 081 @Override 082 public BufferedImage process(BufferedImage image) { 083 if (op != null) { 084 return op.filter(image, null); 085 } else { 086 return image; 087 } 088 } 089 090 @Override 091 public String toString() { 092 return "SharpenImageProcessor [sharpenLevel=" + sharpenLevel + ']'; 093 } 094}