1 /* 2 * $RCSfile: ComponentSampleModelJAI.java,v $ 3 * 4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Use is subject to license terms. 7 * 8 * $Revision: 1.1 $ 9 * $Date: 2005/02/11 04:57:07 $ 10 * $State: Exp $ 11 */ 12 package com.lightcrafts.mediax.jai; 13 import java.awt.image.ComponentSampleModel; 14 import java.awt.image.DataBuffer; 15 import java.awt.image.DataBufferByte; 16 import java.awt.image.DataBufferShort; 17 import java.awt.image.DataBufferInt; 18 import java.awt.image.DataBufferUShort; 19 import java.awt.image.SampleModel; 20 21 import com.lightcrafts.media.jai.util.DataBufferUtils; 22 23 /** 24 * This class represents image data which is stored such that each sample 25 * of a pixel occupies one data element of the <code>DataBuffer</code>. It stores the 26 * N samples which make up a pixel in N separate data array elements. 27 * Different bands may be in different banks of the <code>DataBuffer</code>. 28 * Accessor methods are provided so that image data can be manipulated 29 * directly. This class can support different kinds of interleaving, e.g. 30 * band interleaving, scanline interleaving, and pixel interleaving. 31 * Pixel stride is the number of data array elements between two samples 32 * for the same band on the same scanline. Scanline stride is the number 33 * of data array elements between a given sample and the corresponding sample 34 * in the same column of the next scanline. Band offsets denote the number 35 * of data array elements from the first data array element of the bank 36 * of the <code>DataBuffer</code> holding each band to the first sample of the band. 37 * The bands are numbered from 0 to N-1. This class can represent image 38 * data for the dataTypes enumerated in java.awt.image.DataBuffer (all 39 * samples of a given <code>ComponentSampleModel</code> are stored with the same precision) 40 * . This class adds support for <code>Double</code> and <code>Float</code> data types in addition 41 * to those supported by the <code>ComponentSampleModel</code> class in Java 2D. 42 * All strides and offsets must be non-negative. 43 * @see java.awt.image.ComponentSampleModel 44 */ 45 46 public class ComponentSampleModelJAI extends ComponentSampleModel { 47 48 /** 49 * Constructs a <code>ComponentSampleModel</code> with the specified 50 * parameters. The number of bands will be given by the length of 51 * the bandOffsets array. All bands will be stored in the first 52 * bank of the <code>DataBuffer</code>. 53 * 54 * @param dataType The data type for storing samples. 55 * @param w The width (in pixels) of the region of 56 * image data described. 57 * @param h The height (in pixels) of the region of 58 * image data described. 59 * @param pixelStride The pixel stride of the region of image 60 * data described. 61 * @param scanlineStride The line stride of the region of image 62 * data described. 63 * @param bandOffsets The offsets of all bands. 64 */ ComponentSampleModelJAI(int dataType, int w, int h, int pixelStride, int scanlineStride, int bandOffsets[])65 public ComponentSampleModelJAI(int dataType, 66 int w, int h, 67 int pixelStride, 68 int scanlineStride, 69 int bandOffsets[]) { 70 super(dataType, w, h, pixelStride, scanlineStride, bandOffsets); 71 } 72 73 74 /** 75 * Constructs a <code>ComponentSampleModel</code> with the specified 76 * parameters. The number of bands will be given by the length of 77 * the bandOffsets array. Different bands may be stored in 78 * different banks of the <code>DataBuffer</code>. 79 * 80 * @param dataType The data type for storing samples. 81 * @param w The width (in pixels) of the region of 82 * image data described. 83 * @param h The height (in pixels) of the region of 84 * image data described. 85 * @param pixelStride The pixel stride of the region of image 86 * data described. 87 * @param scanlineStride The line stride of the region of image 88 * data described. 89 * @param bankIndices The bank indices of all bands. 90 * @param bandOffsets The band offsets of all bands. 91 */ ComponentSampleModelJAI(int dataType, int w, int h, int pixelStride, int scanlineStride, int bankIndices[], int bandOffsets[])92 public ComponentSampleModelJAI(int dataType, 93 int w, int h, 94 int pixelStride, 95 int scanlineStride, 96 int bankIndices[], 97 int bandOffsets[]) { 98 super(dataType, w, h, pixelStride, scanlineStride, 99 bankIndices, bandOffsets); 100 } 101 102 /** 103 * Returns the size of the data buffer (in data elements) needed 104 * for a data buffer that matches this <code>ComponentSampleModel</code>. 105 */ getBufferSize()106 private long getBufferSize() { 107 int maxBandOff=bandOffsets[0]; 108 for (int i=1; i<bandOffsets.length; i++) 109 maxBandOff = Math.max(maxBandOff,bandOffsets[i]); 110 111 long size = 0; 112 if (maxBandOff >= 0) 113 size += maxBandOff+1; 114 if (pixelStride > 0) 115 size += pixelStride * (width-1); 116 if (scanlineStride > 0) 117 size += scanlineStride*(height-1); 118 return size; 119 } 120 121 /** 122 * Preserves band ordering with new step factor... 123 */ JAIorderBands(int orig[], int step)124 private int[] JAIorderBands(int orig[], int step) { 125 int map[] = new int[orig.length]; 126 int ret[] = new int[orig.length]; 127 128 for (int i=0; i<map.length; i++) map[i] = i; 129 130 for (int i = 0; i < ret.length; i++) { 131 int index = i; 132 for (int j = i+1; j < ret.length; j++) { 133 if (orig[map[index]] > orig[map[j]]) { 134 index = j; 135 } 136 } 137 ret[map[index]] = i*step; 138 map[index] = map[i]; 139 } 140 return ret; 141 } 142 143 /** 144 * Creates a new <code>ComponentSampleModel</code> with the specified 145 * width and height. The new <code>SampleModel</code> will have the same 146 * number of bands, storage data type, interleaving scheme, and 147 * pixel stride as this <code>SampleModel</code>. 148 * 149 * @param w The width in pixels. 150 * @param h The height in pixels 151 */ createCompatibleSampleModel(int w, int h)152 public SampleModel createCompatibleSampleModel(int w, int h) { 153 SampleModel ret=null; 154 long size; 155 int minBandOff=bandOffsets[0]; 156 int maxBandOff=bandOffsets[0]; 157 for (int i=1; i<bandOffsets.length; i++) { 158 minBandOff = Math.min(minBandOff,bandOffsets[i]); 159 maxBandOff = Math.max(maxBandOff,bandOffsets[i]); 160 } 161 maxBandOff -= minBandOff; 162 163 int bands = bandOffsets.length; 164 int bandOff[]; 165 int pStride = Math.abs(pixelStride); 166 int lStride = Math.abs(scanlineStride); 167 int bStride = Math.abs(maxBandOff); 168 169 if (pStride > lStride) { 170 if (pStride > bStride) { 171 if (lStride > bStride) { // pix > line > band 172 bandOff = new int[bandOffsets.length]; 173 for (int i=0; i<bands; i++) 174 bandOff[i] = bandOffsets[i]-minBandOff; 175 lStride = bStride+1; 176 pStride = lStride*h; 177 } else { // pix > band > line 178 bandOff = JAIorderBands(bandOffsets,lStride*h); 179 pStride = bands*lStride*h; 180 } 181 } else { // band > pix > line 182 pStride = lStride*h; 183 bandOff = JAIorderBands(bandOffsets,pStride*w); 184 } 185 } else { 186 if (pStride > bStride) { // line > pix > band 187 bandOff = new int[bandOffsets.length]; 188 for (int i=0; i<bands; i++) 189 bandOff[i] = bandOffsets[i]-minBandOff; 190 pStride = bStride+1; 191 lStride = pStride*w; 192 } else { 193 if (lStride > bStride) { // line > band > pix 194 bandOff = JAIorderBands(bandOffsets,pStride*w); 195 lStride = bands*pStride*w; 196 } else { // band > line > pix 197 lStride = pStride*w; 198 bandOff = JAIorderBands(bandOffsets,lStride*h); 199 } 200 } 201 } 202 203 // make sure we make room for negative offsets... 204 int base = 0; 205 if (scanlineStride < 0) { 206 base += lStride*h; 207 lStride *= -1; 208 } 209 if (pixelStride < 0) { 210 base += pStride*w; 211 pStride *= -1; 212 } 213 214 for (int i=0; i<bands; i++) 215 bandOff[i] += base; 216 return new ComponentSampleModelJAI(dataType, w, h, pStride, 217 lStride, bankIndices, bandOff); 218 } 219 220 /** 221 * This creates a new <code>ComponentSampleModel</code> with a subset of the bands 222 * of this <code>ComponentSampleModel</code>. The new <code>ComponentSampleModel</code> can be 223 * used with any <code>DataBuffer</code> that the existing <code>ComponentSampleModel</code> 224 * can be used with. The new <code>ComponentSampleModel</code>/<code>DataBuffer</code> 225 * combination will represent an image with a subset of the bands 226 * of the original <code>ComponentSampleModel</code>/<code>DataBuffer</code> combination. 227 * 228 * @param bands subset of bands of this <code>ComponentSampleModel</code> 229 */ createSubsetSampleModel(int bands[])230 public SampleModel createSubsetSampleModel(int bands[]) { 231 int newBankIndices[] = new int[bands.length]; 232 int newBandOffsets[] = new int[bands.length]; 233 for (int i=0; i<bands.length; i++) { 234 int b = bands[i]; 235 newBankIndices[i] = bankIndices[b]; 236 newBandOffsets[i] = bandOffsets[b]; 237 } 238 return new ComponentSampleModelJAI(this.dataType, width, height, 239 this.pixelStride, 240 this.scanlineStride, 241 newBankIndices, 242 newBandOffsets); 243 } 244 245 /** 246 * Creates a <code>DataBuffer</code> that corresponds to this <code>ComponentSampleModel</code>. 247 * The <code>DataBuffer</code>'s data type, number of banks, and size 248 * will be consistent with this <code>ComponentSampleModel</code>. 249 */ createDataBuffer()250 public DataBuffer createDataBuffer() { 251 DataBuffer dataBuffer = null; 252 253 int size = (int)getBufferSize(); 254 switch (dataType) { 255 case DataBuffer.TYPE_BYTE: 256 dataBuffer = new DataBufferByte(size, numBanks); 257 break; 258 case DataBuffer.TYPE_USHORT: 259 dataBuffer = new DataBufferUShort(size, numBanks); 260 break; 261 case DataBuffer.TYPE_INT: 262 dataBuffer = new DataBufferInt(size, numBanks); 263 break; 264 case DataBuffer.TYPE_SHORT: 265 dataBuffer = new DataBufferShort(size, numBanks); 266 break; 267 case DataBuffer.TYPE_FLOAT: 268 dataBuffer = DataBufferUtils.createDataBufferFloat(size, numBanks); 269 break; 270 case DataBuffer.TYPE_DOUBLE: 271 dataBuffer = DataBufferUtils.createDataBufferDouble(size, numBanks); 272 break; 273 default: 274 throw new RuntimeException(JaiI18N.getString("RasterFactory3")); 275 } 276 277 return dataBuffer; 278 } 279 280 281 /** 282 * Returns data for a single pixel in a primitive array of type 283 * TransferType. For a <code>ComponentSampleModel</code>, this will be the same 284 * as the data type, and samples will be returned one per array 285 * element. Generally, obj 286 * should be passed in as null, so that the <code>Object</code> will be created 287 * automatically and will be of the right primitive data type. 288 * <p> 289 * The following code illustrates transferring data for one pixel from 290 * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by 291 * <code>ComponentSampleModel</code> <code>csm1</code>, to <code>DataBuffer</code> <code>db2</code>, 292 * whose storage layout is described by 293 * <code>ComponentSampleModel</code> <code>csm2</code>. 294 * The transfer will generally be more efficient than using 295 * getPixel/setPixel. 296 * <pre> 297 * ComponentSampleModel csm1, csm2; 298 * DataBufferInt db1, db2; 299 * csm2.setDataElements(x, y, 300 * csm1.getDataElements(x, y, null, db1), db2); 301 * </pre> 302 * Using getDataElements/setDataElements to transfer between two 303 * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have 304 * the same number of bands, corresponding bands have the same number of 305 * bits per sample, and the TransferTypes are the same. 306 * <p> 307 * @param x The X coordinate of the pixel location. 308 * @param y The Y coordinate of the pixel location. 309 * @param obj If non-null, a primitive array in which to return 310 * the pixel data. 311 * @param data The <code>DataBuffer</code> containing the image data. 312 * @throws <code>ClassCastException</code> if obj is non-null and is not 313 * a primitive array of type TransferType. 314 * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates 315 * are not in bounds, or if obj is non-null and is not large 316 * enough to hold the pixel data. 317 */ getDataElements(int x, int y, Object obj, DataBuffer data)318 public Object getDataElements(int x, int y, Object obj, DataBuffer data) { 319 320 int type = getTransferType(); 321 int numDataElems = getNumDataElements(); 322 int pixelOffset = y*scanlineStride + x*pixelStride; 323 324 switch(type) { 325 326 case DataBuffer.TYPE_BYTE: 327 328 byte[] bdata; 329 330 if (obj == null) 331 bdata = new byte[numDataElems]; 332 else 333 bdata = (byte[])obj; 334 335 for (int i=0; i<numDataElems; i++) { 336 bdata[i] = (byte)data.getElem(bankIndices[i], 337 pixelOffset + bandOffsets[i]); 338 } 339 340 obj = (Object)bdata; 341 break; 342 343 case DataBuffer.TYPE_USHORT: 344 345 short[] usdata; 346 347 if (obj == null) 348 usdata = new short[numDataElems]; 349 else 350 usdata = (short[])obj; 351 352 for (int i=0; i<numDataElems; i++) { 353 usdata[i] = (short)data.getElem(bankIndices[i], 354 pixelOffset + bandOffsets[i]); 355 } 356 357 obj = (Object)usdata; 358 break; 359 360 case DataBuffer.TYPE_INT: 361 362 int[] idata; 363 364 if (obj == null) 365 idata = new int[numDataElems]; 366 else 367 idata = (int[])obj; 368 369 for (int i=0; i<numDataElems; i++) { 370 idata[i] = data.getElem(bankIndices[i], 371 pixelOffset + bandOffsets[i]); 372 } 373 374 obj = (Object)idata; 375 break; 376 377 case DataBuffer.TYPE_SHORT: 378 379 short[] sdata; 380 381 if (obj == null) 382 sdata = new short[numDataElems]; 383 else 384 sdata = (short[])obj; 385 386 for (int i=0; i<numDataElems; i++) { 387 sdata[i] = (short)data.getElem(bankIndices[i], 388 pixelOffset + bandOffsets[i]); 389 } 390 391 obj = (Object)sdata; 392 break; 393 394 case DataBuffer.TYPE_FLOAT: 395 396 float[] fdata; 397 398 if (obj == null) 399 fdata = new float[numDataElems]; 400 else 401 fdata = (float[])obj; 402 403 for (int i=0; i<numDataElems; i++) { 404 fdata[i] = data.getElemFloat(bankIndices[i], 405 pixelOffset + bandOffsets[i]); 406 } 407 408 obj = (Object)fdata; 409 break; 410 411 case DataBuffer.TYPE_DOUBLE: 412 413 double[] ddata; 414 415 if (obj == null) 416 ddata = new double[numDataElems]; 417 else 418 ddata = (double[])obj; 419 420 for (int i=0; i<numDataElems; i++) { 421 ddata[i] = data.getElemDouble(bankIndices[i], 422 pixelOffset + bandOffsets[i]); 423 } 424 425 obj = (Object)ddata; 426 break; 427 428 default: 429 throw new RuntimeException(JaiI18N.getString("RasterFactory3")); 430 431 } 432 433 return obj; 434 } 435 436 437 /** 438 * Returns the pixel data for the specified rectangle of pixels in a 439 * primitive array of type TransferType. 440 * For image data supported by the Java 2D API, this 441 * will be one of the dataTypes supported by java.awt.image.DataBuffer. 442 * Data may be returned in a packed format, thus increasing efficiency 443 * for data transfers. Generally, obj should be passed in as null, so 444 * that the <code>Object</code> will be created automatically and will be of the right 445 * primitive data type. 446 * <p> 447 * The following code illustrates transferring data for a rectangular 448 * region of pixels from 449 * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by 450 * <code>SampleModel</code> <code>sm1</code>, to <code>DataBuffer</code> <code>db2</code>, whose 451 * storage layout is described by <code>SampleModel</code> <code>sm2</code>. 452 * The transfer will generally be more efficient than using 453 * getPixels/setPixels. 454 * <pre> 455 * SampleModel sm1, sm2; 456 * DataBuffer db1, db2; 457 * sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, 458 * h, null, db1), db2); 459 * </pre> 460 * Using getDataElements/setDataElements to transfer between two 461 * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have 462 * the same number of bands, corresponding bands have the same number of 463 * bits per sample, and the TransferTypes are the same. 464 * <p> 465 * @param x The minimum X coordinate of the pixel rectangle. 466 * @param y The minimum Y coordinate of the pixel rectangle. 467 * @param w The width of the pixel rectangle. 468 * @param h The height of the pixel rectangle. 469 * @param obj If non-null, a primitive array in which to return 470 * the pixel data. 471 * @param data The <code>DataBuffer</code> containing the image data. 472 * @see #getNumDataElements 473 * @see #getTransferType 474 * @see java.awt.image.DataBuffer 475 * @throws <code>ClassCastException</code> if obj is non-null and is not 476 * a primitive array of type TransferType. 477 * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates 478 * are not in bounds, or if obj is non-null and is not large 479 * enough to hold the pixel data. 480 */ getDataElements(int x, int y, int w, int h, Object obj, DataBuffer data)481 public Object getDataElements(int x, int y, int w, int h, 482 Object obj, DataBuffer data) { 483 484 int type = getTransferType(); 485 int numDataElems = getNumDataElements(); 486 int cnt = 0; 487 Object o = null; 488 489 switch(type) { 490 491 case DataBuffer.TYPE_BYTE: { 492 byte[] btemp; 493 byte[] bdata; 494 495 if (obj == null) 496 bdata = new byte[numDataElems*w*h]; 497 else 498 bdata = (byte[])obj; 499 500 for (int i=y; i<y+h; i++) { 501 for (int j=x; j<x+w; j++) { 502 o = getDataElements(j, i, o, data); 503 btemp = (byte[])o; 504 for (int k=0; k<numDataElems; k++) { 505 bdata[cnt++] = btemp[k]; 506 } 507 } 508 } 509 obj = (Object)bdata; 510 break; 511 } 512 513 case DataBuffer.TYPE_USHORT: { 514 515 short[] usdata; 516 short[] ustemp; 517 518 if (obj == null) 519 usdata = new short[numDataElems*w*h]; 520 else 521 usdata = (short[])obj; 522 523 for (int i=y; i<y+h; i++) { 524 for (int j=x; j<x+w; j++) { 525 o = getDataElements(j, i, o, data); 526 ustemp = (short[])o; 527 for (int k=0; k<numDataElems; k++) { 528 usdata[cnt++] = ustemp[k]; 529 } 530 } 531 } 532 533 obj = (Object)usdata; 534 break; 535 } 536 537 case DataBuffer.TYPE_INT: { 538 539 int[] idata; 540 int[] itemp; 541 542 if (obj == null) 543 idata = new int[numDataElems*w*h]; 544 else 545 idata = (int[])obj; 546 547 for (int i=y; i<y+h; i++) { 548 for (int j=x; j<x+w; j++) { 549 o = getDataElements(j, i, o, data); 550 itemp = (int[])o; 551 for (int k=0; k<numDataElems; k++) { 552 idata[cnt++] = itemp[k]; 553 } 554 } 555 } 556 557 obj = (Object)idata; 558 break; 559 } 560 561 case DataBuffer.TYPE_SHORT: { 562 563 short[] sdata; 564 short[] stemp; 565 566 if (obj == null) 567 sdata = new short[numDataElems*w*h]; 568 else 569 sdata = (short[])obj; 570 571 for (int i=y; i<y+h; i++) { 572 for (int j=x; j<x+w; j++) { 573 o = getDataElements(j, i, o, data); 574 stemp = (short[])o; 575 for (int k=0; k<numDataElems; k++) { 576 sdata[cnt++] = stemp[k]; 577 } 578 } 579 } 580 581 obj = (Object)sdata; 582 break; 583 } 584 585 case DataBuffer.TYPE_FLOAT: { 586 587 float[] fdata; 588 float[] ftemp; 589 590 if (obj == null) 591 fdata = new float[numDataElems*w*h]; 592 else 593 fdata = (float[])obj; 594 595 for (int i=y; i<y+h; i++) { 596 for (int j=x; j<x+w; j++) { 597 o = getDataElements(j, i, o, data); 598 ftemp = (float[])o; 599 for (int k=0; k<numDataElems; k++) { 600 fdata[cnt++] = ftemp[k]; 601 } 602 } 603 } 604 605 obj = (Object)fdata; 606 break; 607 } 608 609 case DataBuffer.TYPE_DOUBLE: { 610 611 double[] ddata; 612 double[] dtemp; 613 614 if (obj == null) 615 ddata = new double[numDataElems*w*h]; 616 else 617 ddata = (double[])obj; 618 619 for (int i=y; i<y+h; i++) { 620 for (int j=x; j<x+w; j++) { 621 o = getDataElements(j, i, o, data); 622 dtemp = (double[])o; 623 for (int k=0; k<numDataElems; k++) { 624 ddata[cnt++] = dtemp[k]; 625 } 626 } 627 } 628 629 obj = (Object)ddata; 630 break; 631 } 632 633 default: 634 throw new RuntimeException(JaiI18N.getString("RasterFactory3")); 635 } 636 637 return obj; 638 } 639 640 641 642 643 644 645 /** 646 * Sets the data for a single pixel in the specified <code>DataBuffer</code> from a 647 * primitive array of type TransferType. For a <code>ComponentSampleModel</code>, 648 * this will be the same as the data type, and samples are transferred 649 * one per array element. 650 * <p> 651 * The following code illustrates transferring data for one pixel from 652 * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by 653 * <code>ComponentSampleModel</code> <code>csm1</code>, to <code>DataBuffer</code> <code>db2</code>, 654 * whose storage layout is described by 655 * <code>ComponentSampleModel</code> <code>csm2</code>. 656 * The transfer will generally be more efficient than using 657 * getPixel/setPixel. 658 * <pre> 659 * ComponentSampleModel csm1, csm2; 660 * DataBufferInt db1, db2; 661 * csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1), 662 * db2); 663 * </pre> 664 * Using getDataElements/setDataElements to transfer between two 665 * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have 666 * the same number of bands, corresponding bands have the same number of 667 * bits per sample, and the TransferTypes are the same. 668 * <p> 669 * @param x The X coordinate of the pixel location. 670 * @param y The Y coordinate of the pixel location. 671 * @param obj A primitive array containing pixel data. 672 * @param data The <code>DataBuffer</code> containing the image data. 673 * @throws <code>ClassCastException</code> if obj is non-null and is not 674 * a primitive array of type TransferType. 675 * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates 676 * are not in bounds, or if obj is non-null and is not large 677 * enough to hold the pixel data. 678 */ setDataElements(int x, int y, Object obj, DataBuffer data)679 public void setDataElements(int x, int y, Object obj, DataBuffer data) { 680 681 int type = getTransferType(); 682 int numDataElems = getNumDataElements(); 683 int pixelOffset = y*scanlineStride + x*pixelStride; 684 685 switch(type) { 686 687 case DataBuffer.TYPE_BYTE: 688 689 byte[] barray = (byte[])obj; 690 691 for (int i=0; i<numDataElems; i++) { 692 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i], 693 ((int)barray[i])&0xff); 694 } 695 break; 696 697 case DataBuffer.TYPE_USHORT: 698 699 short[] usarray = (short[])obj; 700 701 for (int i=0; i<numDataElems; i++) { 702 data.setElem(bankIndices[i], pixelOffset + bandOffsets[i], 703 ((int)usarray[i])&0xffff); 704 } 705 break; 706 707 case DataBuffer.TYPE_INT: 708 709 int[] iarray = (int[])obj; 710 711 for (int i=0; i<numDataElems; i++) { 712 data.setElem(bankIndices[i], 713 pixelOffset + bandOffsets[i], iarray[i]); 714 } 715 break; 716 717 case DataBuffer.TYPE_SHORT: 718 719 short[] sarray = (short[])obj; 720 721 for (int i=0; i<numDataElems; i++) { 722 data.setElem(bankIndices[i], 723 pixelOffset + bandOffsets[i], sarray[i]); 724 } 725 break; 726 727 case DataBuffer.TYPE_FLOAT: 728 729 float[] farray = (float[])obj; 730 731 for (int i=0; i<numDataElems; i++) { 732 data.setElemFloat(bankIndices[i], 733 pixelOffset + bandOffsets[i], farray[i]); 734 } 735 break; 736 737 case DataBuffer.TYPE_DOUBLE: 738 739 double[] darray = (double[])obj; 740 741 for (int i=0; i<numDataElems; i++) { 742 data.setElemDouble(bankIndices[i], 743 pixelOffset + bandOffsets[i], darray[i]); 744 } 745 break; 746 747 default: 748 throw new RuntimeException(JaiI18N.getString("RasterFactory3")); 749 } 750 } 751 752 /** 753 * Sets the data for a rectangle of pixels in the specified <code>DataBuffer</code> 754 * from a primitive array of type TransferType. For image data supported 755 * by the Java 2D API, this will be one of the dataTypes supported by 756 * java.awt.image.DataBuffer. Data in the array may be in a packed 757 * format, thus increasing efficiency for data transfers. 758 * <p> 759 * The following code illustrates transferring data for a rectangular 760 * region of pixels from 761 * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by 762 * <code>SampleModel</code> <code>sm1</code>, to <code>DataBuffer</code> <code>db2</code>, whose 763 * storage layout is described by <code>SampleModel</code> <code>sm2</code>. 764 * The transfer will generally be more efficient than using 765 * getPixels/setPixels. 766 * <pre> 767 * SampleModel sm1, sm2; 768 * DataBuffer db1, db2; 769 * sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h, 770 * null, db1), db2); 771 * </pre> 772 * Using getDataElements/setDataElements to transfer between two 773 * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have 774 * the same number of bands, corresponding bands have the same number of 775 * bits per sample, and the TransferTypes are the same. 776 * <p> 777 * @param x The minimum X coordinate of the pixel rectangle. 778 * @param y The minimum Y coordinate of the pixel rectangle. 779 * @param w The width of the pixel rectangle. 780 * @param h The height of the pixel rectangle. 781 * @param obj A primitive array containing pixel data. 782 * @param data The <code>DataBuffer</code> containing the image data. 783 * @throws <code>ClassCastException</code> if obj is non-null and is not 784 * a primitive array of type TransferType. 785 * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates 786 * are not in bounds, or if obj is non-null and is not large 787 * enough to hold the pixel data. 788 * @see #getNumDataElements 789 * @see #getTransferType 790 * @see java.awt.image.DataBuffer 791 */ setDataElements(int x, int y, int w, int h, Object obj, DataBuffer data)792 public void setDataElements(int x, int y, int w, int h, 793 Object obj, DataBuffer data) { 794 int cnt = 0; 795 Object o = null; 796 int type = getTransferType(); 797 int numDataElems = getNumDataElements(); 798 799 switch(type) { 800 801 case DataBuffer.TYPE_BYTE: { 802 803 byte[] barray = (byte[])obj; 804 byte[] btemp = new byte[numDataElems]; 805 806 for (int i=y; i<y+h; i++) { 807 for (int j=x; j<x+w; j++) { 808 for (int k=0; k<numDataElems; k++) { 809 btemp[k] = barray[cnt++]; 810 } 811 812 setDataElements(j, i, btemp, data); 813 } 814 } 815 break; 816 } 817 818 case DataBuffer.TYPE_USHORT: { 819 820 short[] usarray = (short[])obj; 821 short[] ustemp = new short[numDataElems]; 822 823 for (int i=y; i<y+h; i++) { 824 for (int j=x; j<x+w; j++) { 825 for (int k=0; k<numDataElems; k++) { 826 ustemp[k] = usarray[cnt++]; 827 } 828 setDataElements(j, i, ustemp, data); 829 } 830 } 831 break; 832 } 833 834 case DataBuffer.TYPE_INT: { 835 836 int[] iArray = (int[])obj; 837 int[] itemp = new int[numDataElems]; 838 839 for (int i=y; i<y+h; i++) { 840 for (int j=x; j<x+w; j++) { 841 for (int k=0; k<numDataElems; k++) { 842 itemp[k] = iArray[cnt++]; 843 } 844 845 setDataElements(j, i, itemp, data); 846 } 847 } 848 break; 849 } 850 851 case DataBuffer.TYPE_SHORT: { 852 853 short[] sArray = (short[])obj; 854 short[] stemp = new short[numDataElems]; 855 856 for (int i=y; i<y+h; i++) { 857 for (int j=x; j<x+w; j++) { 858 for (int k=0; k<numDataElems; k++) { 859 stemp[k] = sArray[cnt++]; 860 } 861 862 setDataElements(j, i, stemp, data); 863 } 864 } 865 break; 866 } 867 868 case DataBuffer.TYPE_FLOAT: { 869 870 float[] fArray = (float[])obj; 871 float[] ftemp = new float[numDataElems]; 872 873 for (int i=y; i<y+h; i++) { 874 for (int j=x; j<x+w; j++) { 875 for (int k=0; k<numDataElems; k++) { 876 ftemp[k] = fArray[cnt++]; 877 } 878 879 setDataElements(j, i, ftemp, data); 880 } 881 } 882 break; 883 } 884 885 case DataBuffer.TYPE_DOUBLE: { 886 887 double[] dArray = (double[])obj; 888 double[] dtemp = new double[numDataElems]; 889 890 for (int i=y; i<y+h; i++) { 891 for (int j=x; j<x+w; j++) { 892 for (int k=0; k<numDataElems; k++) { 893 dtemp[k] = dArray[cnt++]; 894 } 895 896 setDataElements(j, i, dtemp, data); 897 } 898 } 899 break; 900 } 901 902 default: 903 throw new RuntimeException(JaiI18N.getString("RasterFactory3")); 904 } 905 } 906 907 /** 908 * Sets a sample in the specified band for the pixel located at (x,y) 909 * in the <code>DataBuffer</code> using a <code>float</code> for input. 910 * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are 911 * not in bounds. 912 * @param x The X coordinate of the pixel location. 913 * @param y The Y coordinate of the pixel location. 914 * @param b The band to set. 915 * @param s The input sample as a <code>float</code>. 916 * @param data The <code>DataBuffer</code> containing the image data. 917 * 918 * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds 919 */ setSample(int x, int y, int b, float s, DataBuffer data)920 public void setSample(int x, int y, int b, 921 float s, 922 DataBuffer data) { 923 data.setElemFloat(bankIndices[b], 924 y*scanlineStride + x*pixelStride + bandOffsets[b], 925 s); 926 } 927 928 /** 929 * Returns the sample in a specified band 930 * for the pixel located at (x,y) as a <code>float</code>. 931 * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are 932 * not in bounds. 933 * @param x The X coordinate of the pixel location. 934 * @param y The Y coordinate of the pixel location. 935 * @param b The band to return. 936 * @param data The <code>DataBuffer</code> containing the image data. 937 * @return sample The floating point sample value 938 * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds 939 */ getSampleFloat(int x, int y, int b, DataBuffer data)940 public float getSampleFloat(int x, int y, int b, 941 DataBuffer data) { 942 float sample = 943 data.getElemFloat(bankIndices[b], 944 y*scanlineStride + x*pixelStride + 945 bandOffsets[b]); 946 return sample; 947 } 948 949 /** 950 * Sets a sample in the specified band for the pixel located at (x,y) 951 * in the <code>DataBuffer</code> using a <code>double</code> for input. 952 * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are 953 * not in bounds. 954 * @param x The X coordinate of the pixel location. 955 * @param y The Y coordinate of the pixel location. 956 * @param b The band to set. 957 * @param s The input sample as a <code>double</code>. 958 * @param data The <code>DataBuffer</code> containing the image data. 959 * 960 * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds 961 */ setSample(int x, int y, int b, double s, DataBuffer data)962 public void setSample(int x, int y, int b, 963 double s, 964 DataBuffer data) { 965 data.setElemDouble(bankIndices[b], 966 y*scanlineStride + x*pixelStride + bandOffsets[b], 967 s); 968 } 969 970 /** 971 * Returns the sample in a specified band 972 * for a pixel located at (x,y) as a <code>double</code>. 973 * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are 974 * not in bounds. 975 * @param x The X coordinate of the pixel location. 976 * @param y The Y coordinate of the pixel location. 977 * @param b The band to return. 978 * @param data The <code>DataBuffer</code> containing the image data. 979 * @return sample The <code>double</code> sample value 980 * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds 981 */ getSampleDouble(int x, int y, int b, DataBuffer data)982 public double getSampleDouble(int x, int y, int b, 983 DataBuffer data) { 984 double sample = 985 data.getElemDouble(bankIndices[b], 986 y*scanlineStride + x*pixelStride + 987 bandOffsets[b]); 988 return sample; 989 } 990 991 /** 992 * Returns all samples for a rectangle of pixels in a <code>double</code> 993 * array, one sample per array element. 994 * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are 995 * not in bounds. 996 * @param x The X coordinate of the upper left pixel location. 997 * @param y The Y coordinate of the upper left pixel location. 998 * @param w The width of the pixel rectangle. 999 * @param h The height of the pixel rectangle. 1000 * @param dArray If non-null, returns the samples in this array. 1001 * @param data The <code>DataBuffer</code> containing the image data. 1002 * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds 1003 */ getPixels(int x, int y, int w, int h, double dArray[], DataBuffer data)1004 public double[] getPixels(int x, int y, int w, int h, 1005 double dArray[], DataBuffer data) { 1006 double pixels[]; 1007 int Offset = 0; 1008 1009 if (dArray != null) 1010 pixels = dArray; 1011 else 1012 pixels = new double[numBands * w * h]; 1013 1014 for (int i=y; i<(h+y); i++) { 1015 for (int j=x; j<(w+x); j++) { 1016 for (int k=0; k<numBands; k++) { 1017 pixels[Offset++] = getSampleDouble(j, i, k, data); 1018 } 1019 } 1020 } 1021 1022 return pixels; 1023 } 1024 1025 /** Returns a <code>String</code> containing the values of all valid fields. */ toString()1026 public String toString() { 1027 String ret = "ComponentSampleModelJAI: " + 1028 " dataType=" + this.getDataType() + 1029 " numBands=" + this.getNumBands() + 1030 " width=" +this.getWidth() + 1031 " height=" +this.getHeight() + 1032 " bandOffsets=[ "; 1033 for (int i = 0; i < numBands; i++) { 1034 ret += this.getBandOffsets()[i] + " "; 1035 } 1036 ret += "]"; 1037 return ret; 1038 } 1039 } 1040 1041