gifimagereader.java

来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,146 行 · 第 1/3 页

JAVA
1,146
字号
        // attempt to analyze the congruences.  If passPeriod and        // sourceSubsamling are relatively prime, the period will be        // their product.  If they share a common factor, either the        // period will be equal to the larger value, or the sequences        // will be completely disjoint, depending on the relationship        // between passStart and sourceOffset.  Since we only have to do this        // twice per image (once each for X and Y), it seems cheap enough        // to do it the straightforward way.        boolean gotPixel = false;        int firstDst = -1;        int secondDst = -1;        int lastDst = -1;        for (int i = 0; i < passExtent; i++) {            int src = passStart + i*passPeriod;            if (src < sourceOffset) {                continue;            }            if ((src - sourceOffset) % sourceSubsampling != 0) {                continue;            }            if (src >= sourceOffset + sourceExtent) {                break;            }            int dst = destinationOffset +                (src - sourceOffset)/sourceSubsampling;            if (dst < dstMin) {                continue;            }            if (dst > dstMax) {                break;            }            if (!gotPixel) {                firstDst = dst; // Record smallest valid pixel                gotPixel = true;            } else if (secondDst == -1) {                secondDst = dst; // Record second smallest valid pixel            }            lastDst = dst; // Record largest valid pixel        }        vals[offset] = firstDst;        // If we never saw a valid pixel, set width to 0        if (!gotPixel) {            vals[offset + 2] = 0;        } else {            vals[offset + 2] = lastDst - firstDst + 1;        }        // The period is given by the difference of any two adjacent pixels        vals[offset + 4] = Math.max(secondDst - firstDst, 1);    }    /**     * A utility method that computes the exact set of destination     * pixels that will be written during a particular decoding pass.     * The intent is to simplify the work done by readers in combining     * the source region, source subsampling, and destination offset     * information obtained from the <code>ImageReadParam</code> with     * the offsets and periods of a progressive or interlaced decoding     * pass.     *     * @param sourceRegion a <code>Rectangle</code> containing the     * source region being read, offset by the source subsampling     * offsets, and clipped against the source bounds, as returned by     * the <code>getSourceRegion</code> method.     * @param destinationOffset a <code>Point</code> containing the     * coordinates of the upper-left pixel to be written in the     * destination.     * @param dstMinX the smallest X coordinate (inclusive) of the     * destination <code>Raster</code>.     * @param dstMinY the smallest Y coordinate (inclusive) of the     * destination <code>Raster</code>.     * @param dstMaxX the largest X coordinate (inclusive) of the destination     * <code>Raster</code>.     * @param dstMaxY the largest Y coordinate (inclusive) of the destination     * <code>Raster</code>.     * @param sourceXSubsampling the X subsampling factor.     * @param sourceYSubsampling the Y subsampling factor.     * @param passXStart the smallest source X coordinate (inclusive)     * of the current progressive pass.     * @param passYStart the smallest source Y coordinate (inclusive)     * of the current progressive pass.     * @param passWidth the width in pixels of the current progressive     * pass.     * @param passHeight the height in pixels of the current progressive     * pass.     * @param passPeriodX the X period (horizontal spacing between     * pixels) of the current progressive pass.     * @param passPeriodY the Y period (vertical spacing between     * pixels) of the current progressive pass.     *     * @return an array of 6 <code>int</code>s containing the     * destination min X, min Y, width, height, X period and Y period     * of the region that will be updated.     */    private static int[] computeUpdatedPixels(Rectangle sourceRegion,                                              Point destinationOffset,                                              int dstMinX,                                              int dstMinY,                                              int dstMaxX,                                              int dstMaxY,                                              int sourceXSubsampling,                                              int sourceYSubsampling,                                              int passXStart,                                              int passYStart,                                              int passWidth,                                              int passHeight,                                              int passPeriodX,                                              int passPeriodY) {        int[] vals = new int[6];        computeUpdatedPixels(sourceRegion.x, sourceRegion.width,                             destinationOffset.x,                             dstMinX, dstMaxX, sourceXSubsampling,                             passXStart, passWidth, passPeriodX,                             vals, 0);        computeUpdatedPixels(sourceRegion.y, sourceRegion.height,                             destinationOffset.y,                             dstMinY, dstMaxY, sourceYSubsampling,                             passYStart, passHeight, passPeriodY,                             vals, 1);        return vals;    }    private void startPass(int pass) {        if (updateListeners == null) {            return;        }        int y = 0;        int yStep = 1;        if (imageMetadata.interlaceFlag) {            y = interlaceOffset[interlacePass];            yStep = interlaceIncrement[interlacePass];        }        int[] vals =            computeUpdatedPixels(sourceRegion,                                 destinationOffset,                                 destinationRegion.x,                                  destinationRegion.y,                                 destinationRegion.x +                                 destinationRegion.width - 1,                                 destinationRegion.y +                                 destinationRegion.height - 1,                                 sourceXSubsampling,                                 sourceYSubsampling,                                 0,                                 y,                                 destinationRegion.width,                                 (destinationRegion.height + yStep - 1)/yStep,                                 1,                                 yStep);        // Initialized updateMinY and updateYStep        this.updateMinY = vals[1];        this.updateYStep = vals[5];        // Inform IIOReadUpdateListeners of new pass        int[] bands = { 0 };        processPassStarted(theImage,                           interlacePass,                           sourceMinProgressivePass,                           sourceMaxProgressivePass,                           0,                           updateMinY,                           1,                           updateYStep,                           bands);    }    public BufferedImage read(int imageIndex, ImageReadParam param)        throws IIOException {        if (stream == null) {            throw new IllegalStateException("Input not set!");        }        checkIndex(imageIndex);        int index = locateImage(imageIndex);        if (index != imageIndex) {            throw new IndexOutOfBoundsException("imageIndex out of bounds!");        }        clearAbortRequest();        readMetadata();        // A null ImageReadParam means we use the default        if (param == null) {            param = getDefaultReadParam();        }        // Initialize the destination image        Iterator imageTypes = getImageTypes(imageIndex);        this.theImage = getDestination(param,                                       imageTypes,                                       imageMetadata.imageWidth,                                       imageMetadata.imageHeight);        this.theTile = theImage.getWritableTile(0, 0);        this.width = imageMetadata.imageWidth;        this.height = imageMetadata.imageHeight;        this.streamX = 0;        this.streamY = 0;        this.rowsDone = 0;        this.interlacePass = 0;        // Get source region, taking subsampling offsets into account,        // and clipping against the true source bounds                this.sourceRegion = new Rectangle(0, 0, 0, 0);        this.destinationRegion = new Rectangle(0, 0, 0, 0);        computeRegions(param, width, height, theImage,                       sourceRegion, destinationRegion);        this.destinationOffset = new Point(destinationRegion.x,                                           destinationRegion.y);        this.sourceXSubsampling = param.getSourceXSubsampling();        this.sourceYSubsampling = param.getSourceYSubsampling();        this.sourceMinProgressivePass =            Math.max(param.getSourceMinProgressivePass(), 0);        this.sourceMaxProgressivePass =            Math.min(param.getSourceMaxProgressivePass(), 3);        this.destY = destinationRegion.y +            (streamY - sourceRegion.y)/sourceYSubsampling;        computeDecodeThisRow();        // Inform IIOReadProgressListeners of start of image        processImageStarted(imageIndex);        startPass(0);        this.rowBuf = new byte[width];        try {            // Read and decode the image data, fill in theImage            this.initCodeSize = stream.readUnsignedByte();            // Read first data block            this.blockLength = stream.readUnsignedByte();            int left = blockLength;            int off = 0;            while (left > 0) {                int nbytes = stream.read(block, off, left);                left -= nbytes;                off += nbytes;            }            this.bitPos = 0;            this.nextByte = 0;            this.lastBlockFound = false;            this.interlacePass = 0;            // Init 32-bit buffer            initNext32Bits();            this.clearCode = 1 << initCodeSize;            this.eofCode = clearCode + 1;            int code, oldCode = 0;            int[] prefix = new int[4096];            byte[] suffix = new byte[4096];            byte[] initial = new byte[4096];            int[] length = new int[4096];            byte[] string = new byte[4096];            initializeStringTable(prefix, suffix, initial, length);            int tableIndex = (1 << initCodeSize) + 2;            int codeSize = initCodeSize + 1;            int codeMask = (1 << codeSize) - 1;            while (!abortRequested()) {                code = getCode(codeSize, codeMask);                if (code == clearCode) {                    initializeStringTable(prefix, suffix, initial, length);                    tableIndex = (1 << initCodeSize) + 2;                    codeSize = initCodeSize + 1;                    codeMask = (1 << codeSize) - 1;                    code = getCode(codeSize, codeMask);                    if (code == eofCode) {                        // Inform IIOReadProgressListeners of end of image                        processImageComplete();                        return theImage;                    }                } else if (code == eofCode) {                    // Inform IIOReadProgressListeners of end of image                    processImageComplete();                    return theImage;                } else {                    int newSuffixIndex;                    if (code < tableIndex) {                        newSuffixIndex = code;                    } else { // code == tableIndex                        newSuffixIndex = oldCode;                        if (code != tableIndex) {                            // warning - code out of sequence                            // possibly data corruption                            processWarningOccurred("Out-of-sequence code!");                        }                    }                    int ti = tableIndex;                    int oc = oldCode;                    prefix[ti] = oc;                    suffix[ti] = initial[newSuffixIndex];                    initial[ti] = initial[oc];                    length[ti] = length[oc] + 1;                                        ++tableIndex;                    if ((tableIndex == (1 << codeSize)) &&                        (tableIndex < 4096)) {                        ++codeSize;                        codeMask = (1 << codeSize) - 1;                    }                }                // Reverse code                int c = code;                int len = length[c];                for (int i = len - 1; i >= 0; i--) {                    string[i] = suffix[c];                    c = prefix[c];                }                                outputPixels(string, len);                oldCode = code;            }            processReadAborted();            return theImage;        } catch (IOException e) {            e.printStackTrace();            throw new IIOException("I/O error reading image!", e);        }    }            /**     * Remove all settings including global settings such as     * <code>Locale</code>s and listeners, as well as stream settings.     */    public void reset() {        super.reset();        resetStreamSettings();    }    /**     * Remove local settings based on parsing of a stream.     */    private void resetStreamSettings() {        gotHeader = false;        streamMetadata = null;        currIndex = -1;        imageMetadata = null;        imageStartPosition = new ArrayList();        numImages = -1;        // No need to reinitialize 'block'        blockLength = 0;        bitPos = 0;        nextByte = 0;        next32Bits = 0;        lastBlockFound = false;        theImage = null;        theTile = null;        width = -1;        height = -1;        streamX = -1;        streamY = -1;        rowsDone = 0;        interlacePass = 0;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?