EmbossOp.java 4.27 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.day.image;

import com.day.image.AbstractBufferedImageOp;
import java.awt.RenderingHints;
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);
        }
    }

}