Source for java.awt.image.SinglePixelPackedSampleModel

   1: /* Copyright (C) 2000, 2002, 2003, 2004, 2006,  Free Software Foundation
   2: 
   3: This file is part of GNU Classpath.
   4: 
   5: GNU Classpath is free software; you can redistribute it and/or modify
   6: it under the terms of the GNU General Public License as published by
   7: the Free Software Foundation; either version 2, or (at your option)
   8: any later version.
   9: 
  10: GNU Classpath is distributed in the hope that it will be useful, but
  11: WITHOUT ANY WARRANTY; without even the implied warranty of
  12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13: General Public License for more details.
  14: 
  15: You should have received a copy of the GNU General Public License
  16: along with GNU Classpath; see the file COPYING.  If not, write to the
  17: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  18: 02110-1301 USA.
  19: 
  20: Linking this library statically or dynamically with other modules is
  21: making a combined work based on this library.  Thus, the terms and
  22: conditions of the GNU General Public License cover the whole
  23: combination.
  24: 
  25: As a special exception, the copyright holders of this library give you
  26: permission to link this library with independent modules to produce an
  27: executable, regardless of the license terms of these independent
  28: modules, and to copy and distribute the resulting executable under
  29: terms of your choice, provided that you also meet, for each linked
  30: independent module, the terms and conditions of the license of that
  31: module.  An independent module is a module which is not derived from
  32: or based on this library.  If you modify this library, you may extend
  33: this exception to your version of the library, but you are not
  34: obligated to do so.  If you do not wish to do so, delete this
  35: exception statement from your version. */
  36: 
  37: package java.awt.image;
  38: 
  39: import java.util.Arrays;
  40: 
  41: import gnu.java.awt.BitMaskExtent;
  42: import gnu.java.awt.Buffers;
  43: 
  44: /**
  45:  * A <code>SampleModel</code> used when all samples are stored in a single
  46:  * data element in the {@link DataBuffer}, and each data element contains 
  47:  * samples for one pixel only.
  48:  * 
  49:  * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
  50:  */
  51: public class SinglePixelPackedSampleModel extends SampleModel
  52: {
  53:   private int scanlineStride;
  54:   private int[] bitMasks;
  55:   private int[] bitOffsets;
  56:   private int[] sampleSize;
  57:   
  58:   /**
  59:    * Creates a new <code>SinglePixelPackedSampleModel</code>.
  60:    * 
  61:    * @param dataType  the data buffer type.
  62:    * @param w  the width (in pixels).
  63:    * @param h  the height (in pixels).
  64:    * @param bitMasks  an array containing the bit mask used to extract the
  65:    *     sample value for each band.
  66:    */
  67:   public SinglePixelPackedSampleModel(int dataType, int w, int h,
  68:                       int[] bitMasks)
  69:   {
  70:     this(dataType, w, h, w, bitMasks);
  71:   }
  72: 
  73:   /**
  74:    * Creates a new <code>SinglePixelPackedSampleModel</code>.
  75:    * 
  76:    * @param dataType  the data buffer type.
  77:    * @param w  the width (in pixels).
  78:    * @param h  the height (in pixels).
  79:    * @param scanlineStride  the number of data elements between a pixel on one
  80:    *     row and the corresponding pixel on the next row.
  81:    * @param bitMasks  an array containing the bit mask used to extract the
  82:    *     sample value for each band.
  83:    */
  84:   public SinglePixelPackedSampleModel(int dataType, int w, int h,
  85:                       int scanlineStride, int[] bitMasks)
  86:   {
  87:     super(dataType, w, h, bitMasks.length);
  88: 
  89:     switch (dataType)
  90:       {
  91:       case DataBuffer.TYPE_BYTE:
  92:       case DataBuffer.TYPE_USHORT:
  93:       case DataBuffer.TYPE_INT:
  94:     break;
  95:       default:
  96:         throw new IllegalArgumentException(
  97:             "SinglePixelPackedSampleModel unsupported dataType");
  98:       }
  99:     
 100:     this.scanlineStride = scanlineStride;
 101:     this.bitMasks = bitMasks;
 102:     
 103:     bitOffsets = new int[numBands];
 104:     sampleSize = new int[numBands];
 105:     
 106:     BitMaskExtent extent = new BitMaskExtent();
 107:     for (int b = 0; b < numBands; b++)
 108:       {
 109:         // the mask is an unsigned integer
 110:         long mask = bitMasks[b] & 0xFFFFFFFFL;
 111:         extent.setMask(mask);
 112:         sampleSize[b] = extent.bitWidth;
 113:         bitOffsets[b] = extent.leastSignificantBit;
 114:       }
 115:   }
 116: 
 117:   /**
 118:    * Returns the number of data elements.
 119:    * 
 120:    * @return <code>1</code>.
 121:    */
 122:   public int getNumDataElements()
 123:   {
 124:     return 1;
 125:   }
 126: 
 127:   /**
 128:    * Creates a new <code>SampleModel</code> that is compatible with this
 129:    * model and has the specified width and height.
 130:    * 
 131:    * @param w  the width (in pixels).
 132:    * @param h  the height (in pixels).
 133:    * 
 134:    * @return The new sample model.
 135:    */
 136:   public SampleModel createCompatibleSampleModel(int w, int h)
 137:   {
 138:     /* FIXME: We can avoid recalculation of bit offsets and sample
 139:        sizes here by passing these from the current instance to a
 140:        special private constructor. */
 141:     return new SinglePixelPackedSampleModel(dataType, w, h, bitMasks);
 142:   }
 143: 
 144: 
 145:   /**
 146:    * Creates a DataBuffer for holding pixel data in the format and
 147:    * layout described by this SampleModel. The returned buffer will
 148:    * consist of one single bank.
 149:    * 
 150:    * @return The data buffer.
 151:    */
 152:   public DataBuffer createDataBuffer()
 153:   {
 154:     int size;
 155: 
 156:     // We can save (scanlineStride - width) pixels at the very end of
 157:     // the buffer. The Sun reference implementation (J2SE 1.3.1 and
 158:     // 1.4.1_01) seems to do this; tested with Mauve test code.
 159:     size = scanlineStride * (height - 1) + width;
 160: 
 161:     return Buffers.createBuffer(getDataType(), size);
 162:   }
 163: 
 164:   /**
 165:    * Returns an array containing the size (in bits) for each band accessed by
 166:    * the <code>SampleModel</code>.
 167:    * 
 168:    * @return An array.
 169:    * 
 170:    * @see #getSampleSize(int)
 171:    */
 172:   public int[] getSampleSize()
 173:   {
 174:     return (int[]) sampleSize.clone();
 175:   }
 176:   
 177:   /**
 178:    * Returns the size (in bits) of the samples for the specified band.
 179:    * 
 180:    * @param band  the band (in the range <code>0</code> to 
 181:    *     <code>getNumBands() - 1</code>).
 182:    *     
 183:    * @return The sample size (in bits).
 184:    */
 185:   public int getSampleSize(int band)
 186:   {
 187:     return sampleSize[band];
 188:   }
 189: 
 190:   /**
 191:    * Returns the index in the data buffer that stores the pixel at (x, y).
 192:    * 
 193:    * @param x  the x-coordinate.
 194:    * @param y  the y-coordinate.
 195:    * 
 196:    * @return The index in the data buffer that stores the pixel at (x, y).
 197:    */
 198:   public int getOffset(int x, int y)
 199:   {
 200:     return scanlineStride*y + x;
 201:   }
 202: 
 203:   public int[] getBitOffsets()
 204:   {
 205:     return bitOffsets;
 206:   }
 207: 
 208:   public int[] getBitMasks()
 209:   {
 210:     return bitMasks;
 211:   }
 212: 
 213:   /**
 214:    * Returns the number of data elements from a pixel in one row to the
 215:    * corresponding pixel in the next row.
 216:    * 
 217:    * @return The scanline stride.
 218:    */
 219:   public int getScanlineStride()
 220:   {
 221:     return scanlineStride;
 222:   }
 223: 
 224:   /**
 225:    * Creates a new <code>SinglePixelPackedSampleModel</code> that accesses
 226:    * the specified subset of bands.
 227:    * 
 228:    * @param bands  an array containing band indices (<code>null</code> not
 229:    *     permitted).
 230:    * 
 231:    * @return A new sample model.
 232:    * 
 233:    * @throws NullPointerException if <code>bands</code> is <code>null</code>.
 234:    * @throws RasterFormatException if <code>bands.length</code> is greater
 235:    *     than the number of bands in this model.
 236:    */
 237:   public SampleModel createSubsetSampleModel(int[] bands)
 238:   {
 239:     if (bands.length > numBands)
 240:       throw new RasterFormatException("Too many bands.");
 241:     
 242:     int numBands = bands.length;
 243:     
 244:     int[] bitMasks = new int[numBands];
 245: 
 246:     for (int b = 0; b < numBands; b++)
 247:       bitMasks[b] = this.bitMasks[bands[b]];
 248: 
 249:     return new SinglePixelPackedSampleModel(dataType, width, height,
 250:                         scanlineStride, bitMasks);
 251:   }
 252: 
 253:   public Object getDataElements(int x, int y, Object obj,
 254:                 DataBuffer data)
 255:   {
 256:     int offset = scanlineStride*y + x + data.getOffset();
 257:     
 258:     return Buffers.getData(data, offset, obj,
 259:                0, // destination offset,
 260:                1  // length
 261:                );
 262:   }
 263:   
 264:   /**
 265:    * This is a more efficient implementation of the default implementation in 
 266:    * the super class. 
 267:    * @param x The x-coordinate of the pixel rectangle to store in 
 268:    *     <code>obj</code>.
 269:    * @param y The y-coordinate of the pixel rectangle to store in 
 270:    *     <code>obj</code>.
 271:    * @param w The width of the pixel rectangle to store in <code>obj</code>.
 272:    * @param h The height of the pixel rectangle to store in <code>obj</code>.
 273:    * @param obj The primitive array to store the pixels into or null to force 
 274:    *     creation.
 275:    * @param data The DataBuffer that is the source of the pixel data.
 276:    * @return The primitive array containing the pixel data.
 277:    * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, 
 278:    *     java.lang.Object, java.awt.image.DataBuffer)
 279:    */
 280:   public Object getDataElements(int x, int y, int w, int h, Object obj,
 281:                             DataBuffer data)
 282:   {
 283:     int size = w*h;
 284:     int dataSize = size;
 285:     Object pixelData = null;
 286:     switch (getTransferType())
 287:     {
 288:       case DataBuffer.TYPE_BYTE:
 289:         pixelData = ((DataBufferByte) data).getData();
 290:         if (obj == null) obj = new byte[dataSize];
 291:         break;
 292:        case DataBuffer.TYPE_USHORT:
 293:          pixelData = ((DataBufferUShort) data).getData();
 294:          if (obj == null) obj = new short[dataSize];
 295:          break;
 296:         case DataBuffer.TYPE_INT:
 297:           pixelData = ((DataBufferInt) data).getData();
 298:           if (obj == null) obj = new int[dataSize];
 299:           break;
 300:          default:
 301:              // Seems like the only sensible thing to do.
 302:            throw new ClassCastException();
 303:       }
 304:       if(x == 0 && scanlineStride == w)
 305:       { 
 306:         // The full width need to be copied therefore we can copy in one shot.
 307:         System.arraycopy(pixelData, scanlineStride*y + data.getOffset(), obj, 
 308:                          0, size);
 309:       }
 310:       else
 311:       {  
 312:         // Since we do not need the full width we need to copy line by line.
 313:         int outOffset = 0;
 314:         int dataOffset = scanlineStride*y + x + data.getOffset();
 315:         for (int yy = y; yy<(y+h); yy++)
 316:         {
 317:           System.arraycopy(pixelData, dataOffset, obj, outOffset, w);
 318:           dataOffset += scanlineStride;
 319:           outOffset += w;
 320:         }
 321:       }
 322:     return obj;
 323:   }
 324:   
 325:   /**
 326:    * Returns an array containing the samples for the pixel at (x, y) in the
 327:    * specified data buffer.  If <code>iArray</code> is not <code>null</code>,
 328:    * it will be populated with the sample values and returned as the result of
 329:    * this function (this avoids allocating a new array instance).
 330:    * 
 331:    * @param x  the x-coordinate of the pixel.
 332:    * @param y  the y-coordinate of the pixel.
 333:    * @param iArray  an array to populate with the sample values and return as 
 334:    *     the result (if <code>null</code>, a new array will be allocated).
 335:    * @param data  the data buffer (<code>null</code> not permitted).
 336:    * 
 337:    * @return The pixel sample values.
 338:    * 
 339:    * @throws NullPointerException if <code>data</code> is <code>null</code>.
 340:    */
 341:   public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
 342:   {
 343:     int offset = scanlineStride*y + x;
 344:     if (iArray == null) iArray = new int[numBands];
 345:     int samples = data.getElem(offset);
 346: 
 347:     for (int b = 0; b < numBands; b++)
 348:       iArray[b] = (samples & bitMasks[b]) >>> bitOffsets[b];
 349:     
 350:     return iArray;
 351:   }
 352: 
 353:   /**
 354:    * Returns an array containing the samples for the pixels in the region 
 355:    * specified by (x, y, w, h) in the specified data buffer.  The array is
 356:    * ordered by pixels (that is, all the samples for the first pixel are 
 357:    * grouped together, followed by all the samples for the second pixel, and so
 358:    * on).  If <code>iArray</code> is not <code>null</code>, it will be 
 359:    * populated with the sample values and returned as the result of this 
 360:    * function (this avoids allocating a new array instance).
 361:    * 
 362:    * @param x  the x-coordinate of the top-left pixel.
 363:    * @param y  the y-coordinate of the top-left pixel.
 364:    * @param w  the width of the region of pixels.
 365:    * @param h  the height of the region of pixels.
 366:    * @param iArray  an array to populate with the sample values and return as 
 367:    *     the result (if <code>null</code>, a new array will be allocated).
 368:    * @param data  the data buffer (<code>null</code> not permitted).
 369:    * 
 370:    * @return The pixel sample values.
 371:    * 
 372:    * @throws NullPointerException if <code>data</code> is <code>null</code>.
 373:    */
 374:   public int[] getPixels(int x, int y, int w, int h, int[] iArray,
 375:              DataBuffer data)
 376:   {
 377:     int offset = scanlineStride*y + x;
 378:     if (iArray == null) iArray = new int[numBands*w*h];
 379:     int outOffset = 0;
 380:     for (y = 0; y < h; y++)
 381:       {
 382:     int lineOffset = offset;
 383:     for (x = 0; x < w; x++)
 384:       {
 385:         int samples = data.getElem(lineOffset++);
 386:         for (int b = 0; b < numBands; b++)
 387:           iArray[outOffset++] = (samples & bitMasks[b]) >>> bitOffsets[b];
 388:       }
 389:     offset += scanlineStride;
 390:       }
 391:     return iArray;    
 392:   }
 393: 
 394:   /**
 395:    * Returns the sample value for the pixel at (x, y) in the specified data 
 396:    * buffer.
 397:    * 
 398:    * @param x  the x-coordinate of the pixel.
 399:    * @param y  the y-coordinate of the pixel.
 400:    * @param b  the band (in the range <code>0</code> to 
 401:    *     <code>getNumBands() - 1</code>).
 402:    * @param data  the data buffer (<code>null</code> not permitted).
 403:    * 
 404:    * @return The sample value.
 405:    * 
 406:    * @throws NullPointerException if <code>data</code> is <code>null</code>.
 407:    */
 408:   public int getSample(int x, int y, int b, DataBuffer data)
 409:   {
 410:     int offset = scanlineStride*y + x;
 411:     int samples = data.getElem(offset);
 412:     return (samples & bitMasks[b]) >>> bitOffsets[b];
 413:   }
 414:   
 415:   /**
 416:    * This method implements a more efficient way to set data elements than the 
 417:    * default implementation of the super class. It sets the data elements line 
 418:    * by line instead of pixel by pixel.
 419:    * 
 420:    * @param x The x-coordinate of the data elements in <code>obj</code>.
 421:    * @param y The y-coordinate of the data elements in <code>obj</code>.
 422:    * @param w The width of the data elements in <code>obj</code>.
 423:    * @param h The height of the data elements in <code>obj</code>.
 424:    * @param obj The primitive array containing the data elements to set.
 425:    * @param data The DataBuffer to store the data elements into.
 426:    * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, 
 427:    *     java.lang.Object, java.awt.image.DataBuffer)
 428:    */
 429:   public void setDataElements(int x, int y, int w, int h,
 430:                 Object obj, DataBuffer data)
 431:   {
 432:     
 433:     Object pixelData;
 434:     switch (getTransferType())
 435:     {
 436:       case DataBuffer.TYPE_BYTE:
 437:         pixelData = ((DataBufferByte) data).getData();
 438:         break;
 439:        case DataBuffer.TYPE_USHORT:
 440:          pixelData = ((DataBufferUShort) data).getData();
 441:          break;
 442:        case DataBuffer.TYPE_INT:
 443:          pixelData = ((DataBufferInt) data).getData();
 444:          break;
 445:        default:
 446:           // Seems like the only sensible thing to do.
 447:           throw new ClassCastException();
 448:     }
 449:     
 450:     int inOffset = 0;
 451:     int dataOffset = scanlineStride*y + x + data.getOffset();
 452:     for (int yy=y; yy<(y+h); yy++)
 453:     {
 454:       System.arraycopy(obj,inOffset,pixelData,dataOffset,w);
 455:       dataOffset += scanlineStride;
 456:       inOffset += w;
 457:     }
 458:   }
 459:   
 460:   
 461:   public void setDataElements(int x, int y, Object obj, DataBuffer data)
 462:   {
 463:     int offset = scanlineStride*y + x + data.getOffset();
 464:     
 465:     int transferType = getTransferType();
 466:     if (getTransferType() != data.getDataType())
 467:       {
 468:     throw new IllegalArgumentException("transfer type ("+
 469:                        getTransferType()+"), "+
 470:                        "does not match data "+
 471:                        "buffer type (" +
 472:                        data.getDataType() +
 473:                        ").");
 474:       }
 475: 
 476:     try
 477:       {
 478:     switch (transferType)
 479:       {
 480:       case DataBuffer.TYPE_BYTE:
 481:         {
 482:           DataBufferByte out = (DataBufferByte) data;
 483:           byte[] in = (byte[]) obj;
 484:           out.getData()[offset] = in[0];
 485:           return;
 486:         }
 487:       case DataBuffer.TYPE_USHORT:
 488:         {
 489:           DataBufferUShort out = (DataBufferUShort) data;
 490:           short[] in = (short[]) obj;
 491:           out.getData()[offset] = in[0];
 492:           return;
 493:         }
 494:       case DataBuffer.TYPE_INT:
 495:         {
 496:           DataBufferInt out = (DataBufferInt) data;
 497:           int[] in = (int[]) obj;
 498:           out.getData()[offset] = in[0];
 499:           return;
 500:         }
 501:         // FIXME: Fill in the other possible types.
 502:       default:
 503:         throw new InternalError();
 504:       }
 505:       }
 506:     catch (ArrayIndexOutOfBoundsException aioobe)
 507:       {
 508:     String msg = "While writing data elements" +
 509:       ", x="+x+", y="+y+
 510:       ", width="+width+", height="+height+
 511:       ", scanlineStride="+scanlineStride+
 512:       ", offset="+offset+
 513:       ", data.getSize()="+data.getSize()+
 514:       ", data.getOffset()="+data.getOffset()+
 515:       ": " +
 516:       aioobe;
 517:     throw new ArrayIndexOutOfBoundsException(msg);
 518:       }
 519:     }
 520: 
 521:   /**
 522:    * Sets the samples for the pixel at (x, y) in the specified data buffer to
 523:    * the specified values. 
 524:    * 
 525:    * @param x  the x-coordinate of the pixel.
 526:    * @param y  the y-coordinate of the pixel.
 527:    * @param iArray  the sample values (<code>null</code> not permitted).
 528:    * @param data  the data buffer (<code>null</code> not permitted).
 529:    * 
 530:    * @throws NullPointerException if either <code>iArray</code> or 
 531:    *     <code>data</code> is <code>null</code>.
 532:    */
 533:   public void setPixel(int x, int y, int[] iArray, DataBuffer data)
 534:   {
 535:     int offset = scanlineStride*y + x;
 536:     
 537:     int samples = 0;
 538:     for (int b = 0; b < numBands; b++)
 539:       samples |= (iArray[b] << bitOffsets[b]) & bitMasks[b];
 540: 
 541:     data.setElem(offset, samples);
 542:   }
 543: 
 544:   /**
 545:    * This method implements a more efficient way to set pixels than the default
 546:    * implementation of the super class. It copies the pixel components directly
 547:    * from the input array instead of creating a intermediate buffer.
 548:    * @param x The x-coordinate of the pixel rectangle in <code>obj</code>.
 549:    * @param y The y-coordinate of the pixel rectangle in <code>obj</code>.
 550:    * @param w The width of the pixel rectangle in <code>obj</code>.
 551:    * @param h The height of the pixel rectangle in <code>obj</code>.
 552:    * @param iArray The primitive array containing the pixels to set.
 553:    * @param data The DataBuffer to store the pixels into.
 554:    * @see java.awt.image.SampleModel#setPixels(int, int, int, int, int[], 
 555:    *     java.awt.image.DataBuffer)
 556:    */
 557:   public void setPixels(int x, int y, int w, int h, int[] iArray,
 558:                         DataBuffer data)
 559:   {
 560:     int inOffset = 0;
 561:     int[] pixel = new int[numBands];
 562:     for (int yy=y; yy<(y+h); yy++)
 563:      {
 564:       int offset = scanlineStride*yy + x;
 565:       for (int xx=x; xx<(x+w); xx++)
 566:        { 
 567:         int samples = 0;
 568:         for (int b = 0; b < numBands; b++)
 569:           samples |= (iArray[inOffset+b] << bitOffsets[b]) & bitMasks[b];
 570:         data.setElem(0, offset, samples);
 571:         inOffset += numBands;
 572:         offset += 1;
 573:       }
 574:     }
 575:   }
 576:   
 577:   /**
 578:    * Sets the sample value for a band for the pixel at (x, y) in the 
 579:    * specified data buffer. 
 580:    * 
 581:    * @param x  the x-coordinate of the pixel.
 582:    * @param y  the y-coordinate of the pixel.
 583:    * @param b  the band (in the range <code>0</code> to 
 584:    *     <code>getNumBands() - 1</code>).
 585:    * @param s  the sample value.
 586:    * @param data  the data buffer (<code>null</code> not permitted).
 587:    * 
 588:    * @throws NullPointerException if <code>data</code> is <code>null</code>.
 589:    */
 590:   public void setSample(int x, int y, int b, int s, DataBuffer data)
 591:   {
 592:     int offset = scanlineStride*y + x;
 593:     int samples = data.getElem(offset);
 594:     int bitMask = bitMasks[b];
 595:     samples &= ~bitMask;
 596:     samples |= (s << bitOffsets[b]) & bitMask;
 597:     data.setElem(offset, samples);
 598:   }
 599:   
 600:   /**
 601:    * Tests this sample model for equality with an arbitrary object.  This 
 602:    * method returns <code>true</code> if and only if:
 603:    * <ul>
 604:    *   <li><code>obj</code> is not <code>null</code>;
 605:    *   <li><code>obj</code> is an instance of 
 606:    *       <code>SinglePixelPackedSampleModel</code>;
 607:    *   <li>both models have the same:
 608:    *     <ul>
 609:    *       <li><code>dataType</code>;
 610:    *       <li><code>width</code>;
 611:    *       <li><code>height</code>;
 612:    *       <li><code>numBands</code>;
 613:    *       <li><code>scanlineStride</code>;
 614:    *       <li><code>bitMasks</code>;
 615:    *       <li><code>bitOffsets</code>.
 616:    *     </ul>
 617:    *   </li>
 618:    * </ul>
 619:    * 
 620:    * @param obj  the object (<code>null</code> permitted)
 621:    * 
 622:    * @return <code>true</code> if this model is equal to <code>obj</code>, and
 623:    *     <code>false</code> otherwise.
 624:    */
 625:   public boolean equals(Object obj) 
 626:   {
 627:     if (this == obj) 
 628:       return true;
 629:     if (! (obj instanceof SinglePixelPackedSampleModel)) 
 630:       return false;
 631:     SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel) obj;
 632:     if (this.dataType != that.dataType)
 633:       return false;
 634:     if (this.width != that.width)
 635:       return false;
 636:     if (this.height != that.height)
 637:       return false;
 638:     if (this.numBands != that.numBands)
 639:       return false;
 640:     if (this.scanlineStride != that.scanlineStride)
 641:       return false;
 642:     if (!Arrays.equals(this.bitMasks, that.bitMasks))
 643:       return false;
 644:     if (!Arrays.equals(this.bitOffsets, that.bitOffsets)) 
 645:       return false;
 646:     return true;
 647:   }
 648:   
 649:   /**
 650:    * Returns a hash code for this <code>SinglePixelPackedSampleModel</code>.
 651:    * 
 652:    * @return A hash code.
 653:    */
 654:   public int hashCode()
 655:   {
 656:     // this hash code won't match Sun's, but that shouldn't matter...
 657:     int result = 193;
 658:     result = 37 * result + dataType;
 659:     result = 37 * result + width;
 660:     result = 37 * result + height;
 661:     result = 37 * result + numBands;
 662:     result = 37 * result + scanlineStride;
 663:     for (int i = 0; i < bitMasks.length; i++)
 664:       result = 37 * result + bitMasks[i];
 665:     for (int i = 0; i < bitOffsets.length; i++)
 666:       result = 37 * result + bitOffsets[i];
 667:     return result;
 668:   }
 669:   
 670:   /**
 671:    * Creates a String with some information about this SampleModel.
 672:    * @return A String describing this SampleModel.
 673:    * @see java.lang.Object#toString()
 674:    */
 675:   public String toString()
 676:   {
 677:     StringBuffer result = new StringBuffer();
 678:     result.append(getClass().getName());
 679:     result.append("[");
 680:     result.append("scanlineStride=").append(scanlineStride);
 681:     for(int i = 0; i < bitMasks.length; i+=1)
 682:     {
 683:       result.append(", mask[").append(i).append("]=0x").append(
 684:           Integer.toHexString(bitMasks[i]));
 685:     }
 686:     
 687:     result.append("]");
 688:     return result.toString();
 689:   }
 690: }