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