EmbossOp.java
4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
* Decompiled with CFR 0_118.
*/
package com.day.image;
import com.day.image.AbstractBufferedImageOp;
import java.awt.image.BandCombineOp;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
public class EmbossOp
extends AbstractBufferedImageOp {
private final int[] bump;
private final int width;
private final int height;
private final float azimut;
private final float elevation;
private final float filtersize;
public EmbossOp(BufferedImage bump, float azimut, float elevation, float filtersize) {
super(null);
this.checkValue("azimut", azimut);
this.checkValue("elevation", elevation);
this.checkValue("filtersize", filtersize);
this.bump = GreyScalerHelper.filter(bump.getRaster());
this.width = bump.getWidth();
this.height = bump.getHeight();
this.azimut = azimut;
this.elevation = elevation;
this.filtersize = filtersize;
}
private void checkValue(String parName, float parValue) {
if (Float.isNaN(parValue) || parValue < 0.0f) {
throw new IllegalArgumentException("Argument " + parName + " must not be negative or NaN");
}
}
protected void doFilter(BufferedImage src, BufferedImage dst) {
int width = src.getWidth();
int height = src.getHeight();
WritableRaster srcRas = src.getRaster();
WritableRaster dstRas = dst.getRaster();
double pixelScale = 255.9;
double azi = Math.toRadians(this.azimut);
double ele = Math.toRadians(this.elevation);
int lx = (int)(Math.cos(azi) * Math.cos(ele) * pixelScale);
int ly = (int)(Math.sin(azi) * Math.cos(ele) * pixelScale);
int lz = (int)(Math.sin(ele) * pixelScale);
int nz = (int)(1530.0f / this.filtersize);
int nz2 = nz * nz;
int nzlz = nz * lz;
int bw = this.width;
int bh = this.height;
int tw = width;
int th = height;
int nw = tw < bw ? tw : bw;
int nh = th < bh ? th : bh;
int[] srcRed = new int[nw];
int[] srcGrn = new int[nw];
int[] srcBlu = new int[nw];
int background = lz;
for (int y = 0; y < nh; ++y) {
srcRas.getSamples(0, y, nw, 1, 0, srcRed);
srcRas.getSamples(0, y, nw, 1, 1, srcGrn);
srcRas.getSamples(0, y, nw, 1, 2, srcBlu);
int s1 = bw * y + 1;
int s2 = s1 + (y < nh - 1 ? bw : 0);
int s3 = s2 + (y < nh - 2 ? bw : 0);
int x = 1;
int toff = 1;
while (x < nw - 1) {
int nx = this.bump[s1 - 1] + this.bump[s2 - 1] + this.bump[s3 - 1] - this.bump[s1 + 1] - this.bump[s2 + 1] - this.bump[s3 + 1];
int ny = this.bump[s3 - 1] + this.bump[s3] + this.bump[s3 + 1] - this.bump[s1 - 1] - this.bump[s1] - this.bump[s1 + 1];
int ndotl = 0;
int shade = 0;
shade = nx == 0 && ny == 0 ? background : ((ndotl = nx * lx + ny * ly + nzlz) < 0 ? 0 : (int)((double)ndotl / Math.sqrt(nx * nx + ny * ny + nz2)));
srcRed[toff] = srcRed[toff] * shade >>> 8;
srcBlu[toff] = srcBlu[toff] * shade >>> 8;
srcGrn[toff] = srcGrn[toff] * shade >>> 8;
++toff;
++x;
++s1;
++s2;
++s3;
}
dstRas.setSamples(0, y, nw, 1, 0, srcRed);
dstRas.setSamples(0, y, nw, 1, 1, srcBlu);
dstRas.setSamples(0, y, nw, 1, 2, srcGrn);
dstRas.setSamples(0, y, nw, 1, 3, srcRas.getSamples(0, y, nw, 1, 3, srcRed));
}
}
private static final class GreyScalerHelper {
private static final float[][] bopEl = new float[][]{{0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, {-0.3086f, -0.6094f, -0.082f, 0.0f, 255.0f}};
private static final BandCombineOp op = new BandCombineOp(bopEl, null);
private GreyScalerHelper() {
}
private static final int[] filter(Raster input) {
WritableRaster tmp = op.filter(input, null);
return tmp.getSamples(0, 0, tmp.getWidth(), tmp.getHeight(), 3, (int[])null);
}
}
}