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