ResizeOp.java 12.1 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.day.image;

import com.day.image.AbstractBufferedImageOp;

import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

public class ResizeOp
extends AbstractBufferedImageOp {
    private final double scaleX;
    private final double scaleY;
    private boolean fast;

    public ResizeOp(double scaleX, double scaleY, RenderingHints hints) {
        super(hints);
        this.scaleX = scaleX;
        this.scaleY = scaleY;
    }

    public ResizeOp(double scaleX, double scaleY) {
        this(scaleX, scaleY, null);
    }

    public ResizeOp(double scale) {
        this(scale, scale);
    }

    public Rectangle2D getBounds2D(BufferedImage src) {
        int nw = (int)Math.ceil((double)src.getWidth() * this.scaleX);
        int nh = (int)Math.ceil((double)src.getHeight() * this.scaleY);
        return new Rectangle2D.Double(0.0, 0.0, nw, nh);
    }

    public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
        if (dstPt == null) {
            dstPt = new Point2D.Float();
        }
        dstPt.setLocation(srcPt.getX() * this.scaleX, srcPt.getY() * this.scaleY);
        return dstPt;
    }

    public boolean isFast() {
        return this.fast;
    }

    public void setFast(boolean fast) {
        this.fast = fast;
    }

    protected void doFilter(BufferedImage src, BufferedImage dst) {
        if (this.fast) {
            ResizeOp.doFilter_progressive(src, dst);
        } else {
            ResizeOp.doFilter_weighted(src, dst);
        }
    }

    private static void doFilter_bicubic(BufferedImage src, BufferedImage dst) {
        Graphics2D g = dst.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g.drawImage(src, 0, 0, dst.getWidth(), dst.getHeight(), null);
        g.dispose();
    }

    private static void doFilter_bilinear(BufferedImage src, BufferedImage dst) {
        Graphics2D g = dst.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(src, 0, 0, dst.getWidth(), dst.getHeight(), null);
        g.dispose();
    }

    static void doFilter_progressive(BufferedImage src, BufferedImage dst) {
        int dw = dst.getWidth() * 2;
        int dh = dst.getHeight() * 2;
        BufferedImage ori = src;
        while (src.getWidth() > dw && src.getHeight() > dh) {
            int type;
            BufferedImage tmp = new BufferedImage(src.getWidth() / 2, src.getHeight() / 2, (type = src.getType()) == 0 ? 2 : type);
            ResizeOp.doFilter_bilinear(src, tmp);
            if (src != ori) {
                src.flush();
            }
            src = tmp;
        }
        ResizeOp.doFilter_bilinear(src, dst);
        if (src != ori) {
            src.flush();
        }
    }

    /*
     * Unable to fully structure code
     * Enabled aggressive block sorting
     * Lifted jumps to return sites
     */
    private static void doFilter_weighted(BufferedImage src, BufferedImage dst) {
        ow = src.getWidth();
        oh = src.getHeight();
        nw = dst.getWidth();
        nh = dst.getHeight();
        blockWidth = ow > nw ? ow : nw;
        scaleCacheSize = 0;
        if (oh > nh) {
            srcChunkStep = srcChunkHeight = ResizeOp.divideAndRoundUp(oh, nh);
            dstChunkStep = 1;
            dstChunkHeight = 1;
            blockHeight = srcChunkHeight;
            init_s = nh;
            scaleCacheSize = nw;
        } else if (oh < nh) {
            srcChunkHeight = 1;
            srcChunkStep = 1;
            blockHeight = dstChunkHeight = (dstChunkStep = ResizeOp.divideAndRoundUp(nh, oh));
            init_s = oh;
            scaleCacheSize = nw;
        } else {
            dstChunkStep = 1;
            dstChunkHeight = 1;
            srcChunkStep = 1;
            blockHeight = srcChunkHeight = 1;
            init_s = nh;
        }
        sr = new int[blockWidth * blockHeight];
        sg = new int[blockWidth * blockHeight];
        sb = new int[blockWidth * blockHeight];
        sa = new int[blockWidth * blockHeight];
        dr = new int[blockWidth * blockHeight];
        dg = new int[blockWidth * blockHeight];
        db = new int[blockWidth * blockHeight];
        da = new int[blockWidth * blockHeight];
        ccr = new int[scaleCacheSize];
        ccg = new int[scaleCacheSize];
        ccb = new int[scaleCacheSize];
        cca = new int[scaleCacheSize];
        srcRas = src.getRaster();
        dstRas = dst.getRaster();
        srcChunkTop = 0;
        dstChunkTop = 0;
        block0 : do {
            if (srcChunkTop >= oh) return;
            if (srcChunkTop + srcChunkHeight > oh) {
                srcChunkHeight = oh - srcChunkTop;
            }
            srcRas.getSamples(0, srcChunkTop, ow, srcChunkHeight, 0, sr);
            srcRas.getSamples(0, srcChunkTop, ow, srcChunkHeight, 1, sg);
            srcRas.getSamples(0, srcChunkTop, ow, srcChunkHeight, 2, sb);
            srcRas.getSamples(0, srcChunkTop, ow, srcChunkHeight, 3, sa);
            if (nw >= ow) ** GOTO lbl55
            oi = 0;
            ni = 0;
            ** GOTO lbl59
lbl55: // 1 sources:
            if (nw <= ow) ** GOTO lbl105
            oi = 0;
            ni = 0;
            ** GOTO lbl85
lbl59: // 2 sources:
            for (oy = 0; oy < srcChunkHeight; ++oy) {
                s = nw;
                cr = 0;
                cg = 0;
                cb = 0;
                ca = 0;
                for (ox = 0; ox < ow; ++ox, s += nw, ++oi) {
                    if (s >= ow) {
                        a = ow - s + nw;
                        dr[ni] = (cr += sr[oi] * a) / ow;
                        dg[ni] = (cg += sg[oi] * a) / ow;
                        db[ni] = (cb += sb[oi] * a) / ow;
                        da[ni] = (ca += sa[oi] * a) / ow;
                        ++ni;
                        cr = sr[oi] * (s -= ow);
                        cg = sg[oi] * s;
                        cb = sb[oi] * s;
                        ca = sa[oi] * s;
                        continue;
                    }
                    cr += sr[oi] * nw;
                    cg += sg[oi] * nw;
                    cb += sb[oi] * nw;
                    ca += sa[oi] * nw;
                }
            }
            ** GOTO lbl105
lbl85: // 2 sources:
            for (oy = 0; oy < srcChunkHeight; ++oy) {
                ox = 0;
                s = ow;
                for (nx = 0; nx < nw; ++nx, s += ow, ++ni) {
                    if (s >= nw) {
                        a = nw - s + ow;
                        oi1 = ox < ow - 1 ? oi + 1 : oi;
                        dr[ni] = (sr[oi] * a + sr[oi1] * (s -= nw)) / ow;
                        dg[ni] = (sg[oi] * a + sg[oi1] * s) / ow;
                        db[ni] = (sb[oi] * a + sb[oi1] * s) / ow;
                        da[ni] = (sa[oi] * a + sa[oi1] * s) / ow;
                        ++oi;
                        ++ox;
                        continue;
                    }
                    dr[ni] = sr[oi];
                    dg[ni] = sg[oi];
                    db[ni] = sb[oi];
                    da[ni] = sa[oi];
                }
            }
lbl105: // 3 sources:
            if (nw == ow && nh == oh || nw != ow && nh != oh) {
                tr = sr;
                tg = sg;
                tb = sb;
                ta = sa;
                sr = dr;
                sg = dg;
                sb = db;
                sa = da;
                dr = tr;
                dg = tg;
                db = tb;
                da = ta;
            }
            if (nh >= oh) ** GOTO lbl128
            if (srcChunkTop == 0) {
                for (i = 0; i < nw; ++i) {
                    ccr[i] = sr[i] * nh;
                    ccg[i] = sg[i] * nh;
                    ccb[i] = sb[i] * nh;
                    cca[i] = sa[i] * nh;
                    init_s = 2 * nh;
                }
            }
            ** GOTO lbl163
lbl128: // 1 sources:
            if (nh <= oh) ** GOTO lbl181
            if (srcChunkTop != 0) ** GOTO lbl136
            System.arraycopy(sr, 0, ccr, 0, nw);
            System.arraycopy(sg, 0, ccg, 0, nw);
            System.arraycopy(sb, 0, ccb, 0, nw);
            System.arraycopy(sa, 0, cca, 0, nw);
            dstChunkTop -= dstChunkStep;
            ** GOTO lbl187
lbl136: // 1 sources:
            s = init_s;
            ni = 0;
            for (ny = 0; ny < dstChunkHeight; ++ny, s += oh, ni += nw) {
                if (s < nh) {
                    System.arraycopy(ccr, 0, dr, ni, nw);
                    System.arraycopy(ccg, 0, dg, ni, nw);
                    System.arraycopy(ccb, 0, db, ni, nw);
                    System.arraycopy(cca, 0, da, ni, nw);
                    continue;
                }
                a = nh - s + oh;
                s -= nh;
                for (ox = 0; ox < nw; ++ox) {
                    dr[ni + ox] = (ccr[ox] * a + sr[ox] * s) / oh;
                    dg[ni + ox] = (ccg[ox] * a + sg[ox] * s) / oh;
                    db[ni + ox] = (ccb[ox] * a + sb[ox] * s) / oh;
                    da[ni + ox] = (cca[ox] * a + sa[ox] * s) / oh;
                }
                System.arraycopy(sr, 0, ccr, 0, nw);
                System.arraycopy(sg, 0, ccg, 0, nw);
                System.arraycopy(sb, 0, ccb, 0, nw);
                System.arraycopy(sa, 0, cca, 0, nw);
                init_s = s + oh;
                dstChunkStep = ny + 1;
                break;
            }
            if (srcChunkTop + srcChunkStep >= oh && dstChunkTop + dstChunkStep < nh) {
                srcChunkTop -= srcChunkStep;
            }
            ** GOTO lbl181
lbl163: // 1 sources:
            start_s = init_s;
            ox = 0;
            do {
                if (ox < nw) {
                    cr = ccr[ox];
                    cg = ccg[ox];
                    cb = ccb[ox];
                    ca = cca[ox];
                    s = start_s;
                    oy = 0;
                    oi = ox;
                    ni = ox;
                } else {
                    srcChunkStep = srcChunkHeight;
                    sum = oh - init_s + nh;
                    srcChunkHeight = sum / nh;
                    if (srcChunkHeight * nh != sum) {
                        ++srcChunkHeight;
                    }
lbl181: // 5 sources:
                    if (dstChunkTop + dstChunkStep > nh) {
                        dstChunkStep = nh - dstChunkTop;
                    }
                    dstRas.setSamples(0, dstChunkTop, nw, dstChunkStep, 0, dr);
                    dstRas.setSamples(0, dstChunkTop, nw, dstChunkStep, 1, dg);
                    dstRas.setSamples(0, dstChunkTop, nw, dstChunkStep, 2, db);
                    dstRas.setSamples(0, dstChunkTop, nw, dstChunkStep, 3, da);
lbl187: // 2 sources:
                    srcChunkTop += srcChunkStep;
                    dstChunkTop += dstChunkStep;
                    continue block0;
                }
                while (oy < dstChunkHeight) {
                    if (s >= oh) {
                        a = oh - s + nh;
                        dr[ni] = (cr += sr[oi] * a) / oh;
                        dg[ni] = (cg += sg[oi] * a) / oh;
                        db[ni] = (cb += sb[oi] * a) / oh;
                        da[ni] = (ca += sa[oi] * a) / oh;
                        ++oy;
                        ni += nw;
                        cr = sr[oi] * (s -= oh);
                        cg = sg[oi] * s;
                        cb = sb[oi] * s;
                        ca = sa[oi] * s;
                    } else {
                        cr += sr[oi] * nh;
                        cg += sg[oi] * nh;
                        cb += sb[oi] * nh;
                        ca += sa[oi] * nh;
                    }
                    s += nh;
                    oi += nw;
                }
                ccr[ox] = cr;
                ccg[ox] = cg;
                ccb[ox] = cb;
                cca[ox] = ca;
                init_s = s;
                ++ox;
            } while (true);
            break;
        } while (true);
    }

    private static int divideAndRoundUp(int a, int b) {
        return (a + b - 1) / b;
    }
}