1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.gui.layer.imagery;
|
---|
3 |
|
---|
4 | import java.awt.image.BufferedImage;
|
---|
5 | import java.awt.image.ConvolveOp;
|
---|
6 | import java.awt.image.Kernel;
|
---|
7 |
|
---|
8 | import org.openstreetmap.josm.gui.layer.ImageProcessor;
|
---|
9 |
|
---|
10 | /**
|
---|
11 | * Sharpens or blurs the image, depending on the sharpen value.
|
---|
12 | * <p>
|
---|
13 | * A positive sharpen level means that we sharpen the image.
|
---|
14 | * <p>
|
---|
15 | * A negative sharpen level let's us blur the image. -1 is the most useful value there.
|
---|
16 | *
|
---|
17 | * @author Michael Zangl
|
---|
18 | * @since 10547
|
---|
19 | */
|
---|
20 | public class SharpenImageProcessor implements ImageProcessor {
|
---|
21 | private float sharpenLevel = 1;
|
---|
22 | private ConvolveOp op;
|
---|
23 |
|
---|
24 | private static final float[] KERNEL_IDENTITY = new float[] {
|
---|
25 | 0, 0, 0,
|
---|
26 | 0, 1, 0,
|
---|
27 | 0, 0, 0
|
---|
28 | };
|
---|
29 |
|
---|
30 | private static final float[] KERNEL_BLUR = new float[] {
|
---|
31 | 1f / 16, 2f / 16, 1f / 16,
|
---|
32 | 2f / 16, 4f / 16, 2f / 16,
|
---|
33 | 1f / 16, 2f / 16, 1f / 16
|
---|
34 | };
|
---|
35 |
|
---|
36 | private static final float[] KERNEL_SHARPEN = new float[] {
|
---|
37 | -.5f, -1f, -.5f,
|
---|
38 | -1f, 7, -1f,
|
---|
39 | -.5f, -1f, -.5f
|
---|
40 | };
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * Gets the current sharpen level.
|
---|
44 | * @return The level.
|
---|
45 | */
|
---|
46 | public float getSharpenLevel() {
|
---|
47 | return sharpenLevel;
|
---|
48 | }
|
---|
49 |
|
---|
50 | /**
|
---|
51 | * Sets the sharpening level.
|
---|
52 | * @param sharpenLevel The level. Clamped to be positive or 0.
|
---|
53 | */
|
---|
54 | public void setSharpenLevel(float sharpenLevel) {
|
---|
55 | if (sharpenLevel < 0) {
|
---|
56 | this.sharpenLevel = 0;
|
---|
57 | } else {
|
---|
58 | this.sharpenLevel = sharpenLevel;
|
---|
59 | }
|
---|
60 |
|
---|
61 | if (this.sharpenLevel < 0.95) {
|
---|
62 | op = generateMixed(this.sharpenLevel, KERNEL_IDENTITY, KERNEL_BLUR);
|
---|
63 | } else if (this.sharpenLevel > 1.05) {
|
---|
64 | op = generateMixed(this.sharpenLevel - 1, KERNEL_SHARPEN, KERNEL_IDENTITY);
|
---|
65 | } else {
|
---|
66 | op = null;
|
---|
67 | }
|
---|
68 | }
|
---|
69 |
|
---|
70 | private static ConvolveOp generateMixed(float aFactor, float[] a, float[] b) {
|
---|
71 | if (a.length != 9 || b.length != 9) {
|
---|
72 | throw new IllegalArgumentException("Illegal kernel array length.");
|
---|
73 | }
|
---|
74 | float[] values = new float[9];
|
---|
75 | for (int i = 0; i < values.length; i++) {
|
---|
76 | values[i] = aFactor * a[i] + (1 - aFactor) * b[i];
|
---|
77 | }
|
---|
78 | return new ConvolveOp(new Kernel(3, 3, values), ConvolveOp.EDGE_NO_OP, null);
|
---|
79 | }
|
---|
80 |
|
---|
81 | @Override
|
---|
82 | public BufferedImage process(BufferedImage image) {
|
---|
83 | if (op != null) {
|
---|
84 | return op.filter(image, null);
|
---|
85 | } else {
|
---|
86 | return image;
|
---|
87 | }
|
---|
88 | }
|
---|
89 |
|
---|
90 | @Override
|
---|
91 | public String toString() {
|
---|
92 | return "SharpenImageProcessor [sharpenLevel=" + sharpenLevel + ']';
|
---|
93 | }
|
---|
94 | }
|
---|