Source for java.awt.image.SampleModel

   1: /* Copyright (C) 2000, 2001, 2002, 2005, 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: /**
  40:  * @author Rolf W. Rasmussen (rolfwr@ii.uib.no)
  41:  */
  42: public abstract class SampleModel
  43: {
  44:   /** Width of image described. */
  45:   protected int width;
  46:   
  47:   /** Height of image described. */
  48:   protected int height;
  49:   
  50:   /** Number of bands in the image described.  Package-private here,
  51:       shadowed by ComponentSampleModel. */
  52:   protected int numBands;
  53: 
  54:   /** 
  55:    * The DataBuffer type that is used to store the data of the image
  56:    * described.
  57:    */
  58:   protected int dataType;
  59: 
  60:   /**
  61:    * Creates a new sample model with the specified attributes.
  62:    * 
  63:    * @param dataType  the data type (one of {@link DataBuffer#TYPE_BYTE},
  64:    *   {@link DataBuffer#TYPE_USHORT}, {@link DataBuffer#TYPE_SHORT},
  65:    *   {@link DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT}, 
  66:    *   {@link DataBuffer#TYPE_DOUBLE} or {@link DataBuffer#TYPE_UNDEFINED}).
  67:    * @param w  the width in pixels (must be greater than zero).
  68:    * @param h  the height in pixels (must be greater than zero).
  69:    * @param numBands  the number of bands (must be greater than zero).
  70:    * 
  71:    * @throws IllegalArgumentException if <code>dataType</code> is not one of 
  72:    *   the listed values.
  73:    * @throws IllegalArgumentException if <code>w</code> is less than or equal
  74:    *   to zero.
  75:    * @throws IllegalArgumentException if <code>h</code> is less than or equal 
  76:    *   to zero.
  77:    * @throws IllegalArgumentException if <code>w * h</code> is greater than
  78:    *   {@link Integer#MAX_VALUE}.
  79:    */
  80:   public SampleModel(int dataType, int w, int h, int numBands)
  81:   {
  82:     if (dataType != DataBuffer.TYPE_UNDEFINED)
  83:       if (dataType < DataBuffer.TYPE_BYTE || dataType > DataBuffer.TYPE_DOUBLE)
  84:         throw new IllegalArgumentException("Unrecognised 'dataType' argument.");
  85:     
  86:     if ((w <= 0) || (h <= 0)) 
  87:       throw new IllegalArgumentException((w <= 0 ? " width<=0" : " width is ok")
  88:           + (h <= 0 ? " height<=0" : " height is ok"));
  89:         
  90:     long area = (long) w * (long) h;
  91:     if (area > Integer.MAX_VALUE)
  92:       throw new IllegalArgumentException("w * h exceeds Integer.MAX_VALUE.");
  93: 
  94:     if (numBands <= 0)
  95:       throw new IllegalArgumentException("Requires numBands > 0.");
  96:       
  97:     this.dataType = dataType;
  98:     this.width = w;
  99:     this.height = h;
 100:     this.numBands = numBands;  
 101:   }
 102:   
 103:   public final int getWidth()
 104:   {
 105:     return width;
 106:   }
 107: 
 108:   public final int getHeight()
 109:   {
 110:     return height;
 111:   }
 112: 
 113:   public final int getNumBands()
 114:   {
 115:     return numBands;
 116:   }
 117:     
 118:   public abstract int getNumDataElements();
 119:   
 120:   public final int getDataType()
 121:   {
 122:     return dataType;
 123:   }
 124: 
 125:   public int getTransferType()
 126:   {
 127:     // FIXME: Is this a reasonable default implementation?
 128:     return dataType;
 129:   }
 130: 
 131:   public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
 132:   {
 133:     if (iArray == null) 
 134:       iArray = new int[numBands];
 135:     for (int b = 0; b < numBands; b++) 
 136:       iArray[b] = getSample(x, y, b, data);
 137:     return iArray;
 138:   }
 139:   
 140:   /**
 141:    *
 142:    * This method is provided as a faster alternative to getPixel(),
 143:    * that can be used when there is no need to decode the pixel into
 144:    * separate sample values.
 145:    *
 146:    * @param obj An array to return the pixel data in. If null, an
 147:    * array of the right type and size will be created.
 148:    *
 149:    * @return A single pixel as an array object of a primitive type,
 150:    * based on the transfer type. Eg. if transfer type is
 151:    * DataBuffer.TYPE_USHORT, then a short[] object is returned.
 152:    */
 153:   public abstract Object getDataElements(int x, int y, Object obj,
 154:                                          DataBuffer data);
 155: 
 156:     
 157:   public Object getDataElements(int x, int y, int w, int h, Object obj,
 158:                                 DataBuffer data)
 159:   {
 160:     int size = w * h;
 161:     int numDataElements = getNumDataElements();
 162:     int dataSize = numDataElements * size;
 163:     
 164:     if (obj == null)
 165:       {
 166:         switch (getTransferType())
 167:           {
 168:           case DataBuffer.TYPE_BYTE:
 169:             obj = new byte[dataSize];
 170:             break;
 171:           case DataBuffer.TYPE_USHORT:
 172:             obj = new short[dataSize];
 173:             break;
 174:           case DataBuffer.TYPE_INT:
 175:             obj = new int[dataSize];
 176:             break;
 177:           default:
 178:             // Seems like the only sensible thing to do.
 179:             throw new ClassCastException();
 180:           }
 181:       }
 182:     Object pixelData = null;
 183:     int outOffset = 0;
 184:     for (int yy = y; yy < (y + h); yy++)
 185:       {
 186:         for (int xx = x; xx < (x + w); xx++)
 187:           {
 188:             pixelData = getDataElements(xx, yy, pixelData, data);
 189:             System.arraycopy(pixelData, 0, obj, outOffset,
 190:                              numDataElements);
 191:             outOffset += numDataElements;
 192:           }
 193:       }
 194:     return obj;
 195:   }
 196: 
 197:   public abstract void setDataElements(int x, int y, Object obj,
 198:                                        DataBuffer data);
 199: 
 200:   public void setDataElements(int x, int y, int w, int h,
 201:                               Object obj, DataBuffer data)
 202:   {
 203:     int size = w * h;
 204:     int numDataElements = getNumDataElements();
 205:     int dataSize = numDataElements * size;
 206:     
 207:     Object pixelData;
 208:     switch (getTransferType())
 209:       {
 210:       case DataBuffer.TYPE_BYTE:
 211:         pixelData = new byte[numDataElements];
 212:         break;
 213:       case DataBuffer.TYPE_USHORT:
 214:         pixelData = new short[numDataElements];
 215:         break;
 216:       case DataBuffer.TYPE_INT:
 217:         pixelData = new int[numDataElements];
 218:         break;
 219:       default:
 220:         // Seems like the only sensible thing to do.
 221:         throw new ClassCastException();
 222:       }
 223:     int inOffset = 0;
 224: 
 225:     for (int yy = y; yy < (y + h); yy++)
 226:       {
 227:         for (int xx = x; xx < (x + w); xx++)
 228:           {
 229:             System.arraycopy(obj, inOffset, pixelData, 0,
 230:                              numDataElements);
 231:             setDataElements(xx, yy, pixelData, data);
 232:             inOffset += numDataElements;
 233:           }
 234:       }
 235:   }
 236: 
 237:   public float[] getPixel(int x, int y, float[] fArray, DataBuffer data)
 238:   {
 239:     if (fArray == null) 
 240:       fArray = new float[numBands];
 241:     
 242:     for (int b = 0; b < numBands; b++)
 243:       {
 244:         fArray[b] = getSampleFloat(x, y, b, data);
 245:       }
 246:     return fArray;
 247:   }
 248: 
 249:   public double[] getPixel(int x, int y, double[] dArray, DataBuffer data) {
 250:     if (dArray == null) 
 251:       dArray = new double[numBands];
 252:     for (int b = 0; b < numBands; b++)
 253:       {
 254:         dArray[b] = getSampleDouble(x, y, b, data);
 255:       }
 256:     return dArray;
 257:   }
 258: 
 259:   /* FIXME: Should it return a banded or pixel interleaved array of
 260:      samples? (Assume interleaved.) */
 261:   public int[] getPixels(int x, int y, int w, int h, int[] iArray,
 262:                          DataBuffer data)
 263:   {
 264:     int size = w * h;
 265:     int outOffset = 0;
 266:     int[] pixel = null;
 267:     if (iArray == null) 
 268:       iArray = new int[w * h * numBands];
 269:     for (int yy = y; yy < (y + h); yy++)
 270:       {
 271:         for (int xx = x; xx < (x + w); xx++)
 272:           {
 273:             pixel = getPixel(xx, yy, pixel, data);
 274:             System.arraycopy(pixel, 0, iArray, outOffset, numBands);
 275:             outOffset += numBands;
 276:           }
 277:       }
 278:     return iArray;
 279:   }
 280: 
 281:   /* FIXME: Should it return a banded or pixel interleaved array of
 282:      samples? (Assume interleaved.) */
 283:   public float[] getPixels(int x, int y, int w, int h, float[] fArray,
 284:                            DataBuffer data)
 285:   {
 286:     int size = w * h;
 287:     int outOffset = 0;
 288:     float[] pixel = null;
 289:     if (fArray == null) fArray = new float[w * h * numBands];
 290:     for (int yy = y; yy < (y + h); yy++)
 291:       {
 292:         for (int xx = x; xx < (x + w); xx++)
 293:           {
 294:             pixel = getPixel(xx, yy, pixel, data);
 295:             System.arraycopy(pixel, 0, fArray, outOffset, numBands);
 296:             outOffset += numBands;
 297:           }
 298:       }
 299:     return fArray;
 300:   }
 301:     
 302:   /* FIXME: Should it return a banded or pixel interleaved array of
 303:      samples? (Assume interleaved.) */
 304:   public double[] getPixels(int x, int y, int w, int h, double[] dArray,
 305:                             DataBuffer data)
 306:   {
 307:     int size = w * h;
 308:     int outOffset = 0;
 309:     double[] pixel = null;
 310:     if (dArray == null) 
 311:       dArray = new double[w * h * numBands];
 312:     for (int yy = y; yy < (y + h); yy++)
 313:       {
 314:         for (int xx = x; xx < (x + w); xx++)
 315:           {
 316:             pixel = getPixel(xx, yy, pixel, data);
 317:             System.arraycopy(pixel, 0, dArray, outOffset, numBands);
 318:             outOffset += numBands;
 319:           }
 320:       }
 321:     return dArray;
 322:   }
 323: 
 324:   public abstract int getSample(int x, int y, int b, DataBuffer data);
 325: 
 326:   public float getSampleFloat(int x, int y, int b, DataBuffer data)
 327:   {
 328:     return getSample(x, y, b, data);
 329:   }
 330: 
 331:   public double getSampleDouble(int x, int y, int b, DataBuffer data)
 332:   {
 333:     return getSampleFloat(x, y, b, data);
 334:   }
 335: 
 336:   public int[] getSamples(int x, int y, int w, int h, int b,
 337:                           int[] iArray, DataBuffer data)
 338:   {
 339:     int size = w * h;
 340:     int outOffset = 0;
 341:     if (iArray == null) 
 342:       iArray = new int[size];
 343:     for (int yy = y; yy < (y + h); yy++)
 344:       {
 345:         for (int xx = x; xx < (x + w); xx++)
 346:           {
 347:             iArray[outOffset++] = getSample(xx, yy, b, data);
 348:           }
 349:       }
 350:     return iArray;
 351:   }
 352: 
 353:   public float[] getSamples(int x, int y, int w, int h, int b,
 354:                             float[] fArray, DataBuffer data)
 355:   {
 356:     int size = w * h;
 357:     int outOffset = 0;
 358:     if (fArray == null) 
 359:       fArray = new float[size];
 360:     for (int yy = y; yy < (y + h); yy++)
 361:       {
 362:         for (int xx = x; xx < (x + w); xx++)
 363:           {
 364:             fArray[outOffset++] = getSampleFloat(xx, yy, b, data);
 365:           }
 366:       }
 367:     return fArray;
 368:   }
 369: 
 370:   public double[] getSamples(int x, int y, int w, int h, int b,
 371:                              double[] dArray, DataBuffer data)
 372:   {
 373:     int size = w * h;
 374:     int outOffset = 0;
 375:     if (dArray == null) 
 376:       dArray = new double[size];
 377:     for (int yy = y; yy < (y + h); yy++)
 378:       {
 379:         for (int xx = x; xx < (x + w); xx++)
 380:           {
 381:             dArray[outOffset++] = getSampleDouble(xx, yy, b, data);
 382:           }
 383:       }
 384:     return dArray;
 385:   }
 386:   
 387:   public void setPixel(int x, int y, int[] iArray, DataBuffer data)
 388:   {
 389:     for (int b = 0; b < numBands; b++) 
 390:       setSample(x, y, b, iArray[b], data);
 391:   }
 392: 
 393:   public void setPixel(int x, int y, float[] fArray, DataBuffer data)
 394:   {
 395:     for (int b = 0; b < numBands; b++) 
 396:       setSample(x, y, b, fArray[b], data);
 397:   }
 398: 
 399:   public void setPixel(int x, int y, double[] dArray, DataBuffer data)
 400:   {
 401:     for (int b = 0; b < numBands; b++) 
 402:       setSample(x, y, b, dArray[b], data);
 403:   }
 404: 
 405:   public void setPixels(int x, int y, int w, int h, int[] iArray,
 406:                         DataBuffer data)
 407:   {
 408:     int inOffset = 0;
 409:     int[] pixel = new int[numBands];
 410:     for (int yy = y; yy < (y + h); yy++)
 411:       {
 412:         for (int xx = x; xx < (x + w); xx++)
 413:           {
 414:             System.arraycopy(iArray, inOffset, pixel, 0, numBands);
 415:             setPixel(xx, yy, pixel, data);
 416:             inOffset += numBands;
 417:           }
 418:       }
 419:   }
 420: 
 421:   public void setPixels(int x, int y, int w, int h, float[] fArray,
 422:                         DataBuffer data)
 423:   {
 424:     int inOffset = 0;
 425:     float[] pixel = new float[numBands];
 426:     for (int yy = y; yy < (y + h); yy++)
 427:       {
 428:         for (int xx = x; xx < (x + w); xx++)
 429:           {
 430:             System.arraycopy(fArray, inOffset, pixel, 0, numBands);
 431:             setPixel(xx, yy, pixel, data);
 432:             inOffset += numBands;
 433:           }
 434:       }
 435:   }
 436: 
 437:   public void setPixels(int x, int y, int w, int h, double[] dArray,
 438:                         DataBuffer data)
 439:   {
 440:     int inOffset = 0;
 441:     double[] pixel = new double[numBands];
 442:     for (int yy = y; yy < (y + h); yy++)
 443:       {
 444:         for (int xx = x; xx < (x + w); xx++)
 445:           {
 446:             System.arraycopy(dArray, inOffset, pixel, 0, numBands);
 447:             setPixel(xx, yy, pixel, data);
 448:             inOffset += numBands;
 449:           }
 450:       }
 451:   }
 452: 
 453:   public abstract void setSample(int x, int y, int b, int s,
 454:                                  DataBuffer data);
 455: 
 456:   public void setSample(int x, int y, int b, float s,
 457:                         DataBuffer data)
 458:   {
 459:     setSample(x, y, b, (int) s, data);
 460:   }
 461: 
 462:   public void setSample(int x, int y, int b, double s,
 463:                         DataBuffer data)
 464:   {
 465:     setSample(x, y, b, (float) s, data);
 466:   }
 467: 
 468:   public void setSamples(int x, int y, int w, int h, int b,
 469:                          int[] iArray, DataBuffer data)
 470:   {
 471:     int size = w * h;
 472:     int inOffset = 0;
 473:     for (int yy = y; yy < (y + h); yy++)
 474:       for (int xx = x; xx < (x + w); xx++)
 475:         setSample(xx, yy, b, iArray[inOffset++], data);
 476:   }
 477: 
 478:   public void setSamples(int x, int y, int w, int h, int b,
 479:                          float[] fArray, DataBuffer data)
 480:   {
 481:     int size = w * h;
 482:     int inOffset = 0;
 483:     for (int yy = y; yy < (y + h); yy++)
 484:       for (int xx = x; xx < (x + w); xx++)
 485:         setSample(xx, yy, b, fArray[inOffset++], data);
 486: 
 487:   }
 488: 
 489:   public void setSamples(int x, int y, int w, int h, int b,
 490:                          double[] dArray, DataBuffer data) {
 491:     int size = w * h;
 492:     int inOffset = 0;
 493:     for (int yy = y; yy < (y + h); yy++)
 494:       for (int xx = x; xx < (x + w); xx++)
 495:         setSample(xx, yy, b, dArray[inOffset++], data);
 496:   }
 497: 
 498:   public abstract SampleModel createCompatibleSampleModel(int w, int h);
 499: 
 500:   /**
 501:    * Return a SampleModel with a subset of the bands in this model.
 502:    * 
 503:    * Selects bands.length bands from this sample model.  The bands chosen
 504:    * are specified in the indices of bands[].  This also permits permuting
 505:    * the bands as well as taking a subset.  Thus, giving an array with
 506:    * 1, 2, 3, ..., numbands, will give an identical sample model.
 507:    * 
 508:    * @param bands Array with band indices to include.
 509:    * @return A new sample model
 510:    */
 511:   public abstract SampleModel createSubsetSampleModel(int[] bands);
 512: 
 513:   public abstract DataBuffer createDataBuffer();
 514: 
 515:   public abstract int[] getSampleSize();
 516: 
 517:   public abstract int getSampleSize(int band);
 518: }