Save This Page
Home » openjdk-7 » javax » imageio » stream » [javadoc | source]
    1   /*
    2    * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.imageio.stream;
   27   
   28   import java.io.IOException;
   29   import java.io.UTFDataFormatException;
   30   import java.nio.ByteOrder;
   31   
   32   /**
   33    * An abstract class implementing the <code>ImageOutputStream</code> interface.
   34    * This class is designed to reduce the number of methods that must
   35    * be implemented by subclasses.
   36    *
   37    */
   38   public abstract class ImageOutputStreamImpl
   39       extends ImageInputStreamImpl
   40       implements ImageOutputStream {
   41   
   42       /**
   43        * Constructs an <code>ImageOutputStreamImpl</code>.
   44        */
   45       public ImageOutputStreamImpl() {
   46       }
   47   
   48       public abstract void write(int b) throws IOException;
   49   
   50       public void write(byte b[]) throws IOException {
   51           write(b, 0, b.length);
   52       }
   53   
   54       public abstract void write(byte b[], int off, int len) throws IOException;
   55   
   56       public void writeBoolean(boolean v) throws IOException {
   57           write(v ? 1 : 0);
   58       }
   59   
   60       public void writeByte(int v) throws IOException {
   61           write(v);
   62       }
   63   
   64       public void writeShort(int v) throws IOException {
   65           if (byteOrder == ByteOrder.BIG_ENDIAN) {
   66               byteBuf[0] = (byte)(v >>> 8);
   67               byteBuf[1] = (byte)(v >>> 0);
   68           } else {
   69               byteBuf[0] = (byte)(v >>> 0);
   70               byteBuf[1] = (byte)(v >>> 8);
   71           }
   72           write(byteBuf, 0, 2);
   73       }
   74   
   75       public void writeChar(int v) throws IOException {
   76           writeShort(v);
   77       }
   78   
   79       public void writeInt(int v) throws IOException {
   80           if (byteOrder == ByteOrder.BIG_ENDIAN) {
   81               byteBuf[0] = (byte)(v >>> 24);
   82               byteBuf[1] = (byte)(v >>> 16);
   83               byteBuf[2] = (byte)(v >>>  8);
   84               byteBuf[3] = (byte)(v >>>  0);
   85           } else {
   86               byteBuf[0] = (byte)(v >>>  0);
   87               byteBuf[1] = (byte)(v >>>  8);
   88               byteBuf[2] = (byte)(v >>> 16);
   89               byteBuf[3] = (byte)(v >>> 24);
   90           }
   91           write(byteBuf, 0, 4);
   92       }
   93   
   94       public void writeLong(long v) throws IOException {
   95           if (byteOrder == ByteOrder.BIG_ENDIAN) {
   96               byteBuf[0] = (byte)(v >>> 56);
   97               byteBuf[1] = (byte)(v >>> 48);
   98               byteBuf[2] = (byte)(v >>> 40);
   99               byteBuf[3] = (byte)(v >>> 32);
  100               byteBuf[4] = (byte)(v >>> 24);
  101               byteBuf[5] = (byte)(v >>> 16);
  102               byteBuf[6] = (byte)(v >>>  8);
  103               byteBuf[7] = (byte)(v >>>  0);
  104           } else {
  105               byteBuf[0] = (byte)(v >>>  0);
  106               byteBuf[1] = (byte)(v >>>  8);
  107               byteBuf[2] = (byte)(v >>> 16);
  108               byteBuf[3] = (byte)(v >>> 24);
  109               byteBuf[4] = (byte)(v >>> 32);
  110               byteBuf[5] = (byte)(v >>> 40);
  111               byteBuf[6] = (byte)(v >>> 48);
  112               byteBuf[7] = (byte)(v >>> 56);
  113           }
  114           // REMIND: Once 6277756 is fixed, we should do a bulk write of all 8
  115           // bytes here as we do in writeShort() and writeInt() for even better
  116           // performance.  For now, two bulk writes of 4 bytes each is still
  117           // faster than 8 individual write() calls (see 6347575 for details).
  118           write(byteBuf, 0, 4);
  119           write(byteBuf, 4, 4);
  120       }
  121   
  122       public void writeFloat(float v) throws IOException {
  123           writeInt(Float.floatToIntBits(v));
  124       }
  125   
  126       public void writeDouble(double v) throws IOException {
  127           writeLong(Double.doubleToLongBits(v));
  128       }
  129   
  130       public void writeBytes(String s) throws IOException {
  131           int len = s.length();
  132           for (int i = 0 ; i < len ; i++) {
  133               write((byte)s.charAt(i));
  134           }
  135       }
  136   
  137       public void writeChars(String s) throws IOException {
  138           int len = s.length();
  139   
  140           byte[] b = new byte[len*2];
  141           int boff = 0;
  142           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  143               for (int i = 0; i < len ; i++) {
  144                   int v = s.charAt(i);
  145                   b[boff++] = (byte)(v >>> 8);
  146                   b[boff++] = (byte)(v >>> 0);
  147               }
  148           } else {
  149               for (int i = 0; i < len ; i++) {
  150                   int v = s.charAt(i);
  151                   b[boff++] = (byte)(v >>> 0);
  152                   b[boff++] = (byte)(v >>> 8);
  153               }
  154           }
  155   
  156           write(b, 0, len*2);
  157       }
  158   
  159       public void writeUTF(String s) throws IOException {
  160           int strlen = s.length();
  161           int utflen = 0;
  162           char[] charr = new char[strlen];
  163           int c, boff = 0;
  164   
  165           s.getChars(0, strlen, charr, 0);
  166   
  167           for (int i = 0; i < strlen; i++) {
  168               c = charr[i];
  169               if ((c >= 0x0001) && (c <= 0x007F)) {
  170                   utflen++;
  171               } else if (c > 0x07FF) {
  172                   utflen += 3;
  173               } else {
  174                   utflen += 2;
  175               }
  176           }
  177   
  178           if (utflen > 65535) {
  179               throw new UTFDataFormatException("utflen > 65536!");
  180           }
  181   
  182           byte[] b = new byte[utflen+2];
  183           b[boff++] = (byte) ((utflen >>> 8) & 0xFF);
  184           b[boff++] = (byte) ((utflen >>> 0) & 0xFF);
  185           for (int i = 0; i < strlen; i++) {
  186               c = charr[i];
  187               if ((c >= 0x0001) && (c <= 0x007F)) {
  188                   b[boff++] = (byte) c;
  189               } else if (c > 0x07FF) {
  190                   b[boff++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
  191                   b[boff++] = (byte) (0x80 | ((c >>  6) & 0x3F));
  192                   b[boff++] = (byte) (0x80 | ((c >>  0) & 0x3F));
  193               } else {
  194                   b[boff++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
  195                   b[boff++] = (byte) (0x80 | ((c >>  0) & 0x3F));
  196               }
  197           }
  198           write(b, 0, utflen + 2);
  199       }
  200   
  201       public void writeShorts(short[] s, int off, int len) throws IOException {
  202           // Fix 4430357 - if off + len < 0, overflow occurred
  203           if (off < 0 || len < 0 || off + len > s.length || off + len < 0) {
  204               throw new IndexOutOfBoundsException
  205                   ("off < 0 || len < 0 || off + len > s.length!");
  206           }
  207   
  208           byte[] b = new byte[len*2];
  209           int boff = 0;
  210           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  211               for (int i = 0; i < len; i++) {
  212                   short v = s[off + i];
  213                   b[boff++] = (byte)(v >>> 8);
  214                   b[boff++] = (byte)(v >>> 0);
  215               }
  216           } else {
  217               for (int i = 0; i < len; i++) {
  218                   short v = s[off + i];
  219                   b[boff++] = (byte)(v >>> 0);
  220                   b[boff++] = (byte)(v >>> 8);
  221               }
  222           }
  223   
  224           write(b, 0, len*2);
  225       }
  226   
  227       public void writeChars(char[] c, int off, int len) throws IOException {
  228           // Fix 4430357 - if off + len < 0, overflow occurred
  229           if (off < 0 || len < 0 || off + len > c.length || off + len < 0) {
  230               throw new IndexOutOfBoundsException
  231                   ("off < 0 || len < 0 || off + len > c.length!");
  232           }
  233   
  234           byte[] b = new byte[len*2];
  235           int boff = 0;
  236           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  237               for (int i = 0; i < len; i++) {
  238                   char v = c[off + i];
  239                   b[boff++] = (byte)(v >>> 8);
  240                   b[boff++] = (byte)(v >>> 0);
  241               }
  242           } else {
  243               for (int i = 0; i < len; i++) {
  244                   char v = c[off + i];
  245                   b[boff++] = (byte)(v >>> 0);
  246                   b[boff++] = (byte)(v >>> 8);
  247               }
  248           }
  249   
  250           write(b, 0, len*2);
  251       }
  252   
  253       public void writeInts(int[] i, int off, int len) throws IOException {
  254           // Fix 4430357 - if off + len < 0, overflow occurred
  255           if (off < 0 || len < 0 || off + len > i.length || off + len < 0) {
  256               throw new IndexOutOfBoundsException
  257                   ("off < 0 || len < 0 || off + len > i.length!");
  258           }
  259   
  260           byte[] b = new byte[len*4];
  261           int boff = 0;
  262           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  263               for (int j = 0; j < len; j++) {
  264                   int v = i[off + j];
  265                   b[boff++] = (byte)(v >>> 24);
  266                   b[boff++] = (byte)(v >>> 16);
  267                   b[boff++] = (byte)(v >>> 8);
  268                   b[boff++] = (byte)(v >>> 0);
  269               }
  270           } else {
  271               for (int j = 0; j < len; j++) {
  272                   int v = i[off + j];
  273                   b[boff++] = (byte)(v >>> 0);
  274                   b[boff++] = (byte)(v >>> 8);
  275                   b[boff++] = (byte)(v >>> 16);
  276                   b[boff++] = (byte)(v >>> 24);
  277               }
  278           }
  279   
  280           write(b, 0, len*4);
  281       }
  282   
  283       public void writeLongs(long[] l, int off, int len) throws IOException {
  284           // Fix 4430357 - if off + len < 0, overflow occurred
  285           if (off < 0 || len < 0 || off + len > l.length || off + len < 0) {
  286               throw new IndexOutOfBoundsException
  287                   ("off < 0 || len < 0 || off + len > l.length!");
  288           }
  289   
  290           byte[] b = new byte[len*8];
  291           int boff = 0;
  292           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  293               for (int i = 0; i < len; i++) {
  294                   long v = l[off + i];
  295                   b[boff++] = (byte)(v >>> 56);
  296                   b[boff++] = (byte)(v >>> 48);
  297                   b[boff++] = (byte)(v >>> 40);
  298                   b[boff++] = (byte)(v >>> 32);
  299                   b[boff++] = (byte)(v >>> 24);
  300                   b[boff++] = (byte)(v >>> 16);
  301                   b[boff++] = (byte)(v >>> 8);
  302                   b[boff++] = (byte)(v >>> 0);
  303               }
  304           } else {
  305               for (int i = 0; i < len; i++) {
  306                   long v = l[off + i];
  307                   b[boff++] = (byte)(v >>> 0);
  308                   b[boff++] = (byte)(v >>> 8);
  309                   b[boff++] = (byte)(v >>> 16);
  310                   b[boff++] = (byte)(v >>> 24);
  311                   b[boff++] = (byte)(v >>> 32);
  312                   b[boff++] = (byte)(v >>> 40);
  313                   b[boff++] = (byte)(v >>> 48);
  314                   b[boff++] = (byte)(v >>> 56);
  315               }
  316           }
  317   
  318           write(b, 0, len*8);
  319       }
  320   
  321       public void writeFloats(float[] f, int off, int len) throws IOException {
  322           // Fix 4430357 - if off + len < 0, overflow occurred
  323           if (off < 0 || len < 0 || off + len > f.length || off + len < 0) {
  324               throw new IndexOutOfBoundsException
  325                   ("off < 0 || len < 0 || off + len > f.length!");
  326           }
  327   
  328           byte[] b = new byte[len*4];
  329           int boff = 0;
  330           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  331               for (int i = 0; i < len; i++) {
  332                   int v = Float.floatToIntBits(f[off + i]);
  333                   b[boff++] = (byte)(v >>> 24);
  334                   b[boff++] = (byte)(v >>> 16);
  335                   b[boff++] = (byte)(v >>> 8);
  336                   b[boff++] = (byte)(v >>> 0);
  337               }
  338           } else {
  339               for (int i = 0; i < len; i++) {
  340                   int v = Float.floatToIntBits(f[off + i]);
  341                   b[boff++] = (byte)(v >>> 0);
  342                   b[boff++] = (byte)(v >>> 8);
  343                   b[boff++] = (byte)(v >>> 16);
  344                   b[boff++] = (byte)(v >>> 24);
  345               }
  346           }
  347   
  348           write(b, 0, len*4);
  349       }
  350   
  351       public void writeDoubles(double[] d, int off, int len) throws IOException {
  352           // Fix 4430357 - if off + len < 0, overflow occurred
  353           if (off < 0 || len < 0 || off + len > d.length || off + len < 0) {
  354               throw new IndexOutOfBoundsException
  355                   ("off < 0 || len < 0 || off + len > d.length!");
  356           }
  357   
  358           byte[] b = new byte[len*8];
  359           int boff = 0;
  360           if (byteOrder == ByteOrder.BIG_ENDIAN) {
  361               for (int i = 0; i < len; i++) {
  362                   long v = Double.doubleToLongBits(d[off + i]);
  363                   b[boff++] = (byte)(v >>> 56);
  364                   b[boff++] = (byte)(v >>> 48);
  365                   b[boff++] = (byte)(v >>> 40);
  366                   b[boff++] = (byte)(v >>> 32);
  367                   b[boff++] = (byte)(v >>> 24);
  368                   b[boff++] = (byte)(v >>> 16);
  369                   b[boff++] = (byte)(v >>> 8);
  370                   b[boff++] = (byte)(v >>> 0);
  371               }
  372           } else {
  373               for (int i = 0; i < len; i++) {
  374                   long v = Double.doubleToLongBits(d[off + i]);
  375                   b[boff++] = (byte)(v >>> 0);
  376                   b[boff++] = (byte)(v >>> 8);
  377                   b[boff++] = (byte)(v >>> 16);
  378                   b[boff++] = (byte)(v >>> 24);
  379                   b[boff++] = (byte)(v >>> 32);
  380                   b[boff++] = (byte)(v >>> 40);
  381                   b[boff++] = (byte)(v >>> 48);
  382                   b[boff++] = (byte)(v >>> 56);
  383               }
  384           }
  385   
  386           write(b, 0, len*8);
  387       }
  388   
  389       public void writeBit(int bit) throws IOException {
  390           writeBits((1L & bit), 1);
  391       }
  392   
  393       public void writeBits(long bits, int numBits) throws IOException {
  394           checkClosed();
  395   
  396           if (numBits < 0 || numBits > 64) {
  397               throw new IllegalArgumentException("Bad value for numBits!");
  398           }
  399           if (numBits == 0) {
  400               return;
  401           }
  402   
  403           // Prologue: deal with pre-existing bits
  404   
  405           // Bug 4499158, 4507868 - if we're at the beginning of the stream
  406           // and the bit offset is 0, there can't be any pre-existing bits
  407           if ((getStreamPosition() > 0) || (bitOffset > 0)) {
  408               int offset = bitOffset;  // read() will reset bitOffset
  409               int partialByte = read();
  410               if (partialByte != -1) {
  411                   seek(getStreamPosition() - 1);
  412               } else {
  413                   partialByte = 0;
  414               }
  415   
  416               if (numBits + offset < 8) {
  417                   // Notch out the partial byte and drop in the new bits
  418                   int shift = 8 - (offset+numBits);
  419                   int mask = -1 >>> (32 - numBits);
  420                   partialByte &= ~(mask << shift);  // Clear out old bits
  421                   partialByte |= ((bits & mask) << shift); // Or in new ones
  422                   write(partialByte);
  423                   seek(getStreamPosition() - 1);
  424                   bitOffset = offset + numBits;
  425                   numBits = 0;  // Signal that we are done
  426               } else {
  427                   // Fill out the partial byte and reduce numBits
  428                   int num = 8 - offset;
  429                   int mask = -1 >>> (32 - num);
  430                   partialByte &= ~mask;  // Clear out bits
  431                   partialByte |= ((bits >> (numBits - num)) & mask);
  432                   // Note that bitOffset is already 0, so there is no risk
  433                   // of this advancing to the next byte
  434                   write(partialByte);
  435                   numBits -= num;
  436               }
  437           }
  438   
  439           // Now write any whole bytes
  440           if (numBits > 7) {
  441               int extra = numBits % 8;
  442               for (int numBytes = numBits / 8; numBytes > 0; numBytes--) {
  443                   int shift = (numBytes-1)*8+extra;
  444                   int value = (int) ((shift == 0)
  445                                      ? bits & 0xFF
  446                                      : (bits>>shift) & 0xFF);
  447                   write(value);
  448               }
  449               numBits = extra;
  450           }
  451   
  452           // Epilogue: write out remaining partial byte, if any
  453           // Note that we may be at EOF, in which case we pad with 0,
  454           // or not, in which case we must preserve the existing bits
  455           if (numBits != 0) {
  456               // If we are not at the end of the file, read the current byte
  457               // If we are at the end of the file, initialize our byte to 0.
  458               int partialByte = 0;
  459               partialByte = read();
  460               if (partialByte != -1) {
  461                   seek(getStreamPosition() - 1);
  462               }
  463               // Fix 4494976: writeBit(int) does not pad the remainder
  464               // of the current byte with 0s
  465               else { // EOF
  466                   partialByte = 0;
  467               }
  468   
  469               int shift = 8 - numBits;
  470               int mask = -1 >>> (32 - numBits);
  471               partialByte &= ~(mask << shift);
  472               partialByte |= (bits & mask) << shift;
  473               // bitOffset is always already 0 when we get here.
  474               write(partialByte);
  475               seek(getStreamPosition() - 1);
  476               bitOffset = numBits;
  477           }
  478       }
  479   
  480       /**
  481        * If the bit offset is non-zero, forces the remaining bits
  482        * in the current byte to 0 and advances the stream position
  483        * by one.  This method should be called by subclasses at the
  484        * beginning of the <code>write(int)</code> and
  485        * <code>write(byte[], int, int)</code> methods.
  486        *
  487        * @exception IOException if an I/O error occurs.
  488        */
  489       protected final void flushBits() throws IOException {
  490           checkClosed();
  491           if (bitOffset != 0) {
  492               int offset = bitOffset;
  493               int partialByte = read(); // Sets bitOffset to 0
  494               if (partialByte < 0) {
  495                   // Fix 4465683: When bitOffset is set
  496                   // to something non-zero beyond EOF,
  497                   // we should set that whole byte to
  498                   // zero and write it to stream.
  499                   partialByte = 0;
  500                   bitOffset = 0;
  501               }
  502               else {
  503                   seek(getStreamPosition() - 1);
  504                   partialByte &= -1 << (8 - offset);
  505               }
  506               write(partialByte);
  507           }
  508       }
  509   
  510   }

Save This Page
Home » openjdk-7 » javax » imageio » stream » [javadoc | source]