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