510 lines · 17.7 KB · Java
RawDownload
/* * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.imageio.stream; import java.io.IOException;import java.io.UTFDataFormatException;import java.nio.ByteOrder; /** * An abstract class implementing the <code>ImageOutputStream</code> interface. * This class is designed to reduce the number of methods that must * be implemented by subclasses. * */public abstract class ImageOutputStreamImpl    extends ImageInputStreamImpl    implements ImageOutputStream {     /**     * Constructs an <code>ImageOutputStreamImpl</code>.     */    public ImageOutputStreamImpl() {    }     public abstract void write(int b) throws IOException;     public void write(byte b[]) throws IOException {        write(b, 0, b.length);    }     public abstract void write(byte b[], int off, int len) throws IOException;     public void writeBoolean(boolean v) throws IOException {        write(v ? 1 : 0);    }     public void writeByte(int v) throws IOException {        write(v);    }     public void writeShort(int v) throws IOException {        if (byteOrder == ByteOrder.BIG_ENDIAN) {            byteBuf[0] = (byte)(v >>> 8);            byteBuf[1] = (byte)(v >>> 0);        } else {            byteBuf[0] = (byte)(v >>> 0);            byteBuf[1] = (byte)(v >>> 8);        }        write(byteBuf, 0, 2);    }     public void writeChar(int v) throws IOException {        writeShort(v);    }     public void writeInt(int v) throws IOException {        if (byteOrder == ByteOrder.BIG_ENDIAN) {            byteBuf[0] = (byte)(v >>> 24);            byteBuf[1] = (byte)(v >>> 16);            byteBuf[2] = (byte)(v >>>  8);            byteBuf[3] = (byte)(v >>>  0);        } else {            byteBuf[0] = (byte)(v >>>  0);            byteBuf[1] = (byte)(v >>>  8);            byteBuf[2] = (byte)(v >>> 16);            byteBuf[3] = (byte)(v >>> 24);        }        write(byteBuf, 0, 4);    }     public void writeLong(long v) throws IOException {        if (byteOrder == ByteOrder.BIG_ENDIAN) {            byteBuf[0] = (byte)(v >>> 56);            byteBuf[1] = (byte)(v >>> 48);            byteBuf[2] = (byte)(v >>> 40);            byteBuf[3] = (byte)(v >>> 32);            byteBuf[4] = (byte)(v >>> 24);            byteBuf[5] = (byte)(v >>> 16);            byteBuf[6] = (byte)(v >>>  8);            byteBuf[7] = (byte)(v >>>  0);        } else {            byteBuf[0] = (byte)(v >>>  0);            byteBuf[1] = (byte)(v >>>  8);            byteBuf[2] = (byte)(v >>> 16);            byteBuf[3] = (byte)(v >>> 24);            byteBuf[4] = (byte)(v >>> 32);            byteBuf[5] = (byte)(v >>> 40);            byteBuf[6] = (byte)(v >>> 48);            byteBuf[7] = (byte)(v >>> 56);        }        // REMIND: Once 6277756 is fixed, we should do a bulk write of all 8        // bytes here as we do in writeShort() and writeInt() for even better        // performance.  For now, two bulk writes of 4 bytes each is still        // faster than 8 individual write() calls (see 6347575 for details).        write(byteBuf, 0, 4);        write(byteBuf, 4, 4);    }     public void writeFloat(float v) throws IOException {        writeInt(Float.floatToIntBits(v));    }     public void writeDouble(double v) throws IOException {        writeLong(Double.doubleToLongBits(v));    }     public void writeBytes(String s) throws IOException {        int len = s.length();        for (int i = 0 ; i < len ; i++) {            write((byte)s.charAt(i));        }    }     public void writeChars(String s) throws IOException {        int len = s.length();         byte[] b = new byte[len*2];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int i = 0; i < len ; i++) {                int v = s.charAt(i);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int i = 0; i < len ; i++) {                int v = s.charAt(i);                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);            }        }         write(b, 0, len*2);    }     public void writeUTF(String s) throws IOException {        int strlen = s.length();        int utflen = 0;        char[] charr = new char[strlen];        int c, boff = 0;         s.getChars(0, strlen, charr, 0);         for (int i = 0; i < strlen; i++) {            c = charr[i];            if ((c >= 0x0001) && (c <= 0x007F)) {                utflen++;            } else if (c > 0x07FF) {                utflen += 3;            } else {                utflen += 2;            }        }         if (utflen > 65535) {            throw new UTFDataFormatException("utflen > 65536!");        }         byte[] b = new byte[utflen+2];        b[boff++] = (byte) ((utflen >>> 8) & 0xFF);        b[boff++] = (byte) ((utflen >>> 0) & 0xFF);        for (int i = 0; i < strlen; i++) {            c = charr[i];            if ((c >= 0x0001) && (c <= 0x007F)) {                b[boff++] = (byte) c;            } else if (c > 0x07FF) {                b[boff++] = (byte) (0xE0 | ((c >> 12) & 0x0F));                b[boff++] = (byte) (0x80 | ((c >>  6) & 0x3F));                b[boff++] = (byte) (0x80 | ((c >>  0) & 0x3F));            } else {                b[boff++] = (byte) (0xC0 | ((c >>  6) & 0x1F));                b[boff++] = (byte) (0x80 | ((c >>  0) & 0x3F));            }        }        write(b, 0, utflen + 2);    }     public void writeShorts(short[] s, int off, int len) throws IOException {        // Fix 4430357 - if off + len < 0, overflow occurred        if (off < 0 || len < 0 || off + len > s.length || off + len < 0) {            throw new IndexOutOfBoundsException                ("off < 0 || len < 0 || off + len > s.length!");        }         byte[] b = new byte[len*2];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int i = 0; i < len; i++) {                short v = s[off + i];                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int i = 0; i < len; i++) {                short v = s[off + i];                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);            }        }         write(b, 0, len*2);    }     public void writeChars(char[] c, int off, int len) throws IOException {        // Fix 4430357 - if off + len < 0, overflow occurred        if (off < 0 || len < 0 || off + len > c.length || off + len < 0) {            throw new IndexOutOfBoundsException                ("off < 0 || len < 0 || off + len > c.length!");        }         byte[] b = new byte[len*2];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int i = 0; i < len; i++) {                char v = c[off + i];                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int i = 0; i < len; i++) {                char v = c[off + i];                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);            }        }         write(b, 0, len*2);    }     public void writeInts(int[] i, int off, int len) throws IOException {        // Fix 4430357 - if off + len < 0, overflow occurred        if (off < 0 || len < 0 || off + len > i.length || off + len < 0) {            throw new IndexOutOfBoundsException                ("off < 0 || len < 0 || off + len > i.length!");        }         byte[] b = new byte[len*4];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int j = 0; j < len; j++) {                int v = i[off + j];                b[boff++] = (byte)(v >>> 24);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int j = 0; j < len; j++) {                int v = i[off + j];                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 24);            }        }         write(b, 0, len*4);    }     public void writeLongs(long[] l, int off, int len) throws IOException {        // Fix 4430357 - if off + len < 0, overflow occurred        if (off < 0 || len < 0 || off + len > l.length || off + len < 0) {            throw new IndexOutOfBoundsException                ("off < 0 || len < 0 || off + len > l.length!");        }         byte[] b = new byte[len*8];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int i = 0; i < len; i++) {                long v = l[off + i];                b[boff++] = (byte)(v >>> 56);                b[boff++] = (byte)(v >>> 48);                b[boff++] = (byte)(v >>> 40);                b[boff++] = (byte)(v >>> 32);                b[boff++] = (byte)(v >>> 24);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int i = 0; i < len; i++) {                long v = l[off + i];                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 24);                b[boff++] = (byte)(v >>> 32);                b[boff++] = (byte)(v >>> 40);                b[boff++] = (byte)(v >>> 48);                b[boff++] = (byte)(v >>> 56);            }        }         write(b, 0, len*8);    }     public void writeFloats(float[] f, int off, int len) throws IOException {        // Fix 4430357 - if off + len < 0, overflow occurred        if (off < 0 || len < 0 || off + len > f.length || off + len < 0) {            throw new IndexOutOfBoundsException                ("off < 0 || len < 0 || off + len > f.length!");        }         byte[] b = new byte[len*4];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int i = 0; i < len; i++) {                int v = Float.floatToIntBits(f[off + i]);                b[boff++] = (byte)(v >>> 24);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int i = 0; i < len; i++) {                int v = Float.floatToIntBits(f[off + i]);                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 24);            }        }         write(b, 0, len*4);    }     public void writeDoubles(double[] d, int off, int len) throws IOException {        // Fix 4430357 - if off + len < 0, overflow occurred        if (off < 0 || len < 0 || off + len > d.length || off + len < 0) {            throw new IndexOutOfBoundsException                ("off < 0 || len < 0 || off + len > d.length!");        }         byte[] b = new byte[len*8];        int boff = 0;        if (byteOrder == ByteOrder.BIG_ENDIAN) {            for (int i = 0; i < len; i++) {                long v = Double.doubleToLongBits(d[off + i]);                b[boff++] = (byte)(v >>> 56);                b[boff++] = (byte)(v >>> 48);                b[boff++] = (byte)(v >>> 40);                b[boff++] = (byte)(v >>> 32);                b[boff++] = (byte)(v >>> 24);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 0);            }        } else {            for (int i = 0; i < len; i++) {                long v = Double.doubleToLongBits(d[off + i]);                b[boff++] = (byte)(v >>> 0);                b[boff++] = (byte)(v >>> 8);                b[boff++] = (byte)(v >>> 16);                b[boff++] = (byte)(v >>> 24);                b[boff++] = (byte)(v >>> 32);                b[boff++] = (byte)(v >>> 40);                b[boff++] = (byte)(v >>> 48);                b[boff++] = (byte)(v >>> 56);            }        }         write(b, 0, len*8);    }     public void writeBit(int bit) throws IOException {        writeBits((1L & bit), 1);    }     public void writeBits(long bits, int numBits) throws IOException {        checkClosed();         if (numBits < 0 || numBits > 64) {            throw new IllegalArgumentException("Bad value for numBits!");        }        if (numBits == 0) {            return;        }         // Prologue: deal with pre-existing bits         // Bug 4499158, 4507868 - if we're at the beginning of the stream        // and the bit offset is 0, there can't be any pre-existing bits        if ((getStreamPosition() > 0) || (bitOffset > 0)) {            int offset = bitOffset;  // read() will reset bitOffset            int partialByte = read();            if (partialByte != -1) {                seek(getStreamPosition() - 1);            } else {                partialByte = 0;            }             if (numBits + offset < 8) {                // Notch out the partial byte and drop in the new bits                int shift = 8 - (offset+numBits);                int mask = -1 >>> (32 - numBits);                partialByte &= ~(mask << shift);  // Clear out old bits                partialByte |= ((bits & mask) << shift); // Or in new ones                write(partialByte);                seek(getStreamPosition() - 1);                bitOffset = offset + numBits;                numBits = 0;  // Signal that we are done            } else {                // Fill out the partial byte and reduce numBits                int num = 8 - offset;                int mask = -1 >>> (32 - num);                partialByte &= ~mask;  // Clear out bits                partialByte |= ((bits >> (numBits - num)) & mask);                // Note that bitOffset is already 0, so there is no risk                // of this advancing to the next byte                write(partialByte);                numBits -= num;            }        }         // Now write any whole bytes        if (numBits > 7) {            int extra = numBits % 8;            for (int numBytes = numBits / 8; numBytes > 0; numBytes--) {                int shift = (numBytes-1)*8+extra;                int value = (int) ((shift == 0)                                   ? bits & 0xFF                                   : (bits>>shift) & 0xFF);                write(value);            }            numBits = extra;        }         // Epilogue: write out remaining partial byte, if any        // Note that we may be at EOF, in which case we pad with 0,        // or not, in which case we must preserve the existing bits        if (numBits != 0) {            // If we are not at the end of the file, read the current byte            // If we are at the end of the file, initialize our byte to 0.            int partialByte = 0;            partialByte = read();            if (partialByte != -1) {                seek(getStreamPosition() - 1);            }            // Fix 4494976: writeBit(int) does not pad the remainder            // of the current byte with 0s            else { // EOF                partialByte = 0;            }             int shift = 8 - numBits;            int mask = -1 >>> (32 - numBits);            partialByte &= ~(mask << shift);            partialByte |= (bits & mask) << shift;            // bitOffset is always already 0 when we get here.            write(partialByte);            seek(getStreamPosition() - 1);            bitOffset = numBits;        }    }     /**     * If the bit offset is non-zero, forces the remaining bits     * in the current byte to 0 and advances the stream position     * by one.  This method should be called by subclasses at the     * beginning of the <code>write(int)</code> and     * <code>write(byte[], int, int)</code> methods.     *     * @exception IOException if an I/O error occurs.     */    protected final void flushBits() throws IOException {        checkClosed();        if (bitOffset != 0) {            int offset = bitOffset;            int partialByte = read(); // Sets bitOffset to 0            if (partialByte < 0) {                // Fix 4465683: When bitOffset is set                // to something non-zero beyond EOF,                // we should set that whole byte to                // zero and write it to stream.                partialByte = 0;                bitOffset = 0;

Lines 1–500 of 510.