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