CroppedImageInputByteStream.java 5.47 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.internal.io.stream;

import com.adobe.internal.io.stream.IO;
import com.adobe.internal.io.stream.InputByteStream;
import com.adobe.internal.io.stream.InputStreamImpl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class CroppedImageInputByteStream
implements InputByteStream {
    private InputStream decodedImage;
    private int oldBytesPerRow;
    private int newBytesPerRow;
    private byte[] bufferedCroppedRow;
    private int bufferPos = 0;
    private int rowOffset;
    private long length;
    private long totalBytesRead = 0;
    private boolean shiftBits = false;
    private ByteArrayOutputStream os = null;
    private int references = 1;

    public CroppedImageInputByteStream(int bpc, int noc, InputStream decodedImage, int width, int height, int x1, int y1, int x2, int y2) throws IOException {
        this.decodedImage = decodedImage;
        this.oldBytesPerRow = (int)Math.ceil((double)(width * noc * bpc) * 1.0 / 8.0);
        this.newBytesPerRow = (int)Math.ceil((double)((x2 - x1) * noc * bpc) * 1.0 / 8.0);
        this.os = new ByteArrayOutputStream();
        for (int i = 0; i < height - y2; ++i) {
            IO.copy(decodedImage, this.oldBytesPerRow, this.os);
            this.os.reset();
        }
        this.rowOffset = x1 * noc * bpc;
        if (this.rowOffset % 8 == 0) {
            this.rowOffset /= 8;
        } else {
            this.shiftBits = true;
        }
        this.bufferPos = this.newBytesPerRow;
        this.length = (y2 - y1) * this.newBytesPerRow;
    }

    private void fillRow() throws IOException {
        if (this.bufferedCroppedRow == null) {
            this.bufferedCroppedRow = new byte[this.newBytesPerRow];
        }
        IO.copyInternal(this.decodedImage, this.oldBytesPerRow, this.os, false);
        this.os.flush();
        byte[] row = this.os.toByteArray();
        this.os.reset();
        if (!this.shiftBits) {
            System.arraycopy(row, this.rowOffset, this.bufferedCroppedRow, 0, this.newBytesPerRow);
        } else {
            this.shiftAndWriteBits(row, this.rowOffset, this.newBytesPerRow);
        }
        this.bufferPos = 0;
    }

    private void shiftAndWriteBits(byte[] data, int shift, int length) throws IOException {
        int start = shift / 8;
        int offset = shift % 8;
        for (int i = 0; i < length - 1; ++i) {
            this.bufferedCroppedRow[i] = (byte)(data[start] << offset | data[++start] & 255 >> 8 - offset);
        }
        this.bufferedCroppedRow[length - 1] = (byte)(data[start] << offset);
    }

    @Override
    public InputByteStream slice(long begin, long length) throws IOException {
        throw new IOException("slice() on CroppedImageInputByteStream not supported.");
    }

    @Override
    public InputByteStream slice() throws IOException {
        ++this.references;
        return this;
    }

    @Override
    public int read() throws IOException {
        if (this.bufferPos >= this.newBytesPerRow) {
            this.fillRow();
        }
        return this.bufferedCroppedRow[this.bufferPos];
    }

    @Override
    public int read(byte[] bytes, int position, int length) throws IOException {
        int totalRead = 0;
        int bytesToRead = 0;
        if (this.totalBytesRead >= this.length) {
            return -1;
        }
        while (totalRead < length && this.totalBytesRead < this.length) {
            if (this.bufferPos >= this.newBytesPerRow) {
                this.fillRow();
            }
            bytesToRead = Math.min(length - totalRead, this.newBytesPerRow - this.bufferPos);
            System.arraycopy(this.bufferedCroppedRow, this.bufferPos, bytes, position + totalRead, bytesToRead);
            this.bufferPos += bytesToRead;
            totalRead += bytesToRead;
            this.totalBytesRead += (long)bytesToRead;
        }
        return totalRead;
    }

    @Override
    public int read(byte[] bytes) throws IOException {
        return this.read(bytes, 0, bytes.length);
    }

    @Override
    public int unget() throws IOException {
        throw new IOException("unget() on CroppedImageInputByteStream not supported.");
    }

    @Override
    public InputByteStream seek(long position) throws IOException {
        if (position == this.getPosition()) {
            return this;
        }
        throw new IOException("seek() on CroppedImageInputByteStream not supported.");
    }

    @Override
    public long getPosition() throws IOException {
        return this.totalBytesRead;
    }

    @Override
    public long length() throws IOException {
        return this.length;
    }

    @Override
    public long bytesAvailable() throws IOException {
        return this.length - this.totalBytesRead;
    }

    @Override
    public boolean eof() throws IOException {
        return this.length == this.totalBytesRead;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public void close() throws IOException {
        if (--this.references != 0) {
            return;
        }
        try {
            if (this.decodedImage != null) {
                this.decodedImage.close();
            }
        }
        finally {
            if (this.os != null) {
                this.os.close();
            }
        }
        this.bufferedCroppedRow = null;
    }

    @Override
    public InputStream toInputStream() throws IOException {
        ++this.references;
        return new InputStreamImpl(this);
    }
}