Home » openjdk-7 » sun » awt » image » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2007, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package sun.awt.image;
   27   import java.awt.image.Raster;
   28   import java.awt.image.WritableRaster;
   29   import java.awt.image.RasterFormatException;
   30   import java.awt.image.SampleModel;
   31   import java.awt.image.MultiPixelPackedSampleModel;
   32   import java.awt.image.DataBuffer;
   33   import java.awt.image.DataBufferByte;
   34   import java.awt.Rectangle;
   35   import java.awt.Point;
   36   
   37   /**
   38    * This class is useful for describing 1, 2, or 4 bit image data
   39    * elements.  This raster has one band whose pixels are packed
   40    * together into individual bytes in a single byte array.  This type
   41    * of raster can be used with an IndexColorModel. This raster uses a
   42    * MultiPixelPackedSampleModel.
   43    *
   44    */
   45   public class BytePackedRaster extends SunWritableRaster {
   46   
   47       /** The data bit offset for each pixel. */
   48       int           dataBitOffset;
   49   
   50       /** Scanline stride of the image data contained in this Raster. */
   51       int           scanlineStride;
   52   
   53       /**
   54        * The bit stride of a pixel, equal to the total number of bits
   55        * required to store a pixel.
   56        */
   57       int           pixelBitStride;
   58   
   59       /** The bit mask for extracting the pixel. */
   60       int           bitMask;
   61   
   62       /** The image data array. */
   63       byte[]        data;
   64   
   65       /** 8 minus the pixel bit stride. */
   66       int shiftOffset;
   67   
   68       int type;
   69   
   70       /** A cached copy of minX + width for use in bounds checks. */
   71       private int maxX;
   72   
   73       /** A cached copy of minY + height for use in bounds checks. */
   74       private int maxY;
   75   
   76       static private native void initIDs();
   77       static {
   78           /* ensure that the necessary native libraries are loaded */
   79           NativeLibLoader.loadLibraries();
   80           initIDs();
   81       }
   82   
   83       /**
   84        * Constructs a BytePackedRaster with the given SampleModel.
   85        * The Raster's upper left corner is origin and it is the same
   86        * size as the SampleModel.  A DataBuffer large enough to describe the
   87        * Raster is automatically created.  SampleModel must be of type
   88        * MultiPixelPackedSampleModel.
   89        * @param sampleModel     The SampleModel that specifies the layout.
   90        * @param origin          The Point that specified the origin.
   91        */
   92       public BytePackedRaster(SampleModel sampleModel,
   93                               Point origin) {
   94           this(sampleModel,
   95                sampleModel.createDataBuffer(),
   96                new Rectangle(origin.x,
   97                              origin.y,
   98                              sampleModel.getWidth(),
   99                              sampleModel.getHeight()),
  100                origin,
  101                null);
  102       }
  103   
  104       /**
  105        * Constructs a BytePackedRaster with the given SampleModel
  106        * and DataBuffer.  The Raster's upper left corner is origin and
  107        * it is the same size as the SampleModel.  The DataBuffer is not
  108        * initialized and must be a DataBufferByte compatible with SampleModel.
  109        * SampleModel must be of type MultiPixelPackedSampleModel.
  110        * @param sampleModel     The SampleModel that specifies the layout.
  111        * @param dataBuffer      The DataBufferShort that contains the image data.
  112        * @param origin          The Point that specifies the origin.
  113        */
  114       public BytePackedRaster(SampleModel sampleModel,
  115                               DataBuffer dataBuffer,
  116                               Point origin) {
  117           this(sampleModel,
  118                dataBuffer,
  119                new Rectangle(origin.x,
  120                              origin.y,
  121                              sampleModel.getWidth(),
  122                              sampleModel.getHeight()),
  123                origin,
  124                null);
  125       }
  126   
  127       /**
  128        * Constructs a BytePackedRaster with the given SampleModel,
  129        * DataBuffer, and parent.  DataBuffer must be a DataBufferByte and
  130        * SampleModel must be of type MultiPixelPackedSampleModel.
  131        * When translated into the base Raster's
  132        * coordinate system, aRegion must be contained by the base Raster.
  133        * Origin is the coordinate in the new Raster's coordinate system of
  134        * the origin of the base Raster.  (The base Raster is the Raster's
  135        * ancestor which has no parent.)
  136        *
  137        * Note that this constructor should generally be called by other
  138        * constructors or create methods, it should not be used directly.
  139        * @param sampleModel     The SampleModel that specifies the layout.
  140        * @param dataBuffer      The DataBufferShort that contains the image data.
  141        * @param aRegion         The Rectangle that specifies the image area.
  142        * @param origin          The Point that specifies the origin.
  143        * @param parent          The parent (if any) of this raster.
  144        *
  145        * @exception RasterFormatException if the parameters do not conform
  146        * to requirements of this Raster type.
  147        */
  148       public BytePackedRaster(SampleModel sampleModel,
  149                               DataBuffer dataBuffer,
  150                               Rectangle aRegion,
  151                               Point origin,
  152                               BytePackedRaster parent){
  153           super(sampleModel,dataBuffer,aRegion,origin, parent);
  154           this.maxX = minX + width;
  155           this.maxY = minY + height;
  156   
  157           if (!(dataBuffer instanceof DataBufferByte)) {
  158              throw new RasterFormatException("BytePackedRasters must have" +
  159                   "byte DataBuffers");
  160           }
  161           DataBufferByte dbb = (DataBufferByte)dataBuffer;
  162           this.data = stealData(dbb, 0);
  163           if (dbb.getNumBanks() != 1) {
  164               throw new
  165                   RasterFormatException("DataBuffer for BytePackedRasters"+
  166                                         " must only have 1 bank.");
  167           }
  168           int dbOffset = dbb.getOffset();
  169   
  170           if (sampleModel instanceof MultiPixelPackedSampleModel) {
  171               MultiPixelPackedSampleModel mppsm =
  172                   (MultiPixelPackedSampleModel)sampleModel;
  173               this.type = IntegerComponentRaster.TYPE_BYTE_BINARY_SAMPLES;
  174               pixelBitStride = mppsm.getPixelBitStride();
  175               if (pixelBitStride != 1 &&
  176                   pixelBitStride != 2 &&
  177                   pixelBitStride != 4) {
  178                   throw new RasterFormatException
  179                     ("BytePackedRasters must have a bit depth of 1, 2, or 4");
  180               }
  181               scanlineStride = mppsm.getScanlineStride();
  182               dataBitOffset = mppsm.getDataBitOffset() + dbOffset*8;
  183               int xOffset = aRegion.x - origin.x;
  184               int yOffset = aRegion.y - origin.y;
  185               dataBitOffset += xOffset*pixelBitStride + yOffset*scanlineStride*8;
  186               bitMask = (1 << pixelBitStride) -1;
  187               shiftOffset = 8 - pixelBitStride;
  188           } else {
  189               throw new RasterFormatException("BytePackedRasters must have"+
  190                   "MultiPixelPackedSampleModel");
  191           }
  192           verify(false);
  193       }
  194   
  195       /**
  196        * Returns the data bit offset for the Raster.  The data
  197        * bit offset is the bit index into the data array element
  198        * corresponding to the first sample of the first scanline.
  199        */
  200       public int getDataBitOffset() {
  201           return dataBitOffset;
  202       }
  203   
  204       /**
  205        * Returns the scanline stride -- the number of data array elements between
  206        * a given sample and the sample in the same column
  207        * of the next row.
  208        */
  209       public int getScanlineStride() {
  210           return scanlineStride;
  211       }
  212   
  213       /**
  214        * Returns pixel bit stride -- the number of bits between two
  215        * samples on the same scanline.
  216        */
  217       public int getPixelBitStride() {
  218           return pixelBitStride;
  219       }
  220   
  221       /**
  222        * Returns a reference to the entire data array.
  223        */
  224       public byte[] getDataStorage() {
  225           return data;
  226       }
  227   
  228       /**
  229        * Returns the data element at the specified
  230        * location.
  231        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  232        * if the pixel coordinate is out of bounds.
  233        * A ClassCastException will be thrown if the input object is non null
  234        * and references anything other than an array of transferType.
  235        * @param x        The X coordinate of the pixel location.
  236        * @param y        The Y coordinate of the pixel location.
  237        * @param outData  An object reference to an array of type defined by
  238        *                 getTransferType() and length getNumDataElements().
  239        *                 If null an array of appropriate type and size will be
  240        *                 allocated.
  241        * @return         An object reference to an array of type defined by
  242        *                 getTransferType() with the request pixel data.
  243        */
  244       public Object getDataElements(int x, int y, Object obj) {
  245           if ((x < this.minX) || (y < this.minY) ||
  246               (x >= this.maxX) || (y >= this.maxY)) {
  247               throw new ArrayIndexOutOfBoundsException
  248                   ("Coordinate out of bounds!");
  249           }
  250           byte outData[];
  251           if (obj == null) {
  252               outData = new byte[numDataElements];
  253           } else {
  254               outData = (byte[])obj;
  255           }
  256           int bitnum = dataBitOffset + (x-minX) * pixelBitStride;
  257           // Fix 4184283
  258           int element = data[(y-minY) * scanlineStride + (bitnum >> 3)] & 0xff;
  259           int shift = shiftOffset - (bitnum & 7);
  260           outData[0] = (byte)((element >> shift) & bitMask);
  261           return outData;
  262       }
  263   
  264       /**
  265        * Returns the pixel data for the specified rectangle of pixels in a
  266        * primitive array of type TransferType.
  267        * For image data supported by the Java 2D API, this
  268        * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or
  269        * DataBuffer.TYPE_INT.  Data may be returned in a packed format,
  270        * thus increasing efficiency for data transfers.
  271        *
  272        * An ArrayIndexOutOfBoundsException may be thrown
  273        * if the coordinates are not in bounds.
  274        * A ClassCastException will be thrown if the input object is non null
  275        * and references anything other than an array of TransferType.
  276        * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, Object, DataBuffer)
  277        * @param x        The X coordinate of the upper left pixel location.
  278        * @param y        The Y coordinate of the upper left pixel location.
  279        * @param w        Width of the pixel rectangle.
  280        * @param h        Height of the pixel rectangle.
  281        * @param outData  An object reference to an array of type defined by
  282        *                 getTransferType() and length w*h*getNumDataElements().
  283        *                 If null, an array of appropriate type and size will be
  284        *                 allocated.
  285        * @return         An object reference to an array of type defined by
  286        *                 getTransferType() with the requested pixel data.
  287        */
  288       public Object getDataElements(int x, int y, int w, int h,
  289                                     Object outData) {
  290           return getByteData(x, y, w, h, (byte[])outData);
  291       }
  292   
  293       /**
  294        * Returns an array  of data elements from the specified rectangular
  295        * region.
  296        *
  297        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  298        * if the pixel coordinates are out of bounds.
  299        * A ClassCastException will be thrown if the input object is non null
  300        * and references anything other than an array of transferType.
  301        * <pre>
  302        *       byte[] bandData = (byte[])raster.getPixelData(x, y, w, h, null);
  303        *       int pixel;
  304        *       // To find a data element at location (x2, y2)
  305        *       pixel = bandData[((y2-y)*w + (x2-x))];
  306        * </pre>
  307        * @param x        The X coordinate of the upper left pixel location.
  308        * @param y        The Y coordinate of the upper left pixel location.
  309        * @param width    Width of the pixel rectangle.
  310        * @param height   Height of the pixel rectangle.
  311        * @param outData  An object reference to an array of type defined by
  312        *                 getTransferType() and length w*h*getNumDataElements().
  313        *                 If null an array of appropriate type and size will be
  314        *                 allocated.
  315        * @return         An object reference to an array of type defined by
  316        *                 getTransferType() with the request pixel data.
  317        */
  318       public Object getPixelData(int x, int y, int w, int h, Object obj) {
  319           if ((x < this.minX) || (y < this.minY) ||
  320               (x + w > this.maxX) || (y + h > this.maxY)) {
  321               throw new ArrayIndexOutOfBoundsException
  322                   ("Coordinate out of bounds!");
  323           }
  324           byte outData[];
  325           if (obj == null) {
  326               outData = new byte[numDataElements*w*h];
  327           } else {
  328               outData = (byte[])obj;
  329           }
  330           int pixbits = pixelBitStride;
  331           int scanbit = dataBitOffset + (x-minX) * pixbits;
  332           int index = (y-minY) * scanlineStride;
  333           int outindex = 0;
  334           byte data[] = this.data;
  335   
  336           for (int j = 0; j < h; j++) {
  337               int bitnum = scanbit;
  338               for (int i = 0; i < w; i++) {
  339                   int shift = shiftOffset - (bitnum & 7);
  340                   outData[outindex++] =
  341                       (byte)(bitMask & (data[index + (bitnum >> 3)] >> shift));
  342                   bitnum += pixbits;
  343               }
  344               index += scanlineStride;
  345           }
  346           return outData;
  347       }
  348   
  349       /**
  350        * Returns a byte array containing the specified data elements
  351        * from the data array.  The band index will be ignored.
  352        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  353        * if the pixel coordinates are out of bounds.
  354        * <pre>
  355        *       byte[] byteData = getByteData(x, y, band, w, h, null);
  356        *       // To find a data element at location (x2, y2)
  357        *       byte element = byteData[(y2-y)*w + (x2-x)];
  358        * </pre>
  359        * @param x        The X coordinate of the upper left pixel location.
  360        * @param y        The Y coordinate of the upper left pixel location.
  361        * @param width    Width of the pixel rectangle.
  362        * @param height   Height of the pixel rectangle.
  363        * @param band     The band to return, is ignored.
  364        * @param outData  If non-null, data elements
  365        *                 at the specified locations are returned in this array.
  366        * @return         Byte array with data elements.
  367        */
  368       public byte[] getByteData(int x, int y, int w, int h,
  369                                 int band, byte[] outData) {
  370           return getByteData(x, y, w, h, outData);
  371       }
  372   
  373       /**
  374        * Returns a byte array containing the specified data elements
  375        * from the data array.
  376        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  377        * if the pixel coordinates are out of bounds.
  378        * <pre>
  379        *       byte[] byteData = raster.getByteData(x, y, w, h, null);
  380        *       byte pixel;
  381        *       // To find a data element at location (x2, y2)
  382        *       pixel = byteData[((y2-y)*w + (x2-x))];
  383        * </pre>
  384        * @param x        The X coordinate of the upper left pixel location.
  385        * @param y        The Y coordinate of the upper left pixel location.
  386        * @param width    Width of the pixel rectangle.
  387        * @param height   Height of the pixel rectangle.
  388        * @param outData  If non-null, data elements
  389        *                 at the specified locations are returned in this array.
  390        * @return         Byte array with data elements.
  391        */
  392       public byte[] getByteData(int x, int y, int w, int h, byte[] outData) {
  393           if ((x < this.minX) || (y < this.minY) ||
  394               (x + w > this.maxX) || (y + h > this.maxY)) {
  395               throw new ArrayIndexOutOfBoundsException
  396                   ("Coordinate out of bounds!");
  397           }
  398           if (outData == null) {
  399               outData = new byte[w * h];
  400           }
  401           int pixbits = pixelBitStride;
  402           int scanbit = dataBitOffset + (x-minX) * pixbits;
  403           int index = (y-minY) * scanlineStride;
  404           int outindex = 0;
  405           byte data[] = this.data;
  406   
  407           for (int j = 0; j < h; j++) {
  408               int bitnum = scanbit;
  409               int element;
  410   
  411               // Process initial portion of scanline
  412               int i = 0;
  413               while ((i < w) && ((bitnum & 7) != 0)) {
  414                   int shift = shiftOffset - (bitnum & 7);
  415                   outData[outindex++] =
  416                       (byte)(bitMask & (data[index + (bitnum >> 3)] >> shift));
  417                   bitnum += pixbits;
  418                   i++;
  419               }
  420   
  421               // Process central portion of scanline 8 pixels at a time
  422               int inIndex = index + (bitnum >> 3);
  423               switch (pixbits) {
  424               case 1:
  425                   for (; i < w - 7; i += 8) {
  426                       element = data[inIndex++];
  427                       outData[outindex++] = (byte)((element >> 7) & 1);
  428                       outData[outindex++] = (byte)((element >> 6) & 1);
  429                       outData[outindex++] = (byte)((element >> 5) & 1);
  430                       outData[outindex++] = (byte)((element >> 4) & 1);
  431                       outData[outindex++] = (byte)((element >> 3) & 1);
  432                       outData[outindex++] = (byte)((element >> 2) & 1);
  433                       outData[outindex++] = (byte)((element >> 1) & 1);
  434                       outData[outindex++] = (byte)(element & 1);
  435                       bitnum += 8;
  436                   }
  437                   break;
  438   
  439               case 2:
  440                   for (; i < w - 7; i += 8) {
  441                       element = data[inIndex++];
  442                       outData[outindex++] = (byte)((element >> 6) & 3);
  443                       outData[outindex++] = (byte)((element >> 4) & 3);
  444                       outData[outindex++] = (byte)((element >> 2) & 3);
  445                       outData[outindex++] = (byte)(element & 3);
  446   
  447                       element = data[inIndex++];
  448                       outData[outindex++] = (byte)((element >> 6) & 3);
  449                       outData[outindex++] = (byte)((element >> 4) & 3);
  450                       outData[outindex++] = (byte)((element >> 2) & 3);
  451                       outData[outindex++] = (byte)(element & 3);
  452   
  453                       bitnum += 16;
  454                   }
  455                   break;
  456   
  457               case 4:
  458                   for (; i < w - 7; i += 8) {
  459                       element = data[inIndex++];
  460                       outData[outindex++] = (byte)((element >> 4) & 0xf);
  461                       outData[outindex++] = (byte)(element & 0xf);
  462   
  463                       element = data[inIndex++];
  464                       outData[outindex++] = (byte)((element >> 4) & 0xf);
  465                       outData[outindex++] = (byte)(element & 0xf);
  466   
  467                       element = data[inIndex++];
  468                       outData[outindex++] = (byte)((element >> 4) & 0xf);
  469                       outData[outindex++] = (byte)(element & 0xf);
  470   
  471                       element = data[inIndex++];
  472                       outData[outindex++] = (byte)((element >> 4) & 0xf);
  473                       outData[outindex++] = (byte)(element & 0xf);
  474   
  475                       bitnum += 32;
  476                   }
  477                   break;
  478               }
  479   
  480               // Process final portion of scanline
  481               for (; i < w; i++) {
  482                   int shift = shiftOffset - (bitnum & 7);
  483                   outData[outindex++] =
  484                       (byte) (bitMask & (data[index + (bitnum >> 3)] >> shift));
  485                   bitnum += pixbits;
  486               }
  487   
  488               index += scanlineStride;
  489           }
  490   
  491           return outData;
  492       }
  493   
  494       /**
  495        * Stores the data elements at the specified location.
  496        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  497        * if the pixel coordinate is out of bounds.
  498        * A ClassCastException will be thrown if the input object is non null
  499        * and references anything other than an array of transferType.
  500        * @param x        The X coordinate of the pixel location.
  501        * @param y        The Y coordinate of the pixel location.
  502        * @param inData   An object reference to an array of type defined by
  503        *                 getTransferType() and length getNumDataElements()
  504        *                 containing the pixel data to place at x,y.
  505        */
  506       public void setDataElements(int x, int y, Object obj) {
  507           if ((x < this.minX) || (y < this.minY) ||
  508               (x >= this.maxX) || (y >= this.maxY)) {
  509               throw new ArrayIndexOutOfBoundsException
  510                   ("Coordinate out of bounds!");
  511           }
  512           byte inData[] = (byte[])obj;
  513           int bitnum = dataBitOffset + (x-minX) * pixelBitStride;
  514           int index = (y-minY) * scanlineStride + (bitnum >> 3);
  515           int shift = shiftOffset - (bitnum & 7);
  516   
  517           byte element = data[index];
  518           element &= ~(bitMask << shift);
  519           element |= (inData[0] & bitMask) << shift;
  520           data[index] = element;
  521   
  522           markDirty();
  523       }
  524   
  525       /**
  526        * Stores the Raster data at the specified location.
  527        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  528        * if the pixel coordinates are out of bounds.
  529        * @param x          The X coordinate of the pixel location.
  530        * @param y          The Y coordinate of the pixel location.
  531        * @param inRaster   Raster of data to place at x,y location.
  532        */
  533       public void setDataElements(int x, int y, Raster inRaster) {
  534           // Check if we can use fast code
  535           if (!(inRaster instanceof BytePackedRaster) ||
  536               ((BytePackedRaster)inRaster).pixelBitStride != pixelBitStride) {
  537               super.setDataElements(x, y, inRaster);
  538               return;
  539           }
  540   
  541           int srcOffX = inRaster.getMinX();
  542           int srcOffY = inRaster.getMinY();
  543           int dstOffX = srcOffX + x;
  544           int dstOffY = srcOffY + y;
  545           int width = inRaster.getWidth();
  546           int height = inRaster.getHeight();
  547           if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
  548               (dstOffX + width > this.maxX) || (dstOffY + height > this.maxY)) {
  549               throw new ArrayIndexOutOfBoundsException
  550                   ("Coordinate out of bounds!");
  551           }
  552           setDataElements(dstOffX, dstOffY,
  553                           srcOffX, srcOffY,
  554                           width, height,
  555                           (BytePackedRaster)inRaster);
  556       }
  557   
  558       /**
  559        * Stores the Raster data at the specified location.
  560        * @param dstX The absolute X coordinate of the destination pixel
  561        * that will receive a copy of the upper-left pixel of the
  562        * inRaster
  563        * @param dstY The absolute Y coordinate of the destination pixel
  564        * that will receive a copy of the upper-left pixel of the
  565        * inRaster
  566        * @param srcX The absolute X coordinate of the upper-left source
  567        * pixel that will be copied into this Raster
  568        * @param srcY The absolute Y coordinate of the upper-left source
  569        * pixel that will be copied into this Raster
  570        * @param width      The number of pixels to store horizontally
  571        * @param height     The number of pixels to store vertically
  572        * @param inRaster   BytePackedRaster of data to place at x,y location.
  573        */
  574       private void setDataElements(int dstX, int dstY,
  575                                    int srcX, int srcY,
  576                                    int width, int height,
  577                                    BytePackedRaster inRaster) {
  578           // Assume bounds checking has been performed previously
  579           if (width <= 0 || height <= 0) {
  580               return;
  581           }
  582   
  583           byte[] inData = inRaster.data;
  584           byte[] outData = this.data;
  585   
  586           int inscan = inRaster.scanlineStride;
  587           int outscan = this.scanlineStride;
  588           int inbit = inRaster.dataBitOffset +
  589                         8 * (srcY - inRaster.minY) * inscan +
  590                         (srcX - inRaster.minX) * inRaster.pixelBitStride;
  591           int outbit = (this.dataBitOffset +
  592                         8 * (dstY - minY) * outscan +
  593                         (dstX - minX) * this.pixelBitStride);
  594           int copybits = width * pixelBitStride;
  595   
  596           // Check whether the same bit alignment is present in both
  597           // Rasters; if so, we can copy whole bytes using
  598           // System.arraycopy.  If not, we must do a "funnel shift"
  599           // where adjacent bytes contribute to each destination byte.
  600           if ((inbit & 7) == (outbit & 7)) {
  601               // copy is bit aligned
  602               int bitpos = outbit & 7;
  603               if (bitpos != 0) {
  604                   int bits = 8 - bitpos;
  605                   // Copy partial bytes on left
  606                   int inbyte = inbit >> 3;
  607                   int outbyte = outbit >> 3;
  608                   int mask = 0xff >> bitpos;
  609                   if (copybits < bits) {
  610                       // Fix bug 4399076: previously had '8 - copybits' instead
  611                       // of 'bits - copybits'.
  612                       //
  613                       // Prior to the this expression, 'mask' has its rightmost
  614                       // 'bits' bits set to '1'.  We want it to have a total
  615                       // of 'copybits' bits set, therefore we want to introduce
  616                       // 'bits - copybits' zeroes on the right.
  617                       mask &= 0xff << (bits - copybits);
  618                       bits = copybits;
  619                   }
  620                   for (int j = 0; j < height; j++) {
  621                       int element = outData[outbyte];
  622                       element &= ~mask;
  623                       element |= (inData[inbyte] & mask);
  624                       outData[outbyte] = (byte) element;
  625                       inbyte += inscan;
  626                       outbyte += outscan;
  627                   }
  628                   inbit += bits;
  629                   outbit += bits;
  630                   copybits -= bits;
  631               }
  632               if (copybits >= 8) {
  633                   // Copy whole bytes
  634                   int inbyte = inbit >> 3;
  635                   int outbyte = outbit >> 3;
  636                   int copybytes = copybits >> 3;
  637                   if (copybytes == inscan && inscan == outscan) {
  638                       System.arraycopy(inData, inbyte,
  639                                        outData, outbyte,
  640                                        inscan * height);
  641                   } else {
  642                       for (int j = 0; j < height; j++) {
  643                           System.arraycopy(inData, inbyte,
  644                                            outData, outbyte,
  645                                            copybytes);
  646                           inbyte += inscan;
  647                           outbyte += outscan;
  648                       }
  649                   }
  650   
  651                   int bits = copybytes*8;
  652                   inbit += bits;
  653                   outbit += bits;
  654                   copybits -= bits;
  655               }
  656               if (copybits > 0) {
  657                   // Copy partial bytes on right
  658                   int inbyte = inbit >> 3;
  659                   int outbyte = outbit >> 3;
  660                   int mask = (0xff00 >> copybits) & 0xff;
  661                   for (int j = 0; j < height; j++) {
  662                       int element = outData[outbyte];
  663                       element &= ~mask;
  664                       element |= (inData[inbyte] & mask);
  665                       outData[outbyte] = (byte) element;
  666                       inbyte += inscan;
  667                       outbyte += outscan;
  668                   }
  669               }
  670           } else {
  671               // Unaligned case, see RFE #4284166
  672               // Note that the code in that RFE is not correct
  673   
  674               // Insert bits into the first byte of the output
  675               // if either the starting bit position is not zero or
  676               // we are writing fewer than 8 bits in total
  677               int bitpos = outbit & 7;
  678               if (bitpos != 0 || copybits < 8) {
  679                   int bits = 8 - bitpos;
  680                   int inbyte = inbit >> 3;
  681                   int outbyte = outbit >> 3;
  682   
  683                   int lshift = inbit & 7;
  684                   int rshift = 8 - lshift;
  685                   int mask = 0xff >> bitpos;
  686                   if (copybits < bits) {
  687                       // Fix mask if we're only writing a partial byte
  688                       mask &= 0xff << (bits - copybits);
  689                       bits = copybits;
  690                   }
  691                   int lastByte = inData.length - 1;
  692                   for (int j = 0; j < height; j++) {
  693                       // Read two bytes from the source if possible
  694                       // Don't worry about going over a scanline boundary
  695                       // since any extra bits won't get used anyway
  696                       byte inData0 = inData[inbyte];
  697                       byte inData1 = (byte)0;
  698                       if (inbyte < lastByte) {
  699                           inData1 = inData[inbyte + 1];
  700                       }
  701   
  702                       // Insert the new bits into the output
  703                       int element = outData[outbyte];
  704                       element &= ~mask;
  705                       element |= (((inData0 << lshift) |
  706                                    ((inData1 & 0xff) >> rshift))
  707                                   >> bitpos) & mask;
  708                       outData[outbyte] = (byte)element;
  709                       inbyte += inscan;
  710                       outbyte += outscan;
  711                   }
  712   
  713                   inbit += bits;
  714                   outbit += bits;
  715                   copybits -= bits;
  716               }
  717   
  718               // Now we have outbit & 7 == 0 so we can write
  719               // complete bytes for a while
  720   
  721               // Make sure we have work to do in the central loop
  722               // to avoid reading past the end of the scanline
  723               if (copybits >= 8) {
  724                   int inbyte = inbit >> 3;
  725                   int outbyte = outbit >> 3;
  726                   int copybytes = copybits >> 3;
  727                   int lshift = inbit & 7;
  728                   int rshift = 8 - lshift;
  729   
  730                   for (int j = 0; j < height; j++) {
  731                       int ibyte = inbyte + j*inscan;
  732                       int obyte = outbyte + j*outscan;
  733   
  734                       int inData0 = inData[ibyte];
  735                       // Combine adjacent bytes while 8 or more bits left
  736                       for (int i = 0; i < copybytes; i++) {
  737                           int inData1 = inData[ibyte + 1];
  738                           int val = (inData0 << lshift) |
  739                               ((inData1 & 0xff) >> rshift);
  740                           outData[obyte] = (byte)val;
  741                           inData0 = inData1;
  742   
  743                           ++ibyte;
  744                           ++obyte;
  745                       }
  746                   }
  747   
  748                   int bits = copybytes*8;
  749                   inbit += bits;
  750                   outbit += bits;
  751                   copybits -= bits;
  752               }
  753   
  754               // Finish last byte
  755               if (copybits > 0) {
  756                   int inbyte = inbit >> 3;
  757                   int outbyte = outbit >> 3;
  758                   int mask = (0xff00 >> copybits) & 0xff;
  759                   int lshift = inbit & 7;
  760                   int rshift = 8 - lshift;
  761   
  762                   int lastByte = inData.length - 1;
  763                   for (int j = 0; j < height; j++) {
  764                       byte inData0 = inData[inbyte];
  765                       byte inData1 = (byte)0;
  766                       if (inbyte < lastByte) {
  767                           inData1 = inData[inbyte + 1];
  768                       }
  769   
  770                       // Insert the new bits into the output
  771                       int element = outData[outbyte];
  772                       element &= ~mask;
  773                       element |= ((inData0 << lshift) |
  774                                   ((inData1 & 0xff) >> rshift)) & mask;
  775                       outData[outbyte] = (byte)element;
  776   
  777                       inbyte += inscan;
  778                       outbyte += outscan;
  779                   }
  780               }
  781           }
  782   
  783           markDirty();
  784       }
  785   
  786       /**
  787        * Copies pixels from Raster srcRaster to this WritableRaster.
  788        * For each (x, y) address in srcRaster, the corresponding pixel
  789        * is copied to address (x+dx, y+dy) in this WritableRaster,
  790        * unless (x+dx, y+dy) falls outside the bounds of this raster.
  791        * srcRaster must have the same number of bands as this WritableRaster.
  792        * The copy is a simple copy of source samples to the corresponding
  793        * destination samples.  For details, see
  794        * {@link WritableRaster#setRect(Raster)}.
  795        *
  796        * @param dx        The X translation factor from src space to dst space
  797        *                  of the copy.
  798        * @param dy        The Y translation factor from src space to dst space
  799        *                  of the copy.
  800        * @param srcRaster The Raster from which to copy pixels.
  801        */
  802       public void setRect(int dx, int dy, Raster srcRaster) {
  803           // Check if we can use fast code
  804           if (!(srcRaster instanceof BytePackedRaster) ||
  805               ((BytePackedRaster)srcRaster).pixelBitStride != pixelBitStride) {
  806               super.setRect(dx, dy, srcRaster);
  807               return;
  808           }
  809   
  810           int width  = srcRaster.getWidth();
  811           int height = srcRaster.getHeight();
  812           int srcOffX = srcRaster.getMinX();
  813           int srcOffY = srcRaster.getMinY();
  814           int dstOffX = dx+srcOffX;
  815           int dstOffY = dy+srcOffY;
  816   
  817           // Clip to this raster
  818           if (dstOffX < this.minX) {
  819               int skipX = this.minX - dstOffX;
  820               width -= skipX;
  821               srcOffX += skipX;
  822               dstOffX = this.minX;
  823           }
  824           if (dstOffY < this.minY) {
  825               int skipY = this.minY - dstOffY;
  826               height -= skipY;
  827               srcOffY += skipY;
  828               dstOffY = this.minY;
  829           }
  830           if (dstOffX+width > this.maxX) {
  831               width = this.maxX - dstOffX;
  832           }
  833           if (dstOffY+height > this.maxY) {
  834               height = this.maxY - dstOffY;
  835           }
  836   
  837           setDataElements(dstOffX, dstOffY,
  838                           srcOffX, srcOffY,
  839                           width, height,
  840                           (BytePackedRaster)srcRaster);
  841       }
  842   
  843       /**
  844        * Stores an array of data elements into the specified rectangular
  845        * region.
  846        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  847        * if the pixel coordinates are out of bounds.
  848        * A ClassCastException will be thrown if the input object is non null
  849        * and references anything other than an array of transferType.
  850        * The data elements in the
  851        * data array are assumed to be packed.  That is, a data element
  852        * at location (x2, y2) would be found at:
  853        * <pre>
  854        *      inData[((y2-y)*w + (x2-x))]
  855        * </pre>
  856        * @param x        The X coordinate of the upper left pixel location.
  857        * @param y        The Y coordinate of the upper left pixel location.
  858        * @param w        Width of the pixel rectangle.
  859        * @param h        Height of the pixel rectangle.
  860        * @param inData   An object reference to an array of type defined by
  861        *                 getTransferType() and length w*h*getNumDataElements()
  862        *                 containing the pixel data to place between x,y and
  863        *                 x+h, y+h.
  864        */
  865       public void setDataElements(int x, int y, int w, int h, Object obj) {
  866           putByteData(x, y, w, h, (byte[])obj);
  867       }
  868   
  869       /**
  870        * Stores a byte array of data elements into the specified rectangular
  871        * region.  The band index will be ignored.
  872        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  873        * if the pixel coordinates are out of bounds.
  874        * The data elements in the
  875        * data array are assumed to be packed.  That is, a data element
  876        * at location (x2, y2) would be found at:
  877        * <pre>
  878        *      inData[((y2-y)*w + (x2-x))]
  879        * </pre>
  880        * @param x        The X coordinate of the upper left pixel location.
  881        * @param y        The Y coordinate of the upper left pixel location.
  882        * @param w        Width of the pixel rectangle.
  883        * @param h        Height of the pixel rectangle.
  884        * @param band     The band to set, is ignored.
  885        * @param inData   The data elements to be stored.
  886        */
  887       public void putByteData(int x, int y, int w, int h,
  888                               int band, byte[] inData) {
  889           putByteData(x, y, w, h, inData);
  890       }
  891   
  892       /**
  893        * Stores a byte array of data elements into the specified rectangular
  894        * region.
  895        * An ArrayIndexOutOfBounds exception will be thrown at runtime
  896        * if the pixel coordinates are out of bounds.
  897        * The data elements in the
  898        * data array are assumed to be packed.  That is, a data element
  899        * at location (x2, y2) would be found at:
  900        * <pre>
  901        *      inData[((y2-y)*w + (x2-x))]
  902        * </pre>
  903        * @param x        The X coordinate of the upper left pixel location.
  904        * @param y        The Y coordinate of the upper left pixel location.
  905        * @param w        Width of the pixel rectangle.
  906        * @param h        Height of the pixel rectangle.
  907        * @param inData   The data elements to be stored.
  908        */
  909       public void putByteData(int x, int y, int w, int h, byte[] inData) {
  910           if ((x < this.minX) || (y < this.minY) ||
  911               (x + w > this.maxX) || (y + h > this.maxY)) {
  912               throw new ArrayIndexOutOfBoundsException
  913                   ("Coordinate out of bounds!");
  914           }
  915           if (w == 0 || h == 0) {
  916               return;
  917           }
  918   
  919           int pixbits = pixelBitStride;
  920           int scanbit = dataBitOffset + (x - minX) * pixbits;
  921           int index = (y - minY) * scanlineStride;
  922           int outindex = 0;
  923           byte data[] = this.data;
  924           for (int j = 0; j < h; j++) {
  925               int bitnum = scanbit;
  926               int element;
  927   
  928               // Process initial portion of scanline
  929               int i = 0;
  930               while ((i < w) && ((bitnum & 7) != 0)) {
  931                   int shift = shiftOffset - (bitnum & 7);
  932                   element = data[index + (bitnum >> 3)];
  933                   element &= ~(bitMask << shift);
  934                   element |= (inData[outindex++] & bitMask) << shift;
  935                   data[index + (bitnum >> 3)] = (byte)element;
  936   
  937                   bitnum += pixbits;
  938                   i++;
  939               }
  940   
  941               // Process central portion of scanline 8 pixels at a time
  942               int inIndex = index + (bitnum >> 3);
  943               switch (pixbits) {
  944               case 1:
  945                   for (; i < w - 7; i += 8) {
  946                       element = (inData[outindex++] & 1) << 7;
  947                       element |= (inData[outindex++] & 1) << 6;
  948                       element |= (inData[outindex++] & 1) << 5;
  949                       element |= (inData[outindex++] & 1) << 4;
  950                       element |= (inData[outindex++] & 1) << 3;
  951                       element |= (inData[outindex++] & 1) << 2;
  952                       element |= (inData[outindex++] & 1) << 1;
  953                       element |= (inData[outindex++] & 1);
  954   
  955                       data[inIndex++] = (byte)element;
  956   
  957                       bitnum += 8;
  958                   }
  959                   break;
  960   
  961               case 2:
  962                   for (; i < w - 7; i += 8) {
  963                       element = (inData[outindex++] & 3) << 6;
  964                       element |= (inData[outindex++] & 3) << 4;
  965                       element |= (inData[outindex++] & 3) << 2;
  966                       element |= (inData[outindex++] & 3);
  967                       data[inIndex++] = (byte)element;
  968   
  969                       element = (inData[outindex++] & 3) << 6;
  970                       element |= (inData[outindex++] & 3) << 4;
  971                       element |= (inData[outindex++] & 3) << 2;
  972                       element |= (inData[outindex++] & 3);
  973                       data[inIndex++] = (byte)element;
  974   
  975                       bitnum += 16;
  976                   }
  977                   break;
  978   
  979               case 4:
  980                   for (; i < w - 7; i += 8) {
  981                       element = (inData[outindex++] & 0xf) << 4;
  982                       element |= (inData[outindex++] & 0xf);
  983                       data[inIndex++] = (byte)element;
  984   
  985                       element = (inData[outindex++] & 0xf) << 4;
  986                       element |= (inData[outindex++] & 0xf);
  987                       data[inIndex++] = (byte)element;
  988   
  989                       element = (inData[outindex++] & 0xf) << 4;
  990                       element |= (inData[outindex++] & 0xf);
  991                       data[inIndex++] = (byte)element;
  992   
  993                       element = (inData[outindex++] & 0xf) << 4;
  994                       element |= (inData[outindex++] & 0xf);
  995                       data[inIndex++] = (byte)element;
  996   
  997                       bitnum += 32;
  998                   }
  999                   break;
 1000               }
 1001   
 1002               // Process final portion of scanline
 1003               for (; i < w; i++) {
 1004                   int shift = shiftOffset - (bitnum & 7);
 1005   
 1006                   element = data[index + (bitnum >> 3)];
 1007                   element &= ~(bitMask << shift);
 1008                   element |= (inData[outindex++] & bitMask) << shift;
 1009                   data[index + (bitnum >> 3)] = (byte)element;
 1010   
 1011                   bitnum += pixbits;
 1012               }
 1013   
 1014               index += scanlineStride;
 1015           }
 1016   
 1017           markDirty();
 1018       }
 1019   
 1020       /**
 1021        * Returns an int array containing all samples for a rectangle of pixels,
 1022        * one sample per array element.
 1023        * An ArrayIndexOutOfBoundsException may be thrown
 1024        * if the coordinates are not in bounds.
 1025        * @param x,&nbsp;y   the coordinates of the upper-left pixel location
 1026        * @param w      Width of the pixel rectangle
 1027        * @param h      Height of the pixel rectangle
 1028        * @param iArray An optionally pre-allocated int array
 1029        * @return the samples for the specified rectangle of pixels.
 1030        */
 1031       public int[] getPixels(int x, int y, int w, int h, int iArray[]) {
 1032           if ((x < this.minX) || (y < this.minY) ||
 1033               (x + w > this.maxX) || (y + h > this.maxY)) {
 1034               throw new ArrayIndexOutOfBoundsException
 1035                   ("Coordinate out of bounds!");
 1036           }
 1037           if (iArray == null) {
 1038               iArray = new int[w * h];
 1039           }
 1040           int pixbits = pixelBitStride;
 1041           int scanbit = dataBitOffset + (x-minX) * pixbits;
 1042           int index = (y-minY) * scanlineStride;
 1043           int outindex = 0;
 1044           byte data[] = this.data;
 1045   
 1046           for (int j = 0; j < h; j++) {
 1047               int bitnum = scanbit;
 1048               int element;
 1049   
 1050               // Process initial portion of scanline
 1051               int i = 0;
 1052               while ((i < w) && ((bitnum & 7) != 0)) {
 1053                   int shift = shiftOffset - (bitnum & 7);
 1054                   iArray[outindex++] =
 1055                       bitMask & (data[index + (bitnum >> 3)] >> shift);
 1056                   bitnum += pixbits;
 1057                   i++;
 1058               }
 1059   
 1060               // Process central portion of scanline 8 pixels at a time
 1061               int inIndex = index + (bitnum >> 3);
 1062               switch (pixbits) {
 1063               case 1:
 1064                   for (; i < w - 7; i += 8) {
 1065                       element = data[inIndex++];
 1066                       iArray[outindex++] = (element >> 7) & 1;
 1067                       iArray[outindex++] = (element >> 6) & 1;
 1068                       iArray[outindex++] = (element >> 5) & 1;
 1069                       iArray[outindex++] = (element >> 4) & 1;
 1070                       iArray[outindex++] = (element >> 3) & 1;
 1071                       iArray[outindex++] = (element >> 2) & 1;
 1072                       iArray[outindex++] = (element >> 1) & 1;
 1073                       iArray[outindex++] = element & 1;
 1074                       bitnum += 8;
 1075                   }
 1076                   break;
 1077   
 1078               case 2:
 1079                   for (; i < w - 7; i += 8) {
 1080                       element = data[inIndex++];
 1081                       iArray[outindex++] = (element >> 6) & 3;
 1082                       iArray[outindex++] = (element >> 4) & 3;
 1083                       iArray[outindex++] = (element >> 2) & 3;
 1084                       iArray[outindex++] = element & 3;
 1085   
 1086                       element = data[inIndex++];
 1087                       iArray[outindex++] = (element >> 6) & 3;
 1088                       iArray[outindex++] = (element >> 4) & 3;
 1089                       iArray[outindex++] = (element >> 2) & 3;
 1090                       iArray[outindex++] = element & 3;
 1091   
 1092                       bitnum += 16;
 1093                   }
 1094                   break;
 1095   
 1096               case 4:
 1097                   for (; i < w - 7; i += 8) {
 1098                       element = data[inIndex++];
 1099                       iArray[outindex++] = (element >> 4) & 0xf;
 1100                       iArray[outindex++] = element & 0xf;
 1101   
 1102                       element = data[inIndex++];
 1103                       iArray[outindex++] = (element >> 4) & 0xf;
 1104                       iArray[outindex++] = element & 0xf;
 1105   
 1106                       element = data[inIndex++];
 1107                       iArray[outindex++] = (element >> 4) & 0xf;
 1108                       iArray[outindex++] = element & 0xf;
 1109   
 1110                       element = data[inIndex++];
 1111                       iArray[outindex++] = (element >> 4) & 0xf;
 1112                       iArray[outindex++] = element & 0xf;
 1113   
 1114                       bitnum += 32;
 1115                   }
 1116                   break;
 1117               }
 1118   
 1119               // Process final portion of scanline
 1120               for (; i < w; i++) {
 1121                   int shift = shiftOffset - (bitnum & 7);
 1122                   iArray[outindex++] =
 1123                       bitMask & (data[index + (bitnum >> 3)] >> shift);
 1124                   bitnum += pixbits;
 1125               }
 1126   
 1127               index += scanlineStride;
 1128           }
 1129   
 1130           return iArray;
 1131       }
 1132   
 1133       /**
 1134        * Sets all samples for a rectangle of pixels from an int array containing
 1135        * one sample per array element.
 1136        * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
 1137        * not in bounds.
 1138        * @param x        The X coordinate of the upper left pixel location.
 1139        * @param y        The Y coordinate of the upper left pixel location.
 1140        * @param w        Width of the pixel rectangle.
 1141        * @param h        Height of the pixel rectangle.
 1142        * @param iArray   The input int pixel array.
 1143        */
 1144       public void setPixels(int x, int y, int w, int h, int iArray[]) {
 1145           if ((x < this.minX) || (y < this.minY) ||
 1146               (x + w > this.maxX) || (y + h > this.maxY)) {
 1147               throw new ArrayIndexOutOfBoundsException
 1148                   ("Coordinate out of bounds!");
 1149           }
 1150           int pixbits = pixelBitStride;
 1151           int scanbit = dataBitOffset + (x - minX) * pixbits;
 1152           int index = (y - minY) * scanlineStride;
 1153           int outindex = 0;
 1154           byte data[] = this.data;
 1155           for (int j = 0; j < h; j++) {
 1156               int bitnum = scanbit;
 1157               int element;
 1158   
 1159               // Process initial portion of scanline
 1160               int i = 0;
 1161               while ((i < w) && ((bitnum & 7) != 0)) {
 1162                   int shift = shiftOffset - (bitnum & 7);
 1163                   element = data[index + (bitnum >> 3)];
 1164                   element &= ~(bitMask << shift);
 1165                   element |= (iArray[outindex++] & bitMask) << shift;
 1166                   data[index + (bitnum >> 3)] = (byte)element;
 1167   
 1168                   bitnum += pixbits;
 1169                   i++;
 1170               }
 1171   
 1172               // Process central portion of scanline 8 pixels at a time
 1173               int inIndex = index + (bitnum >> 3);
 1174               switch (pixbits) {
 1175               case 1:
 1176                   for (; i < w - 7; i += 8) {
 1177                       element = (iArray[outindex++] & 1) << 7;
 1178                       element |= (iArray[outindex++] & 1) << 6;
 1179                       element |= (iArray[outindex++] & 1) << 5;
 1180                       element |= (iArray[outindex++] & 1) << 4;
 1181                       element |= (iArray[outindex++] & 1) << 3;
 1182                       element |= (iArray[outindex++] & 1) << 2;
 1183                       element |= (iArray[outindex++] & 1) << 1;
 1184                       element |= (iArray[outindex++] & 1);
 1185                       data[inIndex++] = (byte)element;
 1186   
 1187                       bitnum += 8;
 1188                   }
 1189                   break;
 1190   
 1191               case 2:
 1192                   for (; i < w - 7; i += 8) {
 1193                       element = (iArray[outindex++] & 3) << 6;
 1194                       element |= (iArray[outindex++] & 3) << 4;
 1195                       element |= (iArray[outindex++] & 3) << 2;
 1196                       element |= (iArray[outindex++] & 3);
 1197                       data[inIndex++] = (byte)element;
 1198   
 1199                       element = (iArray[outindex++] & 3) << 6;
 1200                       element |= (iArray[outindex++] & 3) << 4;
 1201                       element |= (iArray[outindex++] & 3) << 2;
 1202                       element |= (iArray[outindex++] & 3);
 1203                       data[inIndex++] = (byte)element;
 1204   
 1205                       bitnum += 16;
 1206                   }
 1207                   break;
 1208   
 1209               case 4:
 1210                   for (; i < w - 7; i += 8) {
 1211                       element = (iArray[outindex++] & 0xf) << 4;
 1212                       element |= (iArray[outindex++] & 0xf);
 1213                       data[inIndex++] = (byte)element;
 1214   
 1215                       element = (iArray[outindex++] & 0xf) << 4;
 1216                       element |= (iArray[outindex++] & 0xf);
 1217                       data[inIndex++] = (byte)element;
 1218   
 1219                       element = (iArray[outindex++] & 0xf) << 4;
 1220                       element |= (iArray[outindex++] & 0xf);
 1221                       data[inIndex++] = (byte)element;
 1222   
 1223                       element = (iArray[outindex++] & 0xf) << 4;
 1224                       element |= (iArray[outindex++] & 0xf);
 1225                       data[inIndex++] = (byte)element;
 1226   
 1227                       bitnum += 32;
 1228                   }
 1229                   break;
 1230               }
 1231   
 1232               // Process final portion of scanline
 1233               for (; i < w; i++) {
 1234                   int shift = shiftOffset - (bitnum & 7);
 1235   
 1236                   element = data[index + (bitnum >> 3)];
 1237                   element &= ~(bitMask << shift);
 1238                   element |= (iArray[outindex++] & bitMask) << shift;
 1239                   data[index + (bitnum >> 3)] = (byte)element;
 1240   
 1241                   bitnum += pixbits;
 1242               }
 1243   
 1244               index += scanlineStride;
 1245           }
 1246   
 1247           markDirty();
 1248       }
 1249   
 1250       /**
 1251        * Creates a subraster given a region of the raster.  The x and y
 1252        * coordinates specify the horizontal and vertical offsets
 1253        * from the upper-left corner of this raster to the upper-left corner
 1254        * of the subraster.  Note that the subraster will reference the same
 1255        * DataBuffer as the parent raster, but using different offsets. The
 1256        * bandList is ignored.
 1257        * @param x               X offset.
 1258        * @param y               Y offset.
 1259        * @param width           Width (in pixels) of the subraster.
 1260        * @param height          Height (in pixels) of the subraster.
 1261        * @param x0              Translated X origin of the subraster.
 1262        * @param y0              Translated Y origin of the subraster.
 1263        * @param bandList        Array of band indices.
 1264        * @exception RasterFormatException
 1265        *            if the specified bounding box is outside of the parent raster.
 1266        */
 1267       public Raster createChild(int x, int y,
 1268                                 int width, int height,
 1269                                 int x0, int y0, int[] bandList) {
 1270           WritableRaster newRaster = createWritableChild(x, y,
 1271                                                          width, height,
 1272                                                          x0, y0,
 1273                                                          bandList);
 1274           return (Raster) newRaster;
 1275       }
 1276   
 1277       /**
 1278        * Creates a Writable subRaster given a region of the Raster. The x and y
 1279        * coordinates specify the horizontal and vertical offsets
 1280        * from the upper-left corner of this Raster to the upper-left corner
 1281        * of the subRaster.  The bandList is ignored.
 1282        * A translation to the subRaster may also be specified.
 1283        * Note that the subRaster will reference the same
 1284        * DataBuffer as the parent Raster, but using different offsets.
 1285        * @param x               X offset.
 1286        * @param y               Y offset.
 1287        * @param width           Width (in pixels) of the subraster.
 1288        * @param height          Height (in pixels) of the subraster.
 1289        * @param x0              Translated X origin of the subraster.
 1290        * @param y0              Translated Y origin of the subraster.
 1291        * @param bandList        Array of band indices.
 1292        * @exception RasterFormatException
 1293        *            if the specified bounding box is outside of the parent Raster.
 1294        */
 1295       public WritableRaster createWritableChild(int x, int y,
 1296                                                 int width, int height,
 1297                                                 int x0, int y0,
 1298                                                 int[] bandList) {
 1299           if (x < this.minX) {
 1300               throw new RasterFormatException("x lies outside the raster");
 1301           }
 1302           if (y < this.minY) {
 1303               throw new RasterFormatException("y lies outside the raster");
 1304           }
 1305           if ((x+width < x) || (x+width > this.minX + this.width)) {
 1306               throw new RasterFormatException("(x + width) is outside of Raster");
 1307           }
 1308           if ((y+height < y) || (y+height > this.minY + this.height)) {
 1309               throw new RasterFormatException("(y + height) is outside of Raster");
 1310           }
 1311   
 1312           SampleModel sm;
 1313   
 1314           if (bandList != null) {
 1315               sm = sampleModel.createSubsetSampleModel(bandList);
 1316           }
 1317           else {
 1318               sm = sampleModel;
 1319           }
 1320   
 1321           int deltaX = x0 - x;
 1322           int deltaY = y0 - y;
 1323   
 1324           return new BytePackedRaster(sm,
 1325                                       dataBuffer,
 1326                                       new Rectangle(x0, y0, width, height),
 1327                                       new Point(sampleModelTranslateX+deltaX,
 1328                                                 sampleModelTranslateY+deltaY),
 1329                                       this);
 1330       }
 1331   
 1332       /**
 1333        * Creates a raster with the same layout but using a different
 1334        * width and height, and with new zeroed data arrays.
 1335        */
 1336       public WritableRaster createCompatibleWritableRaster(int w, int h) {
 1337           if (w <= 0 || h <=0) {
 1338               throw new RasterFormatException("negative "+
 1339                                             ((w <= 0) ? "width" : "height"));
 1340           }
 1341   
 1342           SampleModel sm = sampleModel.createCompatibleSampleModel(w,h);
 1343   
 1344           return new BytePackedRaster(sm, new Point(0,0));
 1345       }
 1346   
 1347       /**
 1348        * Creates a raster with the same layout and the same
 1349        * width and height, and with new zeroed data arrays.
 1350        */
 1351       public WritableRaster createCompatibleWritableRaster () {
 1352           return createCompatibleWritableRaster(width,height);
 1353       }
 1354   
 1355       /**
 1356        * Verify that the layout parameters are consistent with
 1357        * the data.  If strictCheck
 1358        * is false, this method will check for ArrayIndexOutOfBounds conditions.
 1359        * If strictCheck is true, this method will check for additional error
 1360        * conditions such as line wraparound (width of a line greater than
 1361        * the scanline stride).
 1362        * @return   String   Error string, if the layout is incompatible with
 1363        *                    the data.  Otherwise returns null.
 1364        */
 1365       private void verify (boolean strictCheck) {
 1366           // Make sure data for Raster is in a legal range
 1367           if (dataBitOffset < 0) {
 1368               throw new RasterFormatException("Data offsets must be >= 0");
 1369           }
 1370   
 1371           int lastbit = (dataBitOffset
 1372                          + (height-1) * scanlineStride * 8
 1373                          + (width-1) * pixelBitStride
 1374                          + pixelBitStride - 1);
 1375           if (lastbit / 8 >= data.length) {
 1376               throw new RasterFormatException("raster dimensions overflow " +
 1377                                               "array bounds");
 1378           }
 1379           if (strictCheck) {
 1380               if (height > 1) {
 1381                   lastbit = width * pixelBitStride - 1;
 1382                   if (lastbit / 8 >= scanlineStride) {
 1383                       throw new RasterFormatException("data for adjacent" +
 1384                                                       " scanlines overlaps");
 1385                   }
 1386               }
 1387           }
 1388       }
 1389   
 1390       public String toString() {
 1391           return new String ("BytePackedRaster: width = "+width+" height = "+height
 1392                              +" #channels "+numBands
 1393                              +" xOff = "+sampleModelTranslateX
 1394                              +" yOff = "+sampleModelTranslateY);
 1395       }
 1396   }

Home » openjdk-7 » sun » awt » image » [javadoc | source]