DistortOp.java 12.6 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.day.image;

import com.day.image.AbstractBufferedImageOp;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;

public class DistortOp
extends AbstractBufferedImageOp {
    private final double x00;
    private final double x01;
    private final double x10;
    private final double x11;
    private final double y00;
    private final double y01;
    private final double y10;
    private final double y11;
    private final boolean crop;
    private final Color bgColor;

    public DistortOp(float[][] coords) {
        this(coords, false, Color.black);
    }

    public DistortOp(float[][] coords, boolean crop, Color bgColor) {
        super(null);
        if (coords == null) {
            throw new NullPointerException("coords");
        }
        if (coords.length < 3) {
            throw new IllegalArgumentException("need 4 coordinate pairs");
        }
        for (int i = 0; i < 4; ++i) {
            if (coords[i] == null) {
                throw new NullPointerException("coords[" + i + "]");
            }
            if (coords[i].length >= 2) continue;
            throw new IllegalArgumentException("missing value on coords[" + i + "]");
        }
        this.x00 = coords[0][0];
        this.y00 = coords[0][1];
        this.x10 = coords[1][0];
        this.y10 = coords[1][1];
        this.x01 = coords[2][0];
        this.y01 = coords[2][1];
        this.x11 = coords[3][0];
        this.y11 = coords[3][1];
        this.crop = crop;
        this.bgColor = bgColor;
    }

    public Rectangle2D getBounds2D(BufferedImage src) {
        if (this.crop) {
            double x0 = this.x00 < this.x01 ? this.x00 : this.x01;
            double y0 = this.y00 < this.y10 ? this.y00 : this.y10;
            double x1 = this.x10 > this.x11 ? this.x10 : this.x11;
            double y1 = this.y01 > this.y11 ? this.y01 : this.y11;
            return new Rectangle((int)Math.ceil((x1 - x0) * (double)src.getWidth()), (int)Math.ceil((y1 - y0) * (double)src.getHeight()));
        }
        return super.getBounds2D(src);
    }

    public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
        return super.getPoint2D(srcPt, dstPt);
    }

    protected void doFilter(BufferedImage src, BufferedImage dst) {
        int sw = src.getWidth();
        int sh = src.getHeight();
        int dw = dst.getWidth();
        int dh = dst.getHeight();
        double x00 = this.x00;
        double y00 = this.y00;
        double x01 = this.x01;
        double y01 = this.y01;
        double x10 = this.x10;
        double y10 = this.y10;
        double x11 = this.x11;
        double y11 = this.y11;
        if (this.crop) {
            double x0 = x00 < x01 ? x00 : x01;
            double y0 = y00 < y10 ? y00 : y10;
            x00 -= x0;
            x01 -= x0;
            x10 -= x0;
            x11 -= x0;
            y00 -= y0;
            y01 -= y0;
            y10 -= y0;
            y11 -= y0;
        }
        double b00 = (- y00 + y01) * (x10 * y00 - x11 * y00 - x00 * y10 + x11 * y10 + x00 * y11 - x10 * y11) * (x10 * y01 - x11 * y01 - x01 * y10 + x11 * y10 + x01 * y11 - x10 * y11);
        double b10 = (y00 - y10) * (x01 * y00 - x11 * y00 - x00 * y01 + x11 * y01 + x00 * y11 - x01 * y11) * (- x10 * y01 + x11 * y01 + x01 * y10 - x11 * y10 - x01 * y11 + x10 * y11);
        double b20 = - x10 * x10 * y00 * y00 * y01 + 2.0 * x10 * x11 * y00 * y00 * y01 - x11 * x11 * y00 * y00 * y01 + x10 * x10 * y00 * y01 * y01 - 2.0 * x10 * x11 * y00 * y01 * y01 + x11 * x11 * y00 * y01 * y01 + x01 * x01 * y00 * y00 * y10 - 2.0 * x01 * x11 * y00 * y00 * y10 + x11 * x11 * y00 * y00 * y10 - 2.0 * x00 * x01 * y00 * y01 * y10 + 2.0 * x00 * x10 * y00 * y01 * y10 + 2.0 * x01 * x11 * y00 * y01 * y10 - 2.0 * x10 * x11 * y00 * y01 * y10 + x00 * x00 * y01 * y01 * y10 - 2.0 * x00 * x10 * y01 * y01 * y10 + 2.0 * x10 * x11 * y01 * y01 * y10 - x11 * x11 * y01 * y01 * y10 - x01 * x01 * y00 * y10 * y10 + 2.0 * x01 * x11 * y00 * y10 * y10 - x11 * x11 * y00 * y10 * y10 - x00 * x00 * y01 * y10 * y10 + 2.0 * x00 * x01 * y01 * y10 * y10 - 2.0 * x01 * x11 * y01 * y10 * y10 + x11 * x11 * y01 * y10 * y10 - x01 * x01 * y00 * y00 * y11 + x10 * x10 * y00 * y00 * y11 + 2.0 * x01 * x11 * y00 * y00 * y11 - 2.0 * x10 * x11 * y00 * y00 * y11 + 2.0 * x00 * x01 * y00 * y01 * y11 - 2.0 * x00 * x10 * y00 * y01 * y11 - 2.0 * x01 * x11 * y00 * y01 * y11 + 2.0 * x10 * x11 * y00 * y01 * y11 - x00 * x00 * y01 * y01 * y11 + 2.0 * x00 * x10 * y01 * y01 * y11 - x10 * x10 * y01 * y01 * y11 + 2.0 * x00 * x01 * y00 * y10 * y11 - 2.0 * x00 * x10 * y00 * y10 * y11 - 2.0 * x01 * x11 * y00 * y10 * y11 + 2.0 * x10 * x11 * y00 * y10 * y11 - 2.0 * x00 * x01 * y01 * y10 * y11 + 2.0 * x00 * x10 * y01 * y10 * y11 + 2.0 * x01 * x11 * y01 * y10 * y11 - 2.0 * x10 * x11 * y01 * y10 * y11 + x00 * x00 * y10 * y10 * y11 - 2.0 * x00 * x01 * y10 * y10 * y11 + x01 * x01 * y10 * y10 * y11 - 2.0 * x00 * x01 * y00 * y11 * y11 + x01 * x01 * y00 * y11 * y11 + 2.0 * x00 * x10 * y00 * y11 * y11 - x10 * x10 * y00 * y11 * y11 + x00 * x00 * y01 * y11 * y11 - 2.0 * x00 * x10 * y01 * y11 * y11 + x10 * x10 * y01 * y11 * y11 - x00 * x00 * y10 * y11 * y11 + 2.0 * x00 * x01 * y10 * y11 * y11 - x01 * x01 * y10 * y11 * y11;
        double b01 = (- x00 + x01) * (x10 * y01 - x11 * y01 - x01 * y10 + x11 * y10 + x01 * y11 - x10 * y11) * (- x10 * y00 + x11 * y00 + x00 * y10 - x11 * y10 - x00 * y11 + x10 * y11);
        double b11 = (- x00 + x10) * (- x01 * y00 + x11 * y00 + x00 * y01 - x11 * y01 - x00 * y11 + x01 * y11) * (x10 * y01 - x11 * y01 - x01 * y10 + x11 * y10 + x01 * y11 - x10 * y11);
        double b21 = - x01 * x01 * x10 * y00 * y00 + x01 * x10 * x10 * y00 * y00 + x01 * x01 * x11 * y00 * y00 - x10 * x10 * x11 * y00 * y00 - x01 * x11 * x11 * y00 * y00 + x10 * x11 * x11 * y00 * y00 + 2.0 * x00 * x01 * x10 * y00 * y01 - 2.0 * x01 * x10 * x10 * y00 * y01 - 2.0 * x00 * x01 * x11 * y00 * y01 - 2.0 * x00 * x10 * x11 * y00 * y01 + 2.0 * x01 * x10 * x11 * y00 * y01 + 2.0 * x10 * x10 * x11 * y00 * y01 + 2.0 * x00 * x11 * x11 * y00 * y01 - 2.0 * x10 * x11 * x11 * y00 * y01 - x00 * x00 * x10 * y01 * y01 + x00 * x10 * x10 * y01 * y01 + x00 * x00 * x11 * y01 * y01 - x10 * x10 * x11 * y01 * y01 - x00 * x11 * x11 * y01 * y01 + x10 * x11 * x11 * y01 * y01 - 2.0 * x00 * x01 * x10 * y00 * y10 + 2.0 * x01 * x01 * x10 * y00 * y10 + 2.0 * x00 * x01 * x11 * y00 * y10 - 2.0 * x01 * x01 * x11 * y00 * y10 + 2.0 * x00 * x10 * x11 * y00 * y10 - 2.0 * x01 * x10 * x11 * y00 * y10 - 2.0 * x00 * x11 * x11 * y00 * y10 + 2.0 * x01 * x11 * x11 * y00 * y10 + x00 * x00 * x01 * y10 * y10 - x00 * x01 * x01 * y10 * y10 - x00 * x00 * x11 * y10 * y10 + x01 * x01 * x11 * y10 * y10 + x00 * x11 * x11 * y10 * y10 - x01 * x11 * x11 * y10 * y10 + 2.0 * x00 * x00 * x10 * y01 * y11 - 2.0 * x00 * x01 * x10 * y01 * y11 - 2.0 * x00 * x10 * x10 * y01 * y11 + 2.0 * x01 * x10 * x10 * y01 * y11 - 2.0 * x00 * x00 * x11 * y01 * y11 + 2.0 * x00 * x01 * x11 * y01 * y11 + 2.0 * x00 * x10 * x11 * y01 * y11 - 2.0 * x01 * x10 * x11 * y01 * y11 - 2.0 * x00 * x00 * x01 * y10 * y11 + 2.0 * x00 * x01 * x01 * y10 * y11 + 2.0 * x00 * x01 * x10 * y10 * y11 - 2.0 * x01 * x01 * x10 * y10 * y11 + 2.0 * x00 * x00 * x11 * y10 * y11 - 2.0 * x00 * x01 * x11 * y10 * y11 - 2.0 * x00 * x10 * x11 * y10 * y11 + 2.0 * x01 * x10 * x11 * y10 * y11 + x00 * x00 * x01 * y11 * y11 - x00 * x01 * x01 * y11 * y11 - x00 * x00 * x10 * y11 * y11 + x01 * x01 * x10 * y11 * y11 + x00 * x10 * x10 * y11 * y11 - x01 * x10 * x10 * y11 * y11;
        double b02 = (- x01 * y00 + x00 * y01) * (x10 * y01 - x11 * y01 - x01 * y10 + x11 * y10 + x01 * y11 - x10 * y11) * (- x10 * y00 + x11 * y00 + x00 * y10 - x11 * y10 - x00 * y11 + x10 * y11);
        double b12 = (- x10 * y00 + x00 * y10) * (x01 * y00 - x11 * y00 - x00 * y01 + x11 * y01 + x00 * y11 - x01 * y11) * (- x10 * y01 + x11 * y01 + x01 * y10 - x11 * y10 - x01 * y11 + x10 * y11);
        double b22 = x01 * x10 * x10 * y00 * y00 * y01 - 2.0 * x01 * x10 * x11 * y00 * y00 * y01 + x01 * x11 * x11 * y00 * y00 * y01 - x00 * x10 * x10 * y00 * y01 * y01 + 2.0 * x00 * x10 * x11 * y00 * y01 * y01 - x00 * x11 * x11 * y00 * y01 * y01 - x01 * x01 * x10 * y00 * y00 * y10 + 2.0 * x01 * x10 * x11 * y00 * y00 * y10 - x10 * x11 * x11 * y00 * y00 * y10 + 2.0 * x00 * x01 * x11 * y00 * y01 * y10 - 2.0 * x00 * x10 * x11 * y00 * y01 * y10 - 2.0 * x01 * x11 * x11 * y00 * y01 * y10 + 2.0 * x10 * x11 * x11 * y00 * y01 * y10 + x00 * x00 * x10 * y01 * y01 * y10 - 2.0 * x00 * x00 * x11 * y01 * y01 * y10 + 2.0 * x00 * x11 * x11 * y01 * y01 * y10 - x10 * x11 * x11 * y01 * y01 * y10 + x00 * x01 * x01 * y00 * y10 * y10 - 2.0 * x00 * x01 * x11 * y00 * y10 * y10 + x00 * x11 * x11 * y00 * y10 * y10 - x00 * x00 * x01 * y01 * y10 * y10 + 2.0 * x00 * x00 * x11 * y01 * y10 * y10 - 2.0 * x00 * x11 * x11 * y01 * y10 * y10 + x01 * x11 * x11 * y01 * y10 * y10 + 2.0 * x01 * x01 * x10 * y00 * y00 * y11 - 2.0 * x01 * x10 * x10 * y00 * y00 * y11 - x01 * x01 * x11 * y00 * y00 * y11 + x10 * x10 * x11 * y00 * y00 * y11 - 2.0 * x00 * x01 * x10 * y00 * y01 * y11 + 2.0 * x00 * x10 * x10 * y00 * y01 * y11 + 2.0 * x01 * x10 * x11 * y00 * y01 * y11 - 2.0 * x10 * x10 * x11 * y00 * y01 * y11 + x00 * x00 * x11 * y01 * y01 * y11 - 2.0 * x00 * x10 * x11 * y01 * y01 * y11 + x10 * x10 * x11 * y01 * y01 * y11 - 2.0 * x00 * x01 * x01 * y00 * y10 * y11 + 2.0 * x00 * x01 * x10 * y00 * y10 * y11 + 2.0 * x01 * x01 * x11 * y00 * y10 * y11 - 2.0 * x01 * x10 * x11 * y00 * y10 * y11 + 2.0 * x00 * x00 * x01 * y01 * y10 * y11 - 2.0 * x00 * x00 * x10 * y01 * y10 * y11 - 2.0 * x00 * x01 * x11 * y01 * y10 * y11 + 2.0 * x00 * x10 * x11 * y01 * y10 * y11 - x00 * x00 * x11 * y10 * y10 * y11 + 2.0 * x00 * x01 * x11 * y10 * y10 * y11 - x01 * x01 * x11 * y10 * y10 * y11 + x00 * x01 * x01 * y00 * y11 * y11 - 2.0 * x01 * x01 * x10 * y00 * y11 * y11 - x00 * x10 * x10 * y00 * y11 * y11 + 2.0 * x01 * x10 * x10 * y00 * y11 * y11 - x00 * x00 * x01 * y01 * y11 * y11 + 2.0 * x00 * x01 * x10 * y01 * y11 * y11 - x01 * x10 * x10 * y01 * y11 * y11 + x00 * x00 * x10 * y10 * y11 * y11 - 2.0 * x00 * x01 * x10 * y10 * y11 * y11 + x01 * x01 * x10 * y10 * y11 * y11;
        b01 *= (double)sw / (double)sh;
        b02 *= (double)sw;
        b10 *= (double)sh / (double)sw;
        b12 *= (double)sh;
        b20 /= (double)sw;
        b21 /= (double)sh;
        int[] s0 = src.getRaster().getSamples(0, 0, sw, sh, 0, (int[])null);
        int[] s1 = src.getRaster().getSamples(0, 0, sw, sh, 1, (int[])null);
        int[] s2 = src.getRaster().getSamples(0, 0, sw, sh, 2, (int[])null);
        int[] s3 = src.getRaster().getSamples(0, 0, sw, sh, 3, (int[])null);
        int doff = 0;
        int[] d0 = new int[s0.length];
        int[] d1 = new int[s1.length];
        int[] d2 = new int[s2.length];
        int[] d3 = new int[s3.length];
        for (int dy = 0; dy < dh; ++dy) {
            for (int dx = 0; dx < dw; ++dx) {
                double t0 = 0.0;
                double t1 = 0.0;
                double t2 = 0.0;
                double t3 = 0.0;
                double vv = dy;
                for (int sy2 = 4; sy2 > 0; --sy2) {
                    double uu = dx;
                    for (int sx2 = 4; sx2 > 0; --sx2) {
                        double v0 = b00 * uu + b01 * vv + b02;
                        double v1 = b10 * uu + b11 * vv + b12;
                        double v2 = b20 * uu + b21 * vv + b22;
                        int sx1 = (int)Math.floor(v0 / v2);
                        int sy1 = (int)Math.floor(v1 / v2);
                        if (sx1 >= 0 && sx1 < sw && sy1 >= 0 && sy1 < sh) {
                            int soff = sx1 + sy1 * sw;
                            t0 += (double)s0[soff];
                            t1 += (double)s1[soff];
                            t2 += (double)s2[soff];
                            t3 += (double)s3[soff];
                        } else {
                            t0 += (double)this.bgColor.getRed();
                            t1 += (double)this.bgColor.getGreen();
                            t2 += (double)this.bgColor.getBlue();
                            t3 += (double)this.bgColor.getAlpha();
                        }
                        uu += 0.25;
                    }
                    vv += 0.25;
                }
                d0[doff] = (int)(t0 / 16.0);
                d1[doff] = (int)(t1 / 16.0);
                d2[doff] = (int)(t2 / 16.0);
                d3[doff] = (int)(t3 / 16.0);
                ++doff;
            }
        }
        dst.getRaster().setSamples(0, 0, dw, dh, 0, d0);
        dst.getRaster().setSamples(0, 0, dw, dh, 1, d1);
        dst.getRaster().setSamples(0, 0, dw, dh, 2, d2);
        dst.getRaster().setSamples(0, 0, dw, dh, 3, d3);
    }
}