Use Tree Navigation
public abstract class

ImageOutputStreamImpl

extends ImageInputStreamImpl
implements ImageOutputStream
/*
 * 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;
           
}
           
else {
                seek
(getStreamPosition() - 1);
                partialByte
&= -1 << (8 - offset);
           
}
            write
(partialByte);
       
}
   
}

}