0001: /*
0002: * $RCSfile: RawRenderedImage.java,v $
0003: *
0004: *
0005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
0006: *
0007: * Redistribution and use in source and binary forms, with or without
0008: * modification, are permitted provided that the following conditions
0009: * are met:
0010: *
0011: * - Redistribution of source code must retain the above copyright
0012: * notice, this list of conditions and the following disclaimer.
0013: *
0014: * - Redistribution in binary form must reproduce the above copyright
0015: * notice, this list of conditions and the following disclaimer in
0016: * the documentation and/or other materials provided with the
0017: * distribution.
0018: *
0019: * Neither the name of Sun Microsystems, Inc. or the names of
0020: * contributors may be used to endorse or promote products derived
0021: * from this software without specific prior written permission.
0022: *
0023: * This software is provided "AS IS," without a warranty of any
0024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
0025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
0026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
0028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
0029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
0031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0035: * POSSIBILITY OF SUCH DAMAGES.
0036: *
0037: * You acknowledge that this software is not designed or intended for
0038: * use in the design, construction, operation or maintenance of any
0039: * nuclear facility.
0040: *
0041: * $Revision: 1.2 $
0042: * $Date: 2006/04/21 23:19:13 $
0043: * $State: Exp $
0044: */
0045: package com.sun.media.imageioimpl.plugins.raw;
0046:
0047: import javax.imageio.stream.ImageInputStream;
0048:
0049: import java.awt.Dimension;
0050: import java.awt.Point;
0051: import java.awt.Rectangle;
0052: import java.awt.Transparency;
0053: import java.awt.color.ColorSpace;
0054: import java.awt.image.BufferedImage;
0055: import java.awt.image.BandedSampleModel;
0056: import java.awt.image.ColorModel;
0057: import java.awt.image.ComponentColorModel;
0058: import java.awt.image.ComponentSampleModel;
0059: import java.awt.image.DataBuffer;
0060: import java.awt.image.DataBufferByte;
0061: import java.awt.image.DataBufferDouble;
0062: import java.awt.image.DataBufferFloat;
0063: import java.awt.image.DataBufferInt;
0064: import java.awt.image.DataBufferShort;
0065: import java.awt.image.DataBufferUShort;
0066: import java.awt.image.DirectColorModel;
0067: import java.awt.image.IndexColorModel;
0068: import java.awt.image.MultiPixelPackedSampleModel;
0069: import java.awt.image.PixelInterleavedSampleModel;
0070: import java.awt.image.SinglePixelPackedSampleModel;
0071: import java.awt.image.Raster;
0072: import java.awt.image.RenderedImage;
0073: import java.awt.image.SampleModel;
0074: import java.awt.image.WritableRaster;
0075:
0076: import java.lang.reflect.Constructor;
0077: import java.lang.reflect.Method;
0078: import java.lang.reflect.InvocationTargetException;
0079:
0080: import java.io.*;
0081: import javax.imageio.ImageReadParam;
0082: import javax.imageio.ImageTypeSpecifier;
0083: import com.sun.media.imageio.stream.RawImageInputStream;
0084: import com.sun.media.imageioimpl.common.ImageUtil;
0085: import com.sun.media.imageioimpl.common.SimpleRenderedImage;
0086:
0087: public class RawRenderedImage extends SimpleRenderedImage {
0088: /** The sample model for the original image. */
0089: private SampleModel originalSampleModel;
0090:
0091: private Raster currentTile;
0092: private Point currentTileGrid;
0093:
0094: /** The input stream we read from */
0095: private RawImageInputStream iis = null;
0096:
0097: /** Caches the <code>RawImageReader</code> which creates this object. This
0098: * variable is used to monitor the abortion.
0099: */
0100: private RawImageReader reader;
0101:
0102: /** The <code>ImageReadParam</code> to create this
0103: * <code>renderedImage</code>.
0104: */
0105: private ImageReadParam param = null;
0106:
0107: // The image index in the stream
0108: private int imageIndex;
0109:
0110: /** The destination bounds. */
0111: private Rectangle destinationRegion;
0112: private Rectangle originalRegion;
0113: private Point sourceOrigin;
0114: private Dimension originalDimension;
0115: private int maxXTile, maxYTile;
0116:
0117: /** The subsampling parameters. */
0118: private int scaleX, scaleY, xOffset, yOffset;
0119: private int[] destinationBands = null;
0120: private int[] sourceBands = null;
0121: private int nComp;
0122:
0123: /** Coordinate transform is not needed from the source (image stream)
0124: * to the destination.
0125: */
0126: private boolean noTransform = true;
0127:
0128: /** The raster for medialib tiles to share. */
0129: private WritableRaster rasForATile;
0130:
0131: private BufferedImage destImage;
0132:
0133: /** The position of the first sample of this image in the stream. */
0134: private long position;
0135:
0136: /** cache the size of the data for each tile in the stream. */
0137: private long tileDataSize;
0138:
0139: /** The orginal number tiles in X direction. */
0140: private int originalNumXTiles;
0141:
0142: public RawRenderedImage(RawImageInputStream iis,
0143: RawImageReader reader, ImageReadParam param, int imageIndex)
0144: throws IOException {
0145: this .iis = iis;
0146: this .reader = reader;
0147: this .param = param;
0148: this .imageIndex = imageIndex;
0149: this .position = iis.getImageOffset(imageIndex);
0150: this .originalDimension = iis.getImageDimension(imageIndex);
0151:
0152: ImageTypeSpecifier type = iis.getImageType();
0153: sampleModel = originalSampleModel = type.getSampleModel();
0154: colorModel = type.getColorModel();
0155:
0156: // If the destination band is set used it
0157: sourceBands = (param == null) ? null : param.getSourceBands();
0158:
0159: if (sourceBands == null) {
0160: nComp = originalSampleModel.getNumBands();
0161: sourceBands = new int[nComp];
0162: for (int i = 0; i < nComp; i++)
0163: sourceBands[i] = i;
0164: } else {
0165: sampleModel = originalSampleModel
0166: .createSubsetSampleModel(sourceBands);
0167: colorModel = ImageUtil.createColorModel(null, sampleModel);
0168: }
0169:
0170: nComp = sourceBands.length;
0171:
0172: destinationBands = (param == null) ? null : param
0173: .getDestinationBands();
0174: if (destinationBands == null) {
0175: destinationBands = new int[nComp];
0176: for (int i = 0; i < nComp; i++)
0177: destinationBands[i] = i;
0178: }
0179:
0180: Dimension dim = iis.getImageDimension(imageIndex);
0181: this .width = dim.width;
0182: this .height = dim.height;
0183:
0184: Rectangle sourceRegion = new Rectangle(0, 0, this .width,
0185: this .height);
0186:
0187: originalRegion = (Rectangle) sourceRegion.clone();
0188:
0189: destinationRegion = (Rectangle) sourceRegion.clone();
0190:
0191: if (param != null) {
0192: RawImageReader.computeRegionsWrapper(param, this .width,
0193: this .height, param.getDestination(), sourceRegion,
0194: destinationRegion);
0195: scaleX = param.getSourceXSubsampling();
0196: scaleY = param.getSourceYSubsampling();
0197: xOffset = param.getSubsamplingXOffset();
0198: yOffset = param.getSubsamplingYOffset();
0199: }
0200:
0201: sourceOrigin = new Point(sourceRegion.x, sourceRegion.y);
0202: if (!destinationRegion.equals(sourceRegion))
0203: noTransform = false;
0204:
0205: this .tileDataSize = ImageUtil.getTileSize(originalSampleModel);
0206:
0207: this .tileWidth = originalSampleModel.getWidth();
0208: this .tileHeight = originalSampleModel.getHeight();
0209: this .tileGridXOffset = destinationRegion.x;
0210: this .tileGridYOffset = destinationRegion.y;
0211: this .originalNumXTiles = getNumXTiles();
0212:
0213: this .width = destinationRegion.width;
0214: this .height = destinationRegion.height;
0215: this .minX = destinationRegion.x;
0216: this .minY = destinationRegion.y;
0217:
0218: sampleModel = sampleModel.createCompatibleSampleModel(
0219: tileWidth, tileHeight);
0220:
0221: maxXTile = originalDimension.width / tileWidth;
0222: maxYTile = originalDimension.height / tileHeight;
0223: }
0224:
0225: public synchronized Raster getTile(int tileX, int tileY) {
0226: if (currentTile != null && currentTileGrid.x == tileX
0227: && currentTileGrid.y == tileY)
0228: return currentTile;
0229:
0230: if (tileX >= getNumXTiles() || tileY >= getNumYTiles())
0231: throw new IllegalArgumentException(I18N
0232: .getString("RawRenderedImage0"));
0233:
0234: try {
0235: iis.seek(position + (tileY * originalNumXTiles + tileX)
0236: * tileDataSize);
0237:
0238: int x = tileXToX(tileX);
0239: int y = tileYToY(tileY);
0240: currentTile = Raster.createWritableRaster(sampleModel,
0241: new Point(x, y));
0242:
0243: if (noTransform) {
0244: switch (sampleModel.getDataType()) {
0245: case DataBuffer.TYPE_BYTE:
0246: byte[][] buf = ((DataBufferByte) currentTile
0247: .getDataBuffer()).getBankData();
0248: for (int i = 0; i < buf.length; i++)
0249: iis.readFully(buf[i], 0, buf[i].length);
0250: break;
0251:
0252: case DataBuffer.TYPE_SHORT:
0253: short[][] sbuf = ((DataBufferShort) currentTile
0254: .getDataBuffer()).getBankData();
0255: for (int i = 0; i < sbuf.length; i++)
0256: iis.readFully(sbuf[i], 0, sbuf[i].length);
0257: break;
0258:
0259: case DataBuffer.TYPE_USHORT:
0260: short[][] usbuf = ((DataBufferUShort) currentTile
0261: .getDataBuffer()).getBankData();
0262: for (int i = 0; i < usbuf.length; i++)
0263: iis.readFully(usbuf[i], 0, usbuf[i].length);
0264: break;
0265: case DataBuffer.TYPE_INT:
0266: int[][] ibuf = ((DataBufferInt) currentTile
0267: .getDataBuffer()).getBankData();
0268: for (int i = 0; i < ibuf.length; i++)
0269: iis.readFully(ibuf[i], 0, ibuf[i].length);
0270: break;
0271: case DataBuffer.TYPE_FLOAT:
0272: float[][] fbuf = ((DataBufferFloat) currentTile
0273: .getDataBuffer()).getBankData();
0274: for (int i = 0; i < fbuf.length; i++)
0275: iis.readFully(fbuf[i], 0, fbuf[i].length);
0276: break;
0277: case DataBuffer.TYPE_DOUBLE:
0278: double[][] dbuf = ((DataBufferDouble) currentTile
0279: .getDataBuffer()).getBankData();
0280: for (int i = 0; i < dbuf.length; i++)
0281: iis.readFully(dbuf[i], 0, dbuf[i].length);
0282: break;
0283: }
0284: } else {
0285: currentTile = readSubsampledRaster((WritableRaster) currentTile);
0286: }
0287: } catch (IOException e) {
0288: throw new RuntimeException(e);
0289: }
0290:
0291: if (currentTileGrid == null)
0292: currentTileGrid = new Point(tileX, tileY);
0293: else {
0294: currentTileGrid.x = tileX;
0295: currentTileGrid.y = tileY;
0296: }
0297:
0298: return currentTile;
0299: }
0300:
0301: public void readAsRaster(WritableRaster raster)
0302: throws java.io.IOException {
0303: readSubsampledRaster(raster);
0304: }
0305:
0306: private Raster readSubsampledRaster(WritableRaster raster)
0307: throws IOException {
0308: if (raster == null)
0309: raster = Raster
0310: .createWritableRaster(
0311: sampleModel.createCompatibleSampleModel(
0312: destinationRegion.x
0313: + destinationRegion.width,
0314: destinationRegion.y
0315: + destinationRegion.height),
0316: new Point(destinationRegion.x,
0317: destinationRegion.y));
0318:
0319: int numBands = sourceBands.length;
0320: int dataType = sampleModel.getDataType();
0321: int sampleSizeBit = DataBuffer.getDataTypeSize(dataType);
0322: int sampleSizeByte = (sampleSizeBit + 7) / 8;
0323:
0324: Rectangle destRect = raster.getBounds().intersection(
0325: destinationRegion);
0326:
0327: int offx = destinationRegion.x;
0328: int offy = destinationRegion.y;
0329:
0330: int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x;
0331: int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y;
0332: int sourceEX = (destRect.width - 1) * scaleX + sourceSX;
0333: int sourceEY = (destRect.height - 1) * scaleY + sourceSY;
0334: int startXTile = sourceSX / tileWidth;
0335: int startYTile = sourceSY / tileHeight;
0336: int endXTile = sourceEX / tileWidth;
0337: int endYTile = sourceEY / tileHeight;
0338:
0339: startXTile = clip(startXTile, 0, maxXTile);
0340: startYTile = clip(startYTile, 0, maxYTile);
0341: endXTile = clip(endXTile, 0, maxXTile);
0342: endYTile = clip(endYTile, 0, maxYTile);
0343:
0344: int totalXTiles = getNumXTiles();
0345: int totalYTiles = getNumYTiles();
0346: int totalTiles = totalXTiles * totalYTiles;
0347:
0348: //The line buffer for the source
0349: byte[] pixbuf = null; // byte buffer for the decoded pixels.
0350: short[] spixbuf = null; // byte buffer for the decoded pixels.
0351: int[] ipixbuf = null; // byte buffer for the decoded pixels.
0352: float[] fpixbuf = null; // byte buffer for the decoded pixels.
0353: double[] dpixbuf = null; // byte buffer for the decoded pixels.
0354:
0355: // A flag to show the ComponentSampleModel has a single data bank
0356: boolean singleBank = true;
0357: int pixelStride = 0;
0358: int scanlineStride = 0;
0359: int bandStride = 0;
0360: int[] bandOffsets = null;
0361: int[] bankIndices = null;
0362:
0363: if (originalSampleModel instanceof ComponentSampleModel) {
0364: ComponentSampleModel csm = (ComponentSampleModel) originalSampleModel;
0365: bankIndices = csm.getBankIndices();
0366: int maxBank = 0;
0367: for (int i = 0; i < bankIndices.length; i++)
0368: if (maxBank > bankIndices[i])
0369: maxBank = bankIndices[i];
0370:
0371: if (maxBank > 0)
0372: singleBank = false;
0373: pixelStride = csm.getPixelStride();
0374:
0375: scanlineStride = csm.getScanlineStride();
0376: bandOffsets = csm.getBandOffsets();
0377: for (int i = 0; i < bandOffsets.length; i++)
0378: if (bandStride < bandOffsets[i])
0379: bandStride = bandOffsets[i];
0380: } else if (originalSampleModel instanceof MultiPixelPackedSampleModel) {
0381: scanlineStride = ((MultiPixelPackedSampleModel) originalSampleModel)
0382: .getScanlineStride();
0383: } else if (originalSampleModel instanceof SinglePixelPackedSampleModel) {
0384: pixelStride = 1;
0385: scanlineStride = ((SinglePixelPackedSampleModel) originalSampleModel)
0386: .getScanlineStride();
0387: }
0388:
0389: // The dstination buffer for the raster
0390: byte[] destPixbuf = null; // byte buffer for the decoded pixels.
0391: short[] destSPixbuf = null; // byte buffer for the decoded pixels.
0392: int[] destIPixbuf = null; // byte buffer for the decoded pixels.
0393: float[] destFPixbuf = null; // byte buffer for the decoded pixels.
0394: double[] destDPixbuf = null; // byte buffer for the decoded pixels.
0395: int[] destBandOffsets = null;
0396: int destPixelStride = 0;
0397: int destScanlineStride = 0;
0398: int destSX = 0; // The first pixel for the destionation
0399:
0400: if (raster.getSampleModel() instanceof ComponentSampleModel) {
0401: ComponentSampleModel csm = (ComponentSampleModel) raster
0402: .getSampleModel();
0403: bankIndices = csm.getBankIndices();
0404: destBandOffsets = csm.getBandOffsets();
0405: destPixelStride = csm.getPixelStride();
0406: destScanlineStride = csm.getScanlineStride();
0407: destSX = csm.getOffset(raster.getMinX()
0408: - raster.getSampleModelTranslateX(), raster
0409: .getMinY()
0410: - raster.getSampleModelTranslateY())
0411: - destBandOffsets[0];
0412:
0413: switch (dataType) {
0414: case DataBuffer.TYPE_BYTE:
0415: destPixbuf = ((DataBufferByte) raster.getDataBuffer())
0416: .getData();
0417: break;
0418: case DataBuffer.TYPE_SHORT:
0419: destSPixbuf = ((DataBufferShort) raster.getDataBuffer())
0420: .getData();
0421: break;
0422:
0423: case DataBuffer.TYPE_USHORT:
0424: destSPixbuf = ((DataBufferUShort) raster
0425: .getDataBuffer()).getData();
0426: break;
0427:
0428: case DataBuffer.TYPE_INT:
0429: destIPixbuf = ((DataBufferInt) raster.getDataBuffer())
0430: .getData();
0431: break;
0432:
0433: case DataBuffer.TYPE_FLOAT:
0434: destFPixbuf = ((DataBufferFloat) raster.getDataBuffer())
0435: .getData();
0436: break;
0437:
0438: case DataBuffer.TYPE_DOUBLE:
0439: destDPixbuf = ((DataBufferDouble) raster
0440: .getDataBuffer()).getData();
0441: break;
0442: }
0443: } else if (raster.getSampleModel() instanceof SinglePixelPackedSampleModel) {
0444: numBands = 1;
0445: bankIndices = new int[] { 0 };
0446: destBandOffsets = new int[numBands];
0447: for (int i = 0; i < numBands; i++)
0448: destBandOffsets[i] = 0;
0449: destPixelStride = 1;
0450: destScanlineStride = ((SinglePixelPackedSampleModel) raster
0451: .getSampleModel()).getScanlineStride();
0452: }
0453:
0454: // Start the data delivery to the cached consumers tile by tile
0455: for (int y = startYTile; y <= endYTile; y++) {
0456: if (reader.getAbortRequest())
0457: break;
0458:
0459: // Loop on horizontal tiles
0460: for (int x = startXTile; x <= endXTile; x++) {
0461: if (reader.getAbortRequest())
0462: break;
0463:
0464: long tilePosition = position
0465: + (y * originalNumXTiles + x) * tileDataSize;
0466: iis.seek(tilePosition);
0467: float percentage = (x - startXTile + y * totalXTiles)
0468: / totalXTiles;
0469:
0470: int startX = x * tileWidth;
0471: int startY = y * tileHeight;
0472:
0473: int cTileHeight = tileHeight;
0474: int cTileWidth = tileWidth;
0475:
0476: if (startY + cTileHeight >= originalDimension.height)
0477: cTileHeight = originalDimension.height - startY;
0478:
0479: if (startX + cTileWidth >= originalDimension.width)
0480: cTileWidth = originalDimension.width - startX;
0481:
0482: int tx = startX;
0483: int ty = startY;
0484:
0485: // If source start position calculated by taking subsampling
0486: // into account is after the tile's start X position, adjust
0487: // the start position accordingly
0488: if (sourceSX > startX) {
0489: cTileWidth += startX - sourceSX;
0490: tx = sourceSX;
0491: startX = sourceSX;
0492: }
0493:
0494: if (sourceSY > startY) {
0495: cTileHeight += startY - sourceSY;
0496: ty = sourceSY;
0497: startY = sourceSY;
0498: }
0499:
0500: // If source end position calculated by taking subsampling
0501: // into account is prior to the tile's end X position, adjust
0502: // the tile width to read accordingly
0503: if (sourceEX < startX + cTileWidth - 1) {
0504: cTileWidth += sourceEX - startX - cTileWidth + 1;
0505: }
0506:
0507: if (sourceEY < startY + cTileHeight - 1) {
0508: cTileHeight += sourceEY - startY - cTileHeight + 1;
0509: }
0510:
0511: // The start X in the destination
0512: int x1 = (startX + scaleX - 1 - sourceOrigin.x)
0513: / scaleX;
0514: int x2 = (startX + scaleX - 1 + cTileWidth - sourceOrigin.x)
0515: / scaleX;
0516: int lineLength = x2 - x1;
0517: x2 = (x2 - 1) * scaleX + sourceOrigin.x;
0518:
0519: int y1 = (startY + scaleY - 1 - sourceOrigin.y)
0520: / scaleY;
0521: startX = x1 * scaleX + sourceOrigin.x;
0522: startY = y1 * scaleY + sourceOrigin.y;
0523:
0524: // offx is destination.x
0525: x1 += offx;
0526: y1 += offy;
0527:
0528: tx -= x * tileWidth;
0529: ty -= y * tileHeight;
0530:
0531: if (sampleModel instanceof MultiPixelPackedSampleModel) {
0532: MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel) originalSampleModel;
0533:
0534: iis.skipBytes(mppsm.getOffset(tx, ty)
0535: * sampleSizeByte);
0536:
0537: int readBytes = (mppsm.getOffset(x2, 0)
0538: - mppsm.getOffset(startX, 0) + 1)
0539: * sampleSizeByte;
0540:
0541: int skipLength = (scanlineStride * scaleY - readBytes)
0542: * sampleSizeByte;
0543: readBytes *= sampleSizeByte;
0544:
0545: if (pixbuf == null || pixbuf.length < readBytes)
0546: pixbuf = new byte[readBytes];
0547:
0548: int bitoff = mppsm.getBitOffset(tx);
0549:
0550: for (int l = 0, m = y1; l < cTileHeight; l += scaleY, m++) {
0551: if (reader.getAbortRequest())
0552: break;
0553: iis.readFully(pixbuf, 0, readBytes);
0554: if (scaleX == 1) {
0555:
0556: if (bitoff != 0) {
0557: int mask1 = (255 << bitoff) & 255;
0558: int mask2 = ~mask1 & 255;
0559: int shift = 8 - bitoff;
0560:
0561: int n = 0;
0562: for (; n < readBytes - 1; n++)
0563: pixbuf[n] = (byte) (((pixbuf[n] & mask2) << shift) | (pixbuf[n + 1] & mask1) >> bitoff);
0564: pixbuf[n] = (byte) ((pixbuf[n] & mask2) << shift);
0565: }
0566: } else {
0567:
0568: int bit = 7;
0569: int pos = 0;
0570: int mask = 128;
0571:
0572: for (int n = 0, n1 = startX & 7; n < lineLength; n++, n1 += scaleX) {
0573: pixbuf[pos] = (byte) ((pixbuf[pos] & ~(1 << bit)) | (((pixbuf[n1 >> 3] >> (7 - (n1 & 7))) & 1) << bit));
0574: bit--;
0575: if (bit == -1) {
0576: bit = 7;
0577: pos++;
0578: }
0579: }
0580: }
0581:
0582: ImageUtil.setPackedBinaryData(pixbuf, raster,
0583: new Rectangle(x1, m, lineLength, 1));
0584: iis.skipBytes(skipLength);
0585: if (destImage != null)
0586: reader.processImageUpdateWrapper(destImage,
0587: x1, m, cTileWidth, 1, 1, 1,
0588: destinationBands);
0589:
0590: reader.processImageProgressWrapper(percentage
0591: + (l - startY + 1.0F) / cTileHeight
0592: / totalTiles);
0593: }
0594: } else {
0595:
0596: int readLength, skipLength;
0597: if (pixelStride < scanlineStride) {
0598: readLength = cTileWidth * pixelStride;
0599: skipLength = (scanlineStride * scaleY - readLength)
0600: * sampleSizeByte;
0601: } else {
0602: readLength = cTileHeight * scanlineStride;
0603: skipLength = (pixelStride * scaleX - readLength)
0604: * sampleSizeByte;
0605: }
0606:
0607: //Allocate buffer for all the types
0608: switch (sampleModel.getDataType()) {
0609: case DataBuffer.TYPE_BYTE:
0610: if (pixbuf == null
0611: || pixbuf.length < readLength)
0612: pixbuf = new byte[readLength];
0613: break;
0614:
0615: case DataBuffer.TYPE_SHORT:
0616: case DataBuffer.TYPE_USHORT:
0617: if (spixbuf == null
0618: || spixbuf.length < readLength)
0619: spixbuf = new short[readLength];
0620: break;
0621:
0622: case DataBuffer.TYPE_INT:
0623: if (ipixbuf == null
0624: || ipixbuf.length < readLength)
0625: ipixbuf = new int[readLength];
0626: break;
0627:
0628: case DataBuffer.TYPE_FLOAT:
0629: if (fpixbuf == null
0630: || fpixbuf.length < readLength)
0631: fpixbuf = new float[readLength];
0632: break;
0633:
0634: case DataBuffer.TYPE_DOUBLE:
0635: if (dpixbuf == null
0636: || dpixbuf.length < readLength)
0637: dpixbuf = new double[readLength];
0638: break;
0639: }
0640:
0641: if (sampleModel instanceof PixelInterleavedSampleModel) {
0642: iis.skipBytes((tx * pixelStride + ty
0643: * scanlineStride)
0644: * sampleSizeByte);
0645:
0646: // variables for ther loop
0647: int outerFirst, outerSecond, outerStep, outerBound;
0648: int innerStep, innerStep1, outerStep1;
0649: if (pixelStride < scanlineStride) {
0650: outerFirst = 0;
0651: outerSecond = y1;
0652: outerStep = scaleY;
0653: outerBound = cTileHeight;
0654: innerStep = scaleX * pixelStride;
0655: innerStep1 = destPixelStride;
0656: outerStep1 = destScanlineStride;
0657: } else {
0658: outerFirst = 0;
0659: outerSecond = x1;
0660: outerStep = scaleX;
0661: outerBound = cTileWidth;
0662: innerStep = scaleY * scanlineStride;
0663: innerStep1 = destScanlineStride;
0664: outerStep1 = destPixelStride;
0665: }
0666:
0667: int destPos = destSX
0668: + (y1 - raster
0669: .getSampleModelTranslateY())
0670: * destScanlineStride
0671: + (x1 - raster
0672: .getSampleModelTranslateX())
0673: * destPixelStride;
0674:
0675: for (int l = outerFirst, m = outerSecond; l < outerBound; l += outerStep, m++) {
0676: if (reader.getAbortRequest())
0677: break;
0678:
0679: switch (dataType) {
0680: case DataBuffer.TYPE_BYTE:
0681: if (innerStep == numBands
0682: && innerStep1 == numBands)
0683: iis.readFully(destPixbuf, destPos,
0684: readLength);
0685: else
0686: iis
0687: .readFully(pixbuf, 0,
0688: readLength);
0689: break;
0690: case DataBuffer.TYPE_SHORT:
0691: case DataBuffer.TYPE_USHORT:
0692: if (innerStep == numBands
0693: && innerStep1 == numBands) {
0694: iis.readFully(destSPixbuf, destPos,
0695: readLength);
0696: } else
0697: iis.readFully(spixbuf, 0,
0698: readLength);
0699: break;
0700: case DataBuffer.TYPE_INT:
0701: if (innerStep == numBands
0702: && innerStep1 == numBands)
0703: iis.readFully(destIPixbuf, destPos,
0704: readLength);
0705: else
0706: iis.readFully(ipixbuf, 0,
0707: readLength);
0708: break;
0709: case DataBuffer.TYPE_FLOAT:
0710: if (innerStep == numBands
0711: && innerStep1 == numBands)
0712: iis.readFully(destFPixbuf, destPos,
0713: readLength);
0714: else
0715: iis.readFully(fpixbuf, 0,
0716: readLength);
0717: break;
0718: case DataBuffer.TYPE_DOUBLE:
0719: if (innerStep == numBands
0720: && innerStep1 == numBands)
0721: iis.readFully(destDPixbuf, destPos,
0722: readLength);
0723: else
0724: iis.readFully(dpixbuf, 0,
0725: readLength);
0726: break;
0727: }
0728:
0729: if (innerStep != numBands
0730: || innerStep1 != numBands)
0731: for (int b = 0; b < numBands; b++) {
0732: int destBandOffset = destBandOffsets[destinationBands[b]];
0733: destPos += destBandOffset;
0734:
0735: int sourceBandOffset = bandOffsets[sourceBands[b]];
0736:
0737: switch (dataType) {
0738: case DataBuffer.TYPE_BYTE:
0739: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0740: destPixbuf[n] = pixbuf[m1
0741: + sourceBandOffset];
0742: }
0743: break;
0744: case DataBuffer.TYPE_SHORT:
0745: case DataBuffer.TYPE_USHORT:
0746: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0747: destSPixbuf[n] = spixbuf[m1
0748: + sourceBandOffset];
0749: }
0750: break;
0751: case DataBuffer.TYPE_INT:
0752: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0753: destIPixbuf[n] = ipixbuf[m1
0754: + sourceBandOffset];
0755: }
0756: break;
0757: case DataBuffer.TYPE_FLOAT:
0758: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0759: destFPixbuf[n] = fpixbuf[m1
0760: + sourceBandOffset];
0761: }
0762: break;
0763: case DataBuffer.TYPE_DOUBLE:
0764: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0765: destDPixbuf[n] = dpixbuf[m1
0766: + sourceBandOffset];
0767: }
0768: break;
0769: }
0770: destPos -= destBandOffset;
0771: }
0772:
0773: iis.skipBytes(skipLength);
0774: destPos += outerStep1;
0775:
0776: if (destImage != null)
0777: if (pixelStride < scanlineStride)
0778: reader.processImageUpdateWrapper(
0779: destImage, x1, m,
0780: outerBound, 1, 1, 1,
0781: destinationBands);
0782: else
0783: reader.processImageUpdateWrapper(
0784: destImage, m, y1, 1,
0785: outerBound, 1, 1,
0786: destinationBands);
0787:
0788: reader
0789: .processImageProgressWrapper(percentage
0790: + (l + 1.0F)
0791: / outerBound
0792: / totalTiles);
0793: }
0794: } else if (sampleModel instanceof BandedSampleModel
0795: || sampleModel instanceof SinglePixelPackedSampleModel
0796: || bandStride == 0) {
0797: boolean isBanded = sampleModel instanceof BandedSampleModel;
0798:
0799: int bandSize = (int) ImageUtil
0800: .getBandSize(originalSampleModel);
0801:
0802: for (int b = 0; b < numBands; b++) {
0803: iis.seek(tilePosition + bandSize
0804: * sourceBands[b] * sampleSizeByte);
0805: int destBandOffset = destBandOffsets[destinationBands[b]];
0806:
0807: iis.skipBytes((ty * scanlineStride + tx
0808: * pixelStride)
0809: * sampleSizeByte);
0810:
0811: // variables for ther loop
0812: int outerFirst, outerSecond, outerStep, outerBound;
0813: int innerStep, innerStep1, outerStep1;
0814: if (pixelStride < scanlineStride) {
0815: outerFirst = 0;
0816: outerSecond = y1;
0817: outerStep = scaleY;
0818: outerBound = cTileHeight;
0819: innerStep = scaleX * pixelStride;
0820: innerStep1 = destPixelStride;
0821: outerStep1 = destScanlineStride;
0822: } else {
0823: outerFirst = 0;
0824: outerSecond = x1;
0825: outerStep = scaleX;
0826: outerBound = cTileWidth;
0827: innerStep = scaleY * scanlineStride;
0828: innerStep1 = destScanlineStride;
0829: outerStep1 = destPixelStride;
0830: }
0831:
0832: int destPos = destSX
0833: + (y1 - raster
0834: .getSampleModelTranslateY())
0835: * destScanlineStride
0836: + (x1 - raster
0837: .getSampleModelTranslateX())
0838: * destPixelStride + destBandOffset;
0839:
0840: int bank = bankIndices[destinationBands[b]];
0841:
0842: switch (dataType) {
0843: case DataBuffer.TYPE_BYTE:
0844: destPixbuf = ((DataBufferByte) raster
0845: .getDataBuffer()).getData(bank);
0846: break;
0847: case DataBuffer.TYPE_SHORT:
0848: destSPixbuf = ((DataBufferShort) raster
0849: .getDataBuffer()).getData(bank);
0850: break;
0851:
0852: case DataBuffer.TYPE_USHORT:
0853: destSPixbuf = ((DataBufferUShort) raster
0854: .getDataBuffer()).getData(bank);
0855: break;
0856:
0857: case DataBuffer.TYPE_INT:
0858: destIPixbuf = ((DataBufferInt) raster
0859: .getDataBuffer()).getData(bank);
0860: break;
0861:
0862: case DataBuffer.TYPE_FLOAT:
0863: destFPixbuf = ((DataBufferFloat) raster
0864: .getDataBuffer()).getData(bank);
0865: break;
0866:
0867: case DataBuffer.TYPE_DOUBLE:
0868: destDPixbuf = ((DataBufferDouble) raster
0869: .getDataBuffer()).getData(bank);
0870: break;
0871: }
0872:
0873: for (int l = outerFirst, m = outerSecond; l < outerBound; l += outerStep, m++) {
0874: if (reader.getAbortRequest())
0875: break;
0876:
0877: switch (dataType) {
0878: case DataBuffer.TYPE_BYTE:
0879: if (innerStep == 1
0880: && innerStep1 == 1) {
0881: iis.readFully(destPixbuf,
0882: destPos, readLength);
0883: } else {
0884: iis.readFully(pixbuf, 0,
0885: readLength);
0886: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0887: destPixbuf[n] = pixbuf[m1];
0888: }
0889: }
0890: break;
0891: case DataBuffer.TYPE_SHORT:
0892: case DataBuffer.TYPE_USHORT:
0893: if (innerStep == 1
0894: && innerStep1 == 1) {
0895: iis.readFully(destSPixbuf,
0896: destPos, readLength);
0897: } else {
0898: iis.readFully(spixbuf, 0,
0899: readLength);
0900: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0901: destSPixbuf[n] = spixbuf[m1];
0902: }
0903: }
0904: break;
0905: case DataBuffer.TYPE_INT:
0906: if (innerStep == 1
0907: && innerStep1 == 1) {
0908: iis.readFully(destIPixbuf,
0909: destPos, readLength);
0910: } else {
0911: iis.readFully(ipixbuf, 0,
0912: readLength);
0913: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0914: destIPixbuf[n] = ipixbuf[m1];
0915: }
0916: }
0917: break;
0918: case DataBuffer.TYPE_FLOAT:
0919: if (innerStep == 1
0920: && innerStep1 == 1) {
0921: iis.readFully(destFPixbuf,
0922: destPos, readLength);
0923: } else {
0924: iis.readFully(fpixbuf, 0,
0925: readLength);
0926: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0927: destFPixbuf[n] = fpixbuf[m1];
0928: }
0929: }
0930: break;
0931: case DataBuffer.TYPE_DOUBLE:
0932: if (innerStep == 1
0933: && innerStep1 == 1) {
0934: iis.readFully(destDPixbuf,
0935: destPos, readLength);
0936: } else {
0937: iis.readFully(dpixbuf, 0,
0938: readLength);
0939: for (int m1 = 0, n = destPos; m1 < readLength; m1 += innerStep, n += innerStep1) {
0940: destDPixbuf[n] = dpixbuf[m1];
0941: }
0942: }
0943: break;
0944: }
0945:
0946: iis.skipBytes(skipLength);
0947: destPos += outerStep1;
0948:
0949: if (destImage != null) {
0950: int[] destBands = new int[] { destinationBands[b] };
0951: if (pixelStride < scanlineStride)
0952: reader
0953: .processImageUpdateWrapper(
0954: destImage, x1,
0955: m, outerBound,
0956: 1, 1, 1,
0957: destBands);
0958: else
0959: reader
0960: .processImageUpdateWrapper(
0961: destImage, m,
0962: y1, 1,
0963: outerBound, 1,
0964: 1, destBands);
0965: }
0966:
0967: reader
0968: .processImageProgressWrapper((percentage + (l + 1.0F)
0969: / outerBound
0970: / numBands
0971: / totalTiles) * 100.0F);
0972: }
0973: }
0974: } else if (sampleModel instanceof ComponentSampleModel) {
0975: //for the other case, may slow
0976: //Allocate buffer for all the types
0977: int bufferSize = (int) tileDataSize;
0978:
0979: switch (sampleModel.getDataType()) {
0980: case DataBuffer.TYPE_BYTE:
0981: if (pixbuf == null
0982: || pixbuf.length < tileDataSize)
0983: pixbuf = new byte[(int) tileDataSize];
0984: iis
0985: .readFully(pixbuf, 0,
0986: (int) tileDataSize);
0987: break;
0988:
0989: case DataBuffer.TYPE_SHORT:
0990: case DataBuffer.TYPE_USHORT:
0991: bufferSize /= 2;
0992: if (spixbuf == null
0993: || spixbuf.length < bufferSize)
0994: spixbuf = new short[(int) bufferSize];
0995: iis.readFully(spixbuf, 0, (int) bufferSize);
0996: break;
0997:
0998: case DataBuffer.TYPE_INT:
0999: bufferSize /= 4;
1000: if (ipixbuf == null
1001: || ipixbuf.length < bufferSize)
1002: ipixbuf = new int[(int) bufferSize];
1003: iis.readFully(ipixbuf, 0, (int) bufferSize);
1004: break;
1005:
1006: case DataBuffer.TYPE_FLOAT:
1007: bufferSize /= 4;
1008: if (fpixbuf == null
1009: || fpixbuf.length < bufferSize)
1010: fpixbuf = new float[(int) bufferSize];
1011: iis.readFully(fpixbuf, 0, (int) bufferSize);
1012: break;
1013:
1014: case DataBuffer.TYPE_DOUBLE:
1015: bufferSize /= 8;
1016: if (dpixbuf == null
1017: || dpixbuf.length < bufferSize)
1018: dpixbuf = new double[(int) bufferSize];
1019: iis.readFully(dpixbuf, 0, (int) bufferSize);
1020: break;
1021: }
1022:
1023: for (int b = 0; b < numBands; b++) {
1024: int destBandOffset = destBandOffsets[destinationBands[b]];
1025:
1026: int destPos = ((ComponentSampleModel) raster
1027: .getSampleModel())
1028: .getOffset(
1029: x1
1030: - raster
1031: .getSampleModelTranslateX(),
1032: y1
1033: - raster
1034: .getSampleModelTranslateY(),
1035: destinationBands[b]);
1036:
1037: int bank = bankIndices[destinationBands[b]];
1038:
1039: switch (dataType) {
1040: case DataBuffer.TYPE_BYTE:
1041: destPixbuf = ((DataBufferByte) raster
1042: .getDataBuffer()).getData(bank);
1043: break;
1044: case DataBuffer.TYPE_SHORT:
1045: destSPixbuf = ((DataBufferShort) raster
1046: .getDataBuffer()).getData(bank);
1047: break;
1048:
1049: case DataBuffer.TYPE_USHORT:
1050: destSPixbuf = ((DataBufferUShort) raster
1051: .getDataBuffer()).getData(bank);
1052: break;
1053:
1054: case DataBuffer.TYPE_INT:
1055: destIPixbuf = ((DataBufferInt) raster
1056: .getDataBuffer()).getData(bank);
1057: break;
1058:
1059: case DataBuffer.TYPE_FLOAT:
1060: destFPixbuf = ((DataBufferFloat) raster
1061: .getDataBuffer()).getData(bank);
1062: break;
1063:
1064: case DataBuffer.TYPE_DOUBLE:
1065: destDPixbuf = ((DataBufferDouble) raster
1066: .getDataBuffer()).getData(bank);
1067: break;
1068: }
1069:
1070: int srcPos = ((ComponentSampleModel) originalSampleModel)
1071: .getOffset(tx, ty, sourceBands[b]);
1072: int skipX = scaleX * pixelStride;
1073: ;
1074: for (int l = 0, m = y1; l < cTileHeight; l += scaleY, m++) {
1075: if (reader.getAbortRequest())
1076: break;
1077:
1078: switch (dataType) {
1079: case DataBuffer.TYPE_BYTE:
1080: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride)
1081: destPixbuf[m2] = pixbuf[m1];
1082: break;
1083: case DataBuffer.TYPE_SHORT:
1084: case DataBuffer.TYPE_USHORT:
1085: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride)
1086: destSPixbuf[m2] = spixbuf[m1];
1087: break;
1088: case DataBuffer.TYPE_INT:
1089: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride)
1090: destIPixbuf[m2] = ipixbuf[m1];
1091: break;
1092: case DataBuffer.TYPE_FLOAT:
1093: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride)
1094: destFPixbuf[m2] = fpixbuf[m1];
1095: break;
1096: case DataBuffer.TYPE_DOUBLE:
1097: for (int n = 0, m1 = srcPos, m2 = destPos; n < lineLength; n++, m1 += skipX, m2 += destPixelStride)
1098: destDPixbuf[m2] = dpixbuf[m1];
1099: break;
1100: }
1101:
1102: destPos += destScanlineStride;
1103: srcPos += scanlineStride * scaleY;
1104:
1105: if (destImage != null) {
1106: int[] destBands = new int[] { destinationBands[b] };
1107: reader.processImageUpdateWrapper(
1108: destImage, x1, m,
1109: cTileHeight, 1, 1, 1,
1110: destBands);
1111: }
1112:
1113: reader
1114: .processImageProgressWrapper(percentage
1115: + (l + 1.0F)
1116: / cTileHeight
1117: / numBands / totalTiles);
1118: }
1119: }
1120: } else {
1121: throw new IllegalArgumentException(I18N
1122: .getString("RawRenderedImage1"));
1123: }
1124: }
1125: } // End loop on horizontal tiles
1126: } // End loop on vertical tiles
1127:
1128: return raster;
1129: }
1130:
1131: public void setDestImage(BufferedImage image) {
1132: destImage = image;
1133: }
1134:
1135: public void clearDestImage() {
1136: destImage = null;
1137: }
1138:
1139: private int getTileNum(int x, int y) {
1140: int num = (y - getMinTileY()) * getNumXTiles() + x
1141: - getMinTileX();
1142:
1143: if (num < 0 || num >= getNumXTiles() * getNumYTiles())
1144: throw new IllegalArgumentException(I18N
1145: .getString("RawRenderedImage0"));
1146:
1147: return num;
1148: }
1149:
1150: private int clip(int value, int min, int max) {
1151: if (value < min)
1152: value = min;
1153: if (value > max)
1154: value = max;
1155: return value;
1156: }
1157: }
|