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