001/* 002 * $RCSfile: RawRenderedImage.java,v $ 003 * 004 * 005 * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without 008 * modification, are permitted provided that the following conditions 009 * are met: 010 * 011 * - Redistribution of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * 014 * - Redistribution in binary form must reproduce the above copyright 015 * notice, this list of conditions and the following disclaimer in 016 * the documentation and/or other materials provided with the 017 * distribution. 018 * 019 * Neither the name of Sun Microsystems, Inc. or the names of 020 * contributors may be used to endorse or promote products derived 021 * from this software without specific prior written permission. 022 * 023 * This software is provided "AS IS," without a warranty of any 024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR 034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE 035 * POSSIBILITY OF SUCH DAMAGES. 036 * 037 * You acknowledge that this software is not designed or intended for 038 * use in the design, construction, operation or maintenance of any 039 * nuclear facility. 040 * 041 * $Revision: 1.2 $ 042 * $Date: 2006/04/21 23:19:13 $ 043 * $State: Exp $ 044 */ 045package com.github.jaiimageio.impl.plugins.raw; 046 047import javax.imageio.stream.ImageInputStream; 048 049import java.awt.Dimension; 050import java.awt.Point; 051import java.awt.Rectangle; 052import java.awt.Transparency; 053import java.awt.color.ColorSpace; 054import java.awt.image.BufferedImage; 055import java.awt.image.BandedSampleModel; 056import java.awt.image.ColorModel; 057import java.awt.image.ComponentColorModel; 058import java.awt.image.ComponentSampleModel; 059import java.awt.image.DataBuffer; 060import java.awt.image.DataBufferByte; 061import java.awt.image.DataBufferDouble; 062import java.awt.image.DataBufferFloat; 063import java.awt.image.DataBufferInt; 064import java.awt.image.DataBufferShort; 065import java.awt.image.DataBufferUShort; 066import java.awt.image.DirectColorModel; 067import java.awt.image.IndexColorModel; 068import java.awt.image.MultiPixelPackedSampleModel; 069import java.awt.image.PixelInterleavedSampleModel; 070import java.awt.image.SinglePixelPackedSampleModel; 071import java.awt.image.Raster; 072import java.awt.image.RenderedImage; 073import java.awt.image.SampleModel; 074import java.awt.image.WritableRaster; 075import java.lang.reflect.Constructor; 076import java.lang.reflect.Method; 077import java.lang.reflect.InvocationTargetException; 078import java.io.*; 079 080import javax.imageio.ImageReadParam; 081import javax.imageio.ImageTypeSpecifier; 082 083import com.github.jaiimageio.impl.common.ImageUtil; 084import com.github.jaiimageio.impl.common.SimpleRenderedImage; 085import com.github.jaiimageio.stream.RawImageInputStream; 086 087public class RawRenderedImage extends SimpleRenderedImage { 088 /** The sample model for the original image. */ 089 private SampleModel originalSampleModel; 090 091 private Raster currentTile; 092 private Point currentTileGrid; 093 094 /** The input stream we read from */ 095 private RawImageInputStream iis = null; 096 097 /** Caches the <code>RawImageReader</code> which creates this object. This 098 * variable is used to monitor the abortion. 099 */ 100 private RawImageReader reader; 101 102 /** The <code>ImageReadParam</code> to create this 103 * <code>renderedImage</code>. 104 */ 105 private ImageReadParam param = null; 106 107 // The image index in the stream 108 private int imageIndex; 109 110 /** The destination bounds. */ 111 private Rectangle destinationRegion; 112 private Rectangle originalRegion; 113 private Point sourceOrigin; 114 private Dimension originalDimension; 115 private int maxXTile, maxYTile; 116 117 /** The subsampling parameters. */ 118 private int scaleX, scaleY, xOffset, yOffset; 119 private int[] destinationBands = null; 120 private int[] sourceBands = null; 121 private int nComp; 122 123 /** Coordinate transform is not needed from the source (image stream) 124 * to the destination. 125 */ 126 private boolean noTransform = true; 127 128 /** The raster for medialib tiles to share. */ 129 private WritableRaster rasForATile; 130 131 private BufferedImage destImage; 132 133 /** The position of the first sample of this image in the stream. */ 134 private long position; 135 136 /** cache the size of the data for each tile in the stream. */ 137 private long tileDataSize; 138 139 /** The orginal number tiles in X direction. */ 140 private int originalNumXTiles; 141 142 public RawRenderedImage(RawImageInputStream iis, 143 RawImageReader reader, 144 ImageReadParam param, 145 int imageIndex) throws IOException { 146 this.iis = iis; 147 this.reader = reader; 148 this.param = param; 149 this.imageIndex = imageIndex; 150 this.position = iis.getImageOffset(imageIndex); 151 this.originalDimension = iis.getImageDimension(imageIndex); 152 153 ImageTypeSpecifier type = iis.getImageType(); 154 sampleModel = originalSampleModel = type.getSampleModel(); 155 colorModel = type.getColorModel(); 156 157 // If the destination band is set used it 158 sourceBands = (param == null) ? null : param.getSourceBands(); 159 160 if (sourceBands == null) { 161 nComp = originalSampleModel.getNumBands(); 162 sourceBands = new int[nComp]; 163 for (int i = 0; i < nComp; i++) 164 sourceBands[i] = i; 165 } else { 166 sampleModel = 167 originalSampleModel.createSubsetSampleModel(sourceBands); 168 colorModel = ImageUtil.createColorModel(null, sampleModel); 169 } 170 171 nComp = sourceBands.length; 172 173 destinationBands = (param == null) ? null : param.getDestinationBands(); 174 if (destinationBands == null) { 175 destinationBands = new int[nComp]; 176 for (int i = 0; i < nComp; i++) 177 destinationBands[i] = i; 178 } 179 180 Dimension dim = iis.getImageDimension(imageIndex); 181 this.width = dim.width; 182 this.height = dim.height; 183 184 Rectangle sourceRegion = 185 new Rectangle(0, 0, this.width, this.height); 186 187 originalRegion = (Rectangle)sourceRegion.clone(); 188 189 destinationRegion = (Rectangle)sourceRegion.clone(); 190 191 if (param != null) { 192 RawImageReader.computeRegionsWrapper(param, 193 this.width, this.height, 194 param.getDestination(), 195 sourceRegion, 196 destinationRegion); 197 scaleX = param.getSourceXSubsampling(); 198 scaleY = param.getSourceYSubsampling(); 199 xOffset = param.getSubsamplingXOffset(); 200 yOffset = param.getSubsamplingYOffset(); 201 } 202 203 sourceOrigin = new Point(sourceRegion.x, sourceRegion.y); 204 if (!destinationRegion.equals(sourceRegion)) 205 noTransform = false; 206 207 this.tileDataSize = ImageUtil.getTileSize(originalSampleModel); 208 209 this.tileWidth = originalSampleModel.getWidth(); 210 this.tileHeight = originalSampleModel.getHeight(); 211 this.tileGridXOffset = destinationRegion.x; 212 this.tileGridYOffset = destinationRegion.y; 213 this.originalNumXTiles = getNumXTiles(); 214 215 this.width = destinationRegion.width; 216 this.height = destinationRegion.height; 217 this.minX = destinationRegion.x; 218 this.minY = destinationRegion.y; 219 220 sampleModel = 221 sampleModel.createCompatibleSampleModel(tileWidth, tileHeight); 222 223 maxXTile = originalDimension.width / tileWidth; 224 maxYTile = originalDimension.height / tileHeight; 225 } 226 227 public synchronized Raster getTile(int tileX, int tileY) { 228 if (currentTile != null && 229 currentTileGrid.x == tileX && 230 currentTileGrid.y == tileY) 231 return currentTile; 232 233 if (tileX >= getNumXTiles() || tileY >= getNumYTiles()) 234 throw new IllegalArgumentException(I18N.getString("RawRenderedImage0")); 235 236 try { 237 iis.seek(position + (tileY * originalNumXTiles + tileX) * tileDataSize); 238 239 int x = tileXToX(tileX); 240 int y = tileYToY(tileY); 241 currentTile = Raster.createWritableRaster(sampleModel, new Point(x, y)); 242 243 if (noTransform) { 244 switch (sampleModel.getDataType()) { 245 case DataBuffer.TYPE_BYTE: 246 byte[][] buf = 247 ((DataBufferByte)currentTile.getDataBuffer()).getBankData(); 248 for (int i = 0; i < buf.length; i++) 249 iis.readFully(buf[i], 0, buf[i].length); 250 break; 251 252 case DataBuffer.TYPE_SHORT: 253 short[][] sbuf = 254 ((DataBufferShort)currentTile.getDataBuffer()).getBankData(); 255 for (int i = 0; i < sbuf.length; i++) 256 iis.readFully(sbuf[i], 0, sbuf[i].length); 257 break; 258 259 case DataBuffer.TYPE_USHORT: 260 short[][] usbuf = 261 ((DataBufferUShort)currentTile.getDataBuffer()).getBankData(); 262 for (int i = 0; i < usbuf.length; i++) 263 iis.readFully(usbuf[i], 0, usbuf[i].length); 264 break; 265 case DataBuffer.TYPE_INT: 266 int[][] ibuf = 267 ((DataBufferInt)currentTile.getDataBuffer()).getBankData(); 268 for (int i = 0; i < ibuf.length; i++) 269 iis.readFully(ibuf[i], 0, ibuf[i].length); 270 break; 271 case DataBuffer.TYPE_FLOAT: 272 float[][] fbuf = 273 ((DataBufferFloat)currentTile.getDataBuffer()).getBankData(); 274 for (int i = 0; i < fbuf.length; i++) 275 iis.readFully(fbuf[i], 0, fbuf[i].length); 276 break; 277 case DataBuffer.TYPE_DOUBLE: 278 double[][] dbuf = 279 ((DataBufferDouble)currentTile.getDataBuffer()).getBankData(); 280 for (int i = 0; i < dbuf.length; i++) 281 iis.readFully(dbuf[i], 0, dbuf[i].length); 282 break; 283 } 284 } else { 285 currentTile = readSubsampledRaster((WritableRaster)currentTile); 286 } 287 } catch (IOException e) { 288 throw new RuntimeException(e); 289 } 290 291 if (currentTileGrid == null) 292 currentTileGrid = new Point(tileX, tileY); 293 else { 294 currentTileGrid.x = tileX; 295 currentTileGrid.y = tileY; 296 } 297 298 return currentTile; 299 } 300 301 public void readAsRaster(WritableRaster raster) throws java.io.IOException { 302 readSubsampledRaster(raster); 303 } 304 305 private Raster readSubsampledRaster(WritableRaster raster) throws IOException { 306 if (raster == null) 307 raster = Raster.createWritableRaster( 308 sampleModel.createCompatibleSampleModel(destinationRegion.x + 309 destinationRegion.width, 310 destinationRegion.y + 311 destinationRegion.height), 312 new Point(destinationRegion.x, destinationRegion.y)); 313 314 int numBands = sourceBands.length; 315 int dataType = sampleModel.getDataType(); 316 int sampleSizeBit = DataBuffer.getDataTypeSize(dataType); 317 int sampleSizeByte = (sampleSizeBit + 7) / 8; 318 319 Rectangle destRect = raster.getBounds().intersection(destinationRegion); 320 321 int offx = destinationRegion.x; 322 int offy = destinationRegion.y; 323 324 int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x; 325 int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y; 326 int sourceEX = (destRect.width - 1) * scaleX + sourceSX; 327 int sourceEY = (destRect.height - 1) * scaleY + sourceSY; 328 int startXTile = sourceSX / tileWidth; 329 int startYTile = sourceSY / tileHeight; 330 int endXTile = sourceEX / tileWidth; 331 int endYTile = sourceEY / tileHeight; 332 333 startXTile = clip(startXTile, 0, maxXTile); 334 startYTile = clip(startYTile, 0, maxYTile); 335 endXTile = clip(endXTile, 0, maxXTile); 336 endYTile = clip(endYTile, 0, maxYTile); 337 338 int totalXTiles = getNumXTiles(); 339 int totalYTiles = getNumYTiles(); 340 int totalTiles = totalXTiles * totalYTiles; 341 342 //The line buffer for the source 343 byte[] pixbuf = null; // byte buffer for the decoded pixels. 344 short[] spixbuf = null; // byte buffer for the decoded pixels. 345 int[] ipixbuf = null; // byte buffer for the decoded pixels. 346 float[] fpixbuf = null; // byte buffer for the decoded pixels. 347 double[] dpixbuf = null; // byte buffer for the decoded pixels. 348 349 // A flag to show the ComponentSampleModel has a single data bank 350 boolean singleBank = true; 351 int pixelStride = 0; 352 int scanlineStride = 0; 353 int bandStride = 0; 354 int[] bandOffsets = null; 355 int[] bankIndices = null; 356 357 if (originalSampleModel instanceof ComponentSampleModel) { 358 ComponentSampleModel csm = (ComponentSampleModel)originalSampleModel; 359 bankIndices = csm.getBankIndices(); 360 int maxBank = 0; 361 for (int i = 0; i < bankIndices.length; i++) 362 if (maxBank > bankIndices[i]) 363 maxBank = bankIndices[i]; 364 365 if (maxBank > 0) 366 singleBank = false; 367 pixelStride = csm.getPixelStride(); 368 369 scanlineStride = csm.getScanlineStride(); 370 bandOffsets = csm.getBandOffsets(); 371 for (int i = 0; i < bandOffsets.length; i++) 372 if (bandStride < bandOffsets[i]) 373 bandStride = bandOffsets[i]; 374 } else if (originalSampleModel instanceof MultiPixelPackedSampleModel) { 375 scanlineStride = 376 ((MultiPixelPackedSampleModel)originalSampleModel).getScanlineStride(); 377 } else if(originalSampleModel instanceof SinglePixelPackedSampleModel) { 378 pixelStride = 1; 379 scanlineStride = 380 ((SinglePixelPackedSampleModel)originalSampleModel).getScanlineStride(); 381 } 382 383 // The dstination buffer for the raster 384 byte[] destPixbuf = null; // byte buffer for the decoded pixels. 385 short[] destSPixbuf = null; // byte buffer for the decoded pixels. 386 int[] destIPixbuf = null; // byte buffer for the decoded pixels. 387 float[] destFPixbuf = null; // byte buffer for the decoded pixels. 388 double[] destDPixbuf = null; // byte buffer for the decoded pixels. 389 int[] destBandOffsets = null; 390 int destPixelStride = 0; 391 int destScanlineStride = 0; 392 int destSX = 0; // The first pixel for the destionation 393 394 if (raster.getSampleModel() instanceof ComponentSampleModel) { 395 ComponentSampleModel csm = 396 (ComponentSampleModel)raster.getSampleModel(); 397 bankIndices = csm.getBankIndices(); 398 destBandOffsets = csm.getBandOffsets(); 399 destPixelStride = csm.getPixelStride(); 400 destScanlineStride = csm.getScanlineStride(); 401 destSX = csm.getOffset(raster.getMinX() - 402 raster.getSampleModelTranslateX(), 403 raster.getMinY() - 404 raster.getSampleModelTranslateY()) 405 - destBandOffsets[0]; 406 407 switch(dataType) { 408 case DataBuffer.TYPE_BYTE: 409 destPixbuf = ((DataBufferByte)raster.getDataBuffer()).getData(); 410 break; 411 case DataBuffer.TYPE_SHORT: 412 destSPixbuf = 413 ((DataBufferShort)raster.getDataBuffer()).getData(); 414 break; 415 416 case DataBuffer.TYPE_USHORT: 417 destSPixbuf = 418 ((DataBufferUShort)raster.getDataBuffer()).getData(); 419 break; 420 421 case DataBuffer.TYPE_INT: 422 destIPixbuf = 423 ((DataBufferInt)raster.getDataBuffer()).getData(); 424 break; 425 426 case DataBuffer.TYPE_FLOAT: 427 destFPixbuf = 428 ((DataBufferFloat)raster.getDataBuffer()).getData(); 429 break; 430 431 case DataBuffer.TYPE_DOUBLE: 432 destDPixbuf = 433 ((DataBufferDouble)raster.getDataBuffer()).getData(); 434 break; 435 } 436 } else if (raster.getSampleModel() instanceof SinglePixelPackedSampleModel) { 437 numBands = 1; 438 bankIndices = new int[]{0}; 439 destBandOffsets = new int[numBands]; 440 for (int i = 0; i < numBands; i++) 441 destBandOffsets[i] = 0; 442 destPixelStride = 1; 443 destScanlineStride = 444 ((SinglePixelPackedSampleModel)raster.getSampleModel()).getScanlineStride(); 445 } 446 447 // Start the data delivery to the cached consumers tile by tile 448 for(int y = startYTile; y <= endYTile; y++){ 449 if (reader.getAbortRequest()) 450 break; 451 452 // Loop on horizontal tiles 453 for(int x=startXTile; x <= endXTile; x++){ 454 if (reader.getAbortRequest()) 455 break; 456 457 long tilePosition = 458 position + (y * originalNumXTiles + x) * tileDataSize; 459 iis.seek(tilePosition); 460 float percentage = 461 (x - startXTile + y * totalXTiles) / totalXTiles; 462 463 int startX = x * tileWidth; 464 int startY = y * tileHeight; 465 466 int cTileHeight = tileHeight; 467 int cTileWidth = tileWidth; 468 469 if (startY + cTileHeight >= originalDimension.height) 470 cTileHeight = originalDimension.height - startY; 471 472 if (startX + cTileWidth >= originalDimension.width) 473 cTileWidth = originalDimension.width - startX; 474 475 int tx = startX; 476 int ty = startY; 477 478 // If source start position calculated by taking subsampling 479 // into account is after the tile's start X position, adjust 480 // the start position accordingly 481 if (sourceSX > startX) { 482 cTileWidth += startX - sourceSX; 483 tx = sourceSX; 484 startX = sourceSX; 485 } 486 487 if (sourceSY > startY) { 488 cTileHeight += startY - sourceSY; 489 ty = sourceSY; 490 startY = sourceSY; 491 } 492 493 // If source end position calculated by taking subsampling 494 // into account is prior to the tile's end X position, adjust 495 // the tile width to read accordingly 496 if (sourceEX < startX + cTileWidth -1) { 497 cTileWidth += sourceEX - startX - cTileWidth + 1; 498 } 499 500 if (sourceEY < startY + cTileHeight - 1) { 501 cTileHeight += sourceEY - startY - cTileHeight + 1; 502 } 503 504 // The start X in the destination 505 int x1 = (startX + scaleX - 1 - sourceOrigin.x) / scaleX; 506 int x2 = (startX + scaleX - 1 + cTileWidth - sourceOrigin.x) / 507 scaleX; 508 int lineLength = x2 - x1; 509 x2 = (x2 - 1) * scaleX + sourceOrigin.x; 510 511 int y1 = (startY + scaleY -1 - sourceOrigin.y) /scaleY; 512 startX = x1 * scaleX + sourceOrigin.x; 513 startY = y1 * scaleY + sourceOrigin.y; 514 515 // offx is destination.x 516 x1 += offx; 517 y1 += offy; 518 519 tx -= x * tileWidth; 520 ty -= y * tileHeight; 521 522 if (sampleModel instanceof MultiPixelPackedSampleModel) { 523 MultiPixelPackedSampleModel mppsm = 524 (MultiPixelPackedSampleModel)originalSampleModel; 525 526 iis.skipBytes(mppsm.getOffset(tx, ty) * sampleSizeByte); 527 528 int readBytes = (mppsm.getOffset(x2, 0) - 529 mppsm.getOffset(startX, 0) + 1) * 530 sampleSizeByte; 531 532 int skipLength = (scanlineStride * scaleY - readBytes) * 533 sampleSizeByte; 534 readBytes *= sampleSizeByte; 535 536 if (pixbuf == null || pixbuf.length < readBytes) 537 pixbuf = new byte[readBytes]; 538 539 int bitoff = mppsm.getBitOffset(tx); 540 541 for (int l = 0, m = y1; l < cTileHeight; 542 l += scaleY, m++) { 543 if (reader.getAbortRequest()) 544 break; 545 iis.readFully(pixbuf, 0, readBytes); 546 if (scaleX == 1) { 547 548 if (bitoff != 0) { 549 int mask1 = (255 << bitoff) & 255; 550 int mask2 = ~mask1 & 255; 551 int shift = 8 - bitoff; 552 553 int n = 0; 554 for (; n < readBytes -1; n++) 555 pixbuf[n] = (byte)(((pixbuf[n] & mask2) << shift) | 556 (pixbuf[n + 1] & mask1) >>bitoff); 557 pixbuf[n] = (byte)((pixbuf[n] & mask2) << shift); 558 } 559 } else { 560 561 int bit = 7 ; 562 int pos = 0 ; 563 int mask = 128; 564 565 for (int n = 0, n1 = startX & 7; 566 n < lineLength; n++, n1 += scaleX) { 567 pixbuf[pos] = (byte)((pixbuf[pos] & ~(1 << bit)) | 568 (((pixbuf[n1 >> 3] >> (7 - (n1 & 7))) & 1) << bit)); 569 bit--; 570 if (bit == -1) { 571 bit = 7; 572 pos++; 573 } 574 } 575 } 576 577 ImageUtil.setPackedBinaryData(pixbuf, raster, 578 new Rectangle(x1, m, 579 lineLength, 580 1)); 581 iis.skipBytes(skipLength); 582 if (destImage != null) 583 reader.processImageUpdateWrapper(destImage, x1, m, 584 cTileWidth, 1, 1, 1, 585 destinationBands); 586 587 reader.processImageProgressWrapper(percentage + 588 (l - startY + 1.0F) / 589 cTileHeight / totalTiles); 590 } 591 } else { 592 593 int readLength, skipLength; 594 if (pixelStride < scanlineStride) { 595 readLength = cTileWidth * pixelStride; 596 skipLength = (scanlineStride * scaleY - readLength) * 597 sampleSizeByte; 598 } else { 599 readLength = cTileHeight * scanlineStride; 600 skipLength = (pixelStride * scaleX - readLength) * 601 sampleSizeByte; 602 } 603 604 //Allocate buffer for all the types 605 switch (sampleModel.getDataType()) { 606 case DataBuffer.TYPE_BYTE: 607 if (pixbuf == null || pixbuf.length < readLength) 608 pixbuf = new byte[readLength]; 609 break; 610 611 case DataBuffer.TYPE_SHORT: 612 case DataBuffer.TYPE_USHORT: 613 if (spixbuf == null || spixbuf.length < readLength) 614 spixbuf = new short[readLength]; 615 break; 616 617 case DataBuffer.TYPE_INT: 618 if (ipixbuf == null || ipixbuf.length < readLength) 619 ipixbuf = new int[readLength]; 620 break; 621 622 case DataBuffer.TYPE_FLOAT: 623 if (fpixbuf == null || fpixbuf.length < readLength) 624 fpixbuf = new float[readLength]; 625 break; 626 627 case DataBuffer.TYPE_DOUBLE: 628 if (dpixbuf == null || dpixbuf.length < readLength) 629 dpixbuf = new double[readLength]; 630 break; 631 } 632 633 if (sampleModel instanceof PixelInterleavedSampleModel) { 634 iis.skipBytes((tx * pixelStride + ty * scanlineStride) * 635 sampleSizeByte); 636 637 // variables for ther loop 638 int outerFirst, outerSecond, outerStep, outerBound; 639 int innerStep, innerStep1, outerStep1; 640 if (pixelStride < scanlineStride) { 641 outerFirst = 0; 642 outerSecond = y1; 643 outerStep = scaleY; 644 outerBound = cTileHeight; 645 innerStep = scaleX * pixelStride; 646 innerStep1 = destPixelStride; 647 outerStep1 = destScanlineStride; 648 } else { 649 outerFirst = 0; 650 outerSecond = x1; 651 outerStep = scaleX; 652 outerBound = cTileWidth; 653 innerStep = scaleY * scanlineStride; 654 innerStep1 = destScanlineStride; 655 outerStep1 = destPixelStride; 656 } 657 658 int destPos = 659 destSX + (y1 - raster.getSampleModelTranslateY()) 660 * destScanlineStride + 661 (x1 - raster.getSampleModelTranslateX()) 662 * destPixelStride; 663 664 for (int l = outerFirst, m = outerSecond; l < outerBound; 665 l += outerStep, m++) { 666 if (reader.getAbortRequest()) 667 break; 668 669 switch(dataType) { 670 case DataBuffer.TYPE_BYTE: 671 if (innerStep == numBands && 672 innerStep1 == numBands) 673 iis.readFully(destPixbuf, destPos, readLength); 674 else 675 iis.readFully(pixbuf, 0, readLength); 676 break; 677 case DataBuffer.TYPE_SHORT: 678 case DataBuffer.TYPE_USHORT: 679 if (innerStep == numBands && 680 innerStep1 == numBands) { 681 iis.readFully(destSPixbuf, destPos, readLength); 682 } else 683 iis.readFully(spixbuf, 0, readLength); 684 break; 685 case DataBuffer.TYPE_INT: 686 if (innerStep == numBands && 687 innerStep1 == numBands) 688 iis.readFully(destIPixbuf, destPos, readLength); 689 else 690 iis.readFully(ipixbuf, 0, readLength); 691 break; 692 case DataBuffer.TYPE_FLOAT: 693 if (innerStep == numBands && 694 innerStep1 == numBands) 695 iis.readFully(destFPixbuf, destPos, readLength); 696 else 697 iis.readFully(fpixbuf, 0, readLength); 698 break; 699 case DataBuffer.TYPE_DOUBLE: 700 if (innerStep == numBands && 701 innerStep1 == numBands) 702 iis.readFully(destDPixbuf, destPos, readLength); 703 else 704 iis.readFully(dpixbuf, 0, readLength); 705 break; 706 } 707 708 if (innerStep != numBands || innerStep1 != numBands) 709 for (int b = 0; b < numBands; b++) { 710 int destBandOffset = 711 destBandOffsets[destinationBands[b]]; 712 destPos += destBandOffset; 713 714 int sourceBandOffset = 715 bandOffsets[sourceBands[b]]; 716 717 switch(dataType) { 718 case DataBuffer.TYPE_BYTE: 719 for (int m1 = 0, n = destPos; m1 < readLength; 720 m1 += innerStep, n += innerStep1) { 721 destPixbuf[n] 722 = pixbuf[m1 + sourceBandOffset]; 723 } 724 break; 725 case DataBuffer.TYPE_SHORT: 726 case DataBuffer.TYPE_USHORT: 727 for (int m1 = 0, n = destPos; m1 < readLength; 728 m1 += innerStep, n += innerStep1) { 729 destSPixbuf[n] 730 = spixbuf[m1 + sourceBandOffset]; 731 } 732 break; 733 case DataBuffer.TYPE_INT: 734 for (int m1 = 0, n = destPos; m1 < readLength; 735 m1 += innerStep, n += innerStep1) { 736 destIPixbuf[n] 737 = ipixbuf[m1 + sourceBandOffset]; 738 } 739 break; 740 case DataBuffer.TYPE_FLOAT: 741 for (int m1 = 0, n = destPos; m1 < readLength; 742 m1 += innerStep, n += innerStep1) { 743 destFPixbuf[n] 744 = fpixbuf[m1 + sourceBandOffset]; 745 } 746 break; 747 case DataBuffer.TYPE_DOUBLE: 748 for (int m1 = 0, n = destPos; m1 < readLength; 749 m1 += innerStep, n += innerStep1) { 750 destDPixbuf[n] 751 = dpixbuf[m1 + sourceBandOffset]; 752 } 753 break; 754 } 755 destPos -= destBandOffset; 756 } 757 758 iis.skipBytes(skipLength); 759 destPos += outerStep1; 760 761 if (destImage != null) 762 if (pixelStride < scanlineStride) 763 reader.processImageUpdateWrapper(destImage, 764 x1, m, 765 outerBound, 766 1, 1, 1, 767 destinationBands); 768 else 769 reader.processImageUpdateWrapper(destImage, 770 m, y1, 771 1, outerBound, 772 1, 1, 773 destinationBands); 774 775 reader.processImageProgressWrapper(percentage + 776 (l + 1.0F) / 777 outerBound / 778 totalTiles); 779 } 780 } else if (sampleModel instanceof BandedSampleModel || 781 sampleModel instanceof SinglePixelPackedSampleModel || 782 bandStride == 0) { 783 boolean isBanded = sampleModel instanceof BandedSampleModel; 784 785 int bandSize = 786 (int)ImageUtil.getBandSize(originalSampleModel); 787 788 for (int b = 0; b < numBands; b++) { 789 iis.seek(tilePosition + bandSize * sourceBands[b] * 790 sampleSizeByte); 791 int destBandOffset = 792 destBandOffsets[destinationBands[b]]; 793 794 iis.skipBytes((ty * scanlineStride + tx * pixelStride) * 795 sampleSizeByte); 796 797 // variables for ther loop 798 int outerFirst, outerSecond, outerStep, outerBound; 799 int innerStep, innerStep1, outerStep1; 800 if (pixelStride < scanlineStride) { 801 outerFirst = 0; 802 outerSecond = y1; 803 outerStep = scaleY; 804 outerBound = cTileHeight; 805 innerStep = scaleX * pixelStride; 806 innerStep1 = destPixelStride; 807 outerStep1 = destScanlineStride; 808 } else { 809 outerFirst = 0; 810 outerSecond = x1; 811 outerStep = scaleX; 812 outerBound = cTileWidth; 813 innerStep = scaleY * scanlineStride; 814 innerStep1 = destScanlineStride; 815 outerStep1 = destPixelStride; 816 } 817 818 int destPos = destSX + (y1 - raster.getSampleModelTranslateY())* destScanlineStride + 819 (x1 - raster.getSampleModelTranslateX()) * destPixelStride + destBandOffset; 820 821 int bank = bankIndices[destinationBands[b]]; 822 823 switch(dataType) { 824 case DataBuffer.TYPE_BYTE: 825 destPixbuf = 826 ((DataBufferByte)raster.getDataBuffer()).getData(bank); 827 break; 828 case DataBuffer.TYPE_SHORT: 829 destSPixbuf = 830 ((DataBufferShort)raster.getDataBuffer()).getData(bank); 831 break; 832 833 case DataBuffer.TYPE_USHORT: 834 destSPixbuf = 835 ((DataBufferUShort)raster.getDataBuffer()).getData(bank); 836 break; 837 838 case DataBuffer.TYPE_INT: 839 destIPixbuf = 840 ((DataBufferInt)raster.getDataBuffer()).getData(bank); 841 break; 842 843 case DataBuffer.TYPE_FLOAT: 844 destFPixbuf = 845 ((DataBufferFloat)raster.getDataBuffer()).getData(bank); 846 break; 847 848 case DataBuffer.TYPE_DOUBLE: 849 destDPixbuf = 850 ((DataBufferDouble)raster.getDataBuffer()).getData(bank); 851 break; 852 } 853 854 for (int l = outerFirst, m = outerSecond; l < outerBound; 855 l += outerStep, m++) { 856 if (reader.getAbortRequest()) 857 break; 858 859 switch(dataType) { 860 case DataBuffer.TYPE_BYTE: 861 if (innerStep == 1 && innerStep1 == 1) { 862 iis.readFully(destPixbuf, destPos, readLength); 863 } else { 864 iis.readFully(pixbuf, 0, readLength); 865 for (int m1 = 0, n = destPos; m1 < readLength; 866 m1 += innerStep, n += innerStep1) { 867 destPixbuf[n] = pixbuf[m1]; 868 } 869 } 870 break; 871 case DataBuffer.TYPE_SHORT: 872 case DataBuffer.TYPE_USHORT: 873 if (innerStep == 1 && innerStep1 == 1) { 874 iis.readFully(destSPixbuf, destPos, readLength); 875 } else { 876 iis.readFully(spixbuf, 0, readLength); 877 for (int m1 = 0, n = destPos; m1 < readLength; 878 m1 += innerStep, n += innerStep1) { 879 destSPixbuf[n] = spixbuf[m1]; 880 } 881 } 882 break; 883 case DataBuffer.TYPE_INT: 884 if (innerStep == 1 && innerStep1 == 1) { 885 iis.readFully(destIPixbuf, destPos, readLength); 886 } else { 887 iis.readFully(ipixbuf, 0, readLength); 888 for (int m1 = 0, n = destPos; m1 < readLength; 889 m1 += innerStep, n += innerStep1) { 890 destIPixbuf[n] = ipixbuf[m1]; 891 } 892 } 893 break; 894 case DataBuffer.TYPE_FLOAT: 895 if (innerStep == 1 && innerStep1 == 1) { 896 iis.readFully(destFPixbuf, destPos, readLength); 897 } else { 898 iis.readFully(fpixbuf, 0, readLength); 899 for (int m1 = 0, n = destPos; m1 < readLength; 900 m1 += innerStep, n += innerStep1) { 901 destFPixbuf[n] = fpixbuf[m1]; 902 } 903 } 904 break; 905 case DataBuffer.TYPE_DOUBLE: 906 if (innerStep == 1 && innerStep1 == 1) { 907 iis.readFully(destDPixbuf, destPos, readLength); 908 } else { 909 iis.readFully(dpixbuf, 0, readLength); 910 for (int m1 = 0, n = destPos; m1 < readLength; 911 m1 += innerStep, n += innerStep1) { 912 destDPixbuf[n] = dpixbuf[m1]; 913 } 914 } 915 break; 916 } 917 918 iis.skipBytes(skipLength); 919 destPos += outerStep1; 920 921 if (destImage != null) { 922 int[] destBands = 923 new int[] {destinationBands[b]}; 924 if (pixelStride < scanlineStride) 925 reader.processImageUpdateWrapper(destImage, 926 x1, m, 927 outerBound, 928 1, 1, 1, 929 destBands); 930 else 931 reader.processImageUpdateWrapper(destImage, 932 m, y1, 1, 933 outerBound, 934 1, 1, 935 destBands); 936 } 937 938 reader.processImageProgressWrapper( 939 (percentage + 940 (l+1.0F)/outerBound/numBands/totalTiles) * 941 100.0F); 942 } 943 } 944 } else if (sampleModel instanceof ComponentSampleModel) { 945 //for the other case, may slow 946 //Allocate buffer for all the types 947 int bufferSize = (int)tileDataSize; 948 949 switch (sampleModel.getDataType()) { 950 case DataBuffer.TYPE_BYTE: 951 if (pixbuf == null || pixbuf.length < tileDataSize) 952 pixbuf = new byte[(int)tileDataSize]; 953 iis.readFully(pixbuf, 0, (int)tileDataSize); 954 break; 955 956 case DataBuffer.TYPE_SHORT: 957 case DataBuffer.TYPE_USHORT: 958 bufferSize /= 2; 959 if (spixbuf == null || spixbuf.length < bufferSize) 960 spixbuf = new short[(int)bufferSize]; 961 iis.readFully(spixbuf, 0, (int)bufferSize); 962 break; 963 964 case DataBuffer.TYPE_INT: 965 bufferSize /= 4; 966 if (ipixbuf == null || ipixbuf.length < bufferSize) 967 ipixbuf = new int[(int)bufferSize]; 968 iis.readFully(ipixbuf, 0, (int)bufferSize); 969 break; 970 971 case DataBuffer.TYPE_FLOAT: 972 bufferSize /= 4; 973 if (fpixbuf == null || fpixbuf.length < bufferSize) 974 fpixbuf = new float[(int)bufferSize]; 975 iis.readFully(fpixbuf, 0, (int)bufferSize); 976 break; 977 978 case DataBuffer.TYPE_DOUBLE: 979 bufferSize /= 8; 980 if (dpixbuf == null || dpixbuf.length < bufferSize) 981 dpixbuf = new double[(int)bufferSize]; 982 iis.readFully(dpixbuf, 0, (int)bufferSize); 983 break; 984 } 985 986 for (int b = 0; b < numBands; b++) { 987 int destBandOffset = 988 destBandOffsets[destinationBands[b]]; 989 990 int destPos = 991 ((ComponentSampleModel)raster.getSampleModel()).getOffset( 992 x1-raster.getSampleModelTranslateX(), 993 y1-raster.getSampleModelTranslateY(), 994 destinationBands[b]); 995 996 int bank = bankIndices[destinationBands[b]]; 997 998 switch(dataType) { 999 case DataBuffer.TYPE_BYTE: 1000 destPixbuf = 1001 ((DataBufferByte)raster.getDataBuffer()).getData(bank); 1002 break; 1003 case DataBuffer.TYPE_SHORT: 1004 destSPixbuf = 1005 ((DataBufferShort)raster.getDataBuffer()).getData(bank); 1006 break; 1007 1008 case DataBuffer.TYPE_USHORT: 1009 destSPixbuf = 1010 ((DataBufferUShort)raster.getDataBuffer()).getData(bank); 1011 break; 1012 1013 case DataBuffer.TYPE_INT: 1014 destIPixbuf = 1015 ((DataBufferInt)raster.getDataBuffer()).getData(bank); 1016 break; 1017 1018 case DataBuffer.TYPE_FLOAT: 1019 destFPixbuf = 1020 ((DataBufferFloat)raster.getDataBuffer()).getData(bank); 1021 break; 1022 1023 case DataBuffer.TYPE_DOUBLE: 1024 destDPixbuf = 1025 ((DataBufferDouble)raster.getDataBuffer()).getData(bank); 1026 break; 1027 } 1028 1029 int srcPos = 1030 ((ComponentSampleModel)originalSampleModel).getOffset(tx, ty, sourceBands[b]); 1031 int skipX = scaleX * pixelStride;; 1032 for (int l = 0, m = y1; l < cTileHeight; 1033 l += scaleY, m++) { 1034 if (reader.getAbortRequest()) 1035 break; 1036 1037 switch(dataType) { 1038 case DataBuffer.TYPE_BYTE: 1039 for (int n = 0, m1 = srcPos, m2 = destPos; 1040 n < lineLength; 1041 n++, m1 += skipX, m2 += destPixelStride) 1042 destPixbuf[m2] = pixbuf[m1]; 1043 break; 1044 case DataBuffer.TYPE_SHORT: 1045 case DataBuffer.TYPE_USHORT: 1046 for (int n = 0, m1 = srcPos, m2 = destPos; 1047 n < lineLength; 1048 n++, m1 += skipX, m2 += destPixelStride) 1049 destSPixbuf[m2] = spixbuf[m1]; 1050 break; 1051 case DataBuffer.TYPE_INT: 1052 for (int n = 0, m1 = srcPos, m2 = destPos; 1053 n < lineLength; 1054 n++, m1 += skipX, m2 += destPixelStride) 1055 destIPixbuf[m2] = ipixbuf[m1]; 1056 break; 1057 case DataBuffer.TYPE_FLOAT: 1058 for (int n = 0, m1 = srcPos, m2 = destPos; 1059 n < lineLength; 1060 n++, m1 += skipX, m2 += destPixelStride) 1061 destFPixbuf[m2] = fpixbuf[m1]; 1062 break; 1063 case DataBuffer.TYPE_DOUBLE: 1064 for (int n = 0, m1 = srcPos, m2 = destPos; 1065 n < lineLength; 1066 n++, m1 += skipX, m2 += destPixelStride) 1067 destDPixbuf[m2] = dpixbuf[m1]; 1068 break; 1069 } 1070 1071 destPos += destScanlineStride; 1072 srcPos += scanlineStride * scaleY; 1073 1074 if (destImage != null) { 1075 int[] destBands = 1076 new int[] {destinationBands[b]}; 1077 reader.processImageUpdateWrapper(destImage, 1078 x1, m, 1079 cTileHeight, 1080 1, 1, 1, 1081 destBands); 1082 } 1083 1084 reader.processImageProgressWrapper(percentage + 1085 (l + 1.0F) / 1086 cTileHeight / 1087 numBands / 1088 totalTiles); 1089 } 1090 } 1091 } else { 1092 throw new IllegalArgumentException(I18N.getString("RawRenderedImage1")); 1093 } 1094 } 1095 } // End loop on horizontal tiles 1096 } // End loop on vertical tiles 1097 1098 return raster; 1099 } 1100 1101 public void setDestImage(BufferedImage image) { 1102 destImage = image; 1103 } 1104 1105 public void clearDestImage() { 1106 destImage = null; 1107 } 1108 1109 private int getTileNum(int x, int y) { 1110 int num = (y - getMinTileY()) * getNumXTiles() + x - getMinTileX(); 1111 1112 if (num < 0 || num >= getNumXTiles() * getNumYTiles()) 1113 throw new IllegalArgumentException(I18N.getString("RawRenderedImage0")); 1114 1115 return num; 1116 } 1117 1118 private int clip(int value, int min, int max) { 1119 if (value < min) 1120 value = min; 1121 if (value > max) 1122 value = max; 1123 return value; 1124 } 1125}