0001: /*
0002: * $RCSfile: ComponentSampleModelJAI.java,v $
0003: *
0004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Use is subject to license terms.
0007: *
0008: * $Revision: 1.1 $
0009: * $Date: 2005/02/11 04:57:07 $
0010: * $State: Exp $
0011: */
0012: package javax.media.jai;
0013:
0014: import java.awt.Point;
0015: import java.awt.Rectangle;
0016: import java.awt.image.ComponentSampleModel;
0017: import java.awt.image.DataBuffer;
0018: import java.awt.image.DataBufferByte;
0019: import java.awt.image.DataBufferShort;
0020: import java.awt.image.DataBufferInt;
0021: import java.awt.image.DataBufferUShort;
0022: import java.awt.image.Raster;
0023: import java.awt.image.SampleModel;
0024: import java.awt.image.WritableRaster;
0025: import com.sun.media.jai.util.DataBufferUtils;
0026:
0027: /**
0028: * This class represents image data which is stored such that each sample
0029: * of a pixel occupies one data element of the <code>DataBuffer</code>. It stores the
0030: * N samples which make up a pixel in N separate data array elements.
0031: * Different bands may be in different banks of the <code>DataBuffer</code>.
0032: * Accessor methods are provided so that image data can be manipulated
0033: * directly. This class can support different kinds of interleaving, e.g.
0034: * band interleaving, scanline interleaving, and pixel interleaving.
0035: * Pixel stride is the number of data array elements between two samples
0036: * for the same band on the same scanline. Scanline stride is the number
0037: * of data array elements between a given sample and the corresponding sample
0038: * in the same column of the next scanline. Band offsets denote the number
0039: * of data array elements from the first data array element of the bank
0040: * of the <code>DataBuffer</code> holding each band to the first sample of the band.
0041: * The bands are numbered from 0 to N-1. This class can represent image
0042: * data for the dataTypes enumerated in java.awt.image.DataBuffer (all
0043: * samples of a given <code>ComponentSampleModel</code> are stored with the same precision)
0044: * . This class adds support for <code>Double</code> and <code>Float</code> data types in addition
0045: * to those supported by the <code>ComponentSampleModel</code> class in Java 2D.
0046: * All strides and offsets must be non-negative.
0047: * @see java.awt.image.ComponentSampleModel
0048: */
0049:
0050: public class ComponentSampleModelJAI extends ComponentSampleModel {
0051:
0052: /**
0053: * Constructs a <code>ComponentSampleModel</code> with the specified
0054: * parameters. The number of bands will be given by the length of
0055: * the bandOffsets array. All bands will be stored in the first
0056: * bank of the <code>DataBuffer</code>.
0057: *
0058: * @param dataType The data type for storing samples.
0059: * @param w The width (in pixels) of the region of
0060: * image data described.
0061: * @param h The height (in pixels) of the region of
0062: * image data described.
0063: * @param pixelStride The pixel stride of the region of image
0064: * data described.
0065: * @param scanlineStride The line stride of the region of image
0066: * data described.
0067: * @param bandOffsets The offsets of all bands.
0068: */
0069: public ComponentSampleModelJAI(int dataType, int w, int h,
0070: int pixelStride, int scanlineStride, int bandOffsets[]) {
0071: super (dataType, w, h, pixelStride, scanlineStride, bandOffsets);
0072: }
0073:
0074: /**
0075: * Constructs a <code>ComponentSampleModel</code> with the specified
0076: * parameters. The number of bands will be given by the length of
0077: * the bandOffsets array. Different bands may be stored in
0078: * different banks of the <code>DataBuffer</code>.
0079: *
0080: * @param dataType The data type for storing samples.
0081: * @param w The width (in pixels) of the region of
0082: * image data described.
0083: * @param h The height (in pixels) of the region of
0084: * image data described.
0085: * @param pixelStride The pixel stride of the region of image
0086: * data described.
0087: * @param scanlineStride The line stride of the region of image
0088: * data described.
0089: * @param bankIndices The bank indices of all bands.
0090: * @param bandOffsets The band offsets of all bands.
0091: */
0092: public ComponentSampleModelJAI(int dataType, int w, int h,
0093: int pixelStride, int scanlineStride, int bankIndices[],
0094: int bandOffsets[]) {
0095: super (dataType, w, h, pixelStride, scanlineStride, bankIndices,
0096: bandOffsets);
0097: }
0098:
0099: /**
0100: * Returns the size of the data buffer (in data elements) needed
0101: * for a data buffer that matches this <code>ComponentSampleModel</code>.
0102: */
0103: private long getBufferSize() {
0104: int maxBandOff = bandOffsets[0];
0105: for (int i = 1; i < bandOffsets.length; i++)
0106: maxBandOff = Math.max(maxBandOff, bandOffsets[i]);
0107:
0108: long size = 0;
0109: if (maxBandOff >= 0)
0110: size += maxBandOff + 1;
0111: if (pixelStride > 0)
0112: size += pixelStride * (width - 1);
0113: if (scanlineStride > 0)
0114: size += scanlineStride * (height - 1);
0115: return size;
0116: }
0117:
0118: /**
0119: * Preserves band ordering with new step factor...
0120: */
0121: private int[] JAIorderBands(int orig[], int step) {
0122: int map[] = new int[orig.length];
0123: int ret[] = new int[orig.length];
0124:
0125: for (int i = 0; i < map.length; i++)
0126: map[i] = i;
0127:
0128: for (int i = 0; i < ret.length; i++) {
0129: int index = i;
0130: for (int j = i + 1; j < ret.length; j++) {
0131: if (orig[map[index]] > orig[map[j]]) {
0132: index = j;
0133: }
0134: }
0135: ret[map[index]] = i * step;
0136: map[index] = map[i];
0137: }
0138: return ret;
0139: }
0140:
0141: /**
0142: * Creates a new <code>ComponentSampleModel</code> with the specified
0143: * width and height. The new <code>SampleModel</code> will have the same
0144: * number of bands, storage data type, interleaving scheme, and
0145: * pixel stride as this <code>SampleModel</code>.
0146: *
0147: * @param w The width in pixels.
0148: * @param h The height in pixels
0149: */
0150: public SampleModel createCompatibleSampleModel(int w, int h) {
0151: SampleModel ret = null;
0152: long size;
0153: int minBandOff = bandOffsets[0];
0154: int maxBandOff = bandOffsets[0];
0155: for (int i = 1; i < bandOffsets.length; i++) {
0156: minBandOff = Math.min(minBandOff, bandOffsets[i]);
0157: maxBandOff = Math.max(maxBandOff, bandOffsets[i]);
0158: }
0159: maxBandOff -= minBandOff;
0160:
0161: int bands = bandOffsets.length;
0162: int bandOff[];
0163: int pStride = Math.abs(pixelStride);
0164: int lStride = Math.abs(scanlineStride);
0165: int bStride = Math.abs(maxBandOff);
0166:
0167: if (pStride > lStride) {
0168: if (pStride > bStride) {
0169: if (lStride > bStride) { // pix > line > band
0170: bandOff = new int[bandOffsets.length];
0171: for (int i = 0; i < bands; i++)
0172: bandOff[i] = bandOffsets[i] - minBandOff;
0173: lStride = bStride + 1;
0174: pStride = lStride * h;
0175: } else { // pix > band > line
0176: bandOff = JAIorderBands(bandOffsets, lStride * h);
0177: pStride = bands * lStride * h;
0178: }
0179: } else { // band > pix > line
0180: pStride = lStride * h;
0181: bandOff = JAIorderBands(bandOffsets, pStride * w);
0182: }
0183: } else {
0184: if (pStride > bStride) { // line > pix > band
0185: bandOff = new int[bandOffsets.length];
0186: for (int i = 0; i < bands; i++)
0187: bandOff[i] = bandOffsets[i] - minBandOff;
0188: pStride = bStride + 1;
0189: lStride = pStride * w;
0190: } else {
0191: if (lStride > bStride) { // line > band > pix
0192: bandOff = JAIorderBands(bandOffsets, pStride * w);
0193: lStride = bands * pStride * w;
0194: } else { // band > line > pix
0195: lStride = pStride * w;
0196: bandOff = JAIorderBands(bandOffsets, lStride * h);
0197: }
0198: }
0199: }
0200:
0201: // make sure we make room for negative offsets...
0202: int base = 0;
0203: if (scanlineStride < 0) {
0204: base += lStride * h;
0205: lStride *= -1;
0206: }
0207: if (pixelStride < 0) {
0208: base += pStride * w;
0209: pStride *= -1;
0210: }
0211:
0212: for (int i = 0; i < bands; i++)
0213: bandOff[i] += base;
0214: return new ComponentSampleModelJAI(dataType, w, h, pStride,
0215: lStride, bankIndices, bandOff);
0216: }
0217:
0218: /**
0219: * This creates a new <code>ComponentSampleModel</code> with a subset of the bands
0220: * of this <code>ComponentSampleModel</code>. The new <code>ComponentSampleModel</code> can be
0221: * used with any <code>DataBuffer</code> that the existing <code>ComponentSampleModel</code>
0222: * can be used with. The new <code>ComponentSampleModel</code>/<code>DataBuffer</code>
0223: * combination will represent an image with a subset of the bands
0224: * of the original <code>ComponentSampleModel</code>/<code>DataBuffer</code> combination.
0225: *
0226: * @param bands subset of bands of this <code>ComponentSampleModel</code>
0227: */
0228: public SampleModel createSubsetSampleModel(int bands[]) {
0229: int newBankIndices[] = new int[bands.length];
0230: int newBandOffsets[] = new int[bands.length];
0231: for (int i = 0; i < bands.length; i++) {
0232: int b = bands[i];
0233: newBankIndices[i] = bankIndices[b];
0234: newBandOffsets[i] = bandOffsets[b];
0235: }
0236: return new ComponentSampleModelJAI(this .dataType, width,
0237: height, this .pixelStride, this .scanlineStride,
0238: newBankIndices, newBandOffsets);
0239: }
0240:
0241: /**
0242: * Creates a <code>DataBuffer</code> that corresponds to this <code>ComponentSampleModel</code>.
0243: * The <code>DataBuffer</code>'s data type, number of banks, and size
0244: * will be consistent with this <code>ComponentSampleModel</code>.
0245: */
0246: public DataBuffer createDataBuffer() {
0247: DataBuffer dataBuffer = null;
0248:
0249: int size = (int) getBufferSize();
0250: switch (dataType) {
0251: case DataBuffer.TYPE_BYTE:
0252: dataBuffer = new DataBufferByte(size, numBanks);
0253: break;
0254: case DataBuffer.TYPE_USHORT:
0255: dataBuffer = new DataBufferUShort(size, numBanks);
0256: break;
0257: case DataBuffer.TYPE_INT:
0258: dataBuffer = new DataBufferInt(size, numBanks);
0259: break;
0260: case DataBuffer.TYPE_SHORT:
0261: dataBuffer = new DataBufferShort(size, numBanks);
0262: break;
0263: case DataBuffer.TYPE_FLOAT:
0264: dataBuffer = DataBufferUtils.createDataBufferFloat(size,
0265: numBanks);
0266: break;
0267: case DataBuffer.TYPE_DOUBLE:
0268: dataBuffer = DataBufferUtils.createDataBufferDouble(size,
0269: numBanks);
0270: break;
0271: default:
0272: throw new RuntimeException(JaiI18N
0273: .getString("RasterFactory3"));
0274: }
0275:
0276: return dataBuffer;
0277: }
0278:
0279: /**
0280: * Returns data for a single pixel in a primitive array of type
0281: * TransferType. For a <code>ComponentSampleModel</code>, this will be the same
0282: * as the data type, and samples will be returned one per array
0283: * element. Generally, obj
0284: * should be passed in as null, so that the <code>Object</code> will be created
0285: * automatically and will be of the right primitive data type.
0286: * <p>
0287: * The following code illustrates transferring data for one pixel from
0288: * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
0289: * <code>ComponentSampleModel</code> <code>csm1</code>, to <code>DataBuffer</code> <code>db2</code>,
0290: * whose storage layout is described by
0291: * <code>ComponentSampleModel</code> <code>csm2</code>.
0292: * The transfer will generally be more efficient than using
0293: * getPixel/setPixel.
0294: * <pre>
0295: * ComponentSampleModel csm1, csm2;
0296: * DataBufferInt db1, db2;
0297: * csm2.setDataElements(x, y,
0298: * csm1.getDataElements(x, y, null, db1), db2);
0299: * </pre>
0300: * Using getDataElements/setDataElements to transfer between two
0301: * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
0302: * the same number of bands, corresponding bands have the same number of
0303: * bits per sample, and the TransferTypes are the same.
0304: * <p>
0305: * @param x The X coordinate of the pixel location.
0306: * @param y The Y coordinate of the pixel location.
0307: * @param obj If non-null, a primitive array in which to return
0308: * the pixel data.
0309: * @param data The <code>DataBuffer</code> containing the image data.
0310: * @throws <code>ClassCastException</code> if obj is non-null and is not
0311: * a primitive array of type TransferType.
0312: * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
0313: * are not in bounds, or if obj is non-null and is not large
0314: * enough to hold the pixel data.
0315: */
0316: public Object getDataElements(int x, int y, Object obj,
0317: DataBuffer data) {
0318:
0319: int type = getTransferType();
0320: int numDataElems = getNumDataElements();
0321: int pixelOffset = y * scanlineStride + x * pixelStride;
0322:
0323: switch (type) {
0324:
0325: case DataBuffer.TYPE_BYTE:
0326:
0327: byte[] bdata;
0328:
0329: if (obj == null)
0330: bdata = new byte[numDataElems];
0331: else
0332: bdata = (byte[]) obj;
0333:
0334: for (int i = 0; i < numDataElems; i++) {
0335: bdata[i] = (byte) data.getElem(bankIndices[i],
0336: pixelOffset + bandOffsets[i]);
0337: }
0338:
0339: obj = (Object) bdata;
0340: break;
0341:
0342: case DataBuffer.TYPE_USHORT:
0343:
0344: short[] usdata;
0345:
0346: if (obj == null)
0347: usdata = new short[numDataElems];
0348: else
0349: usdata = (short[]) obj;
0350:
0351: for (int i = 0; i < numDataElems; i++) {
0352: usdata[i] = (short) data.getElem(bankIndices[i],
0353: pixelOffset + bandOffsets[i]);
0354: }
0355:
0356: obj = (Object) usdata;
0357: break;
0358:
0359: case DataBuffer.TYPE_INT:
0360:
0361: int[] idata;
0362:
0363: if (obj == null)
0364: idata = new int[numDataElems];
0365: else
0366: idata = (int[]) obj;
0367:
0368: for (int i = 0; i < numDataElems; i++) {
0369: idata[i] = data.getElem(bankIndices[i], pixelOffset
0370: + bandOffsets[i]);
0371: }
0372:
0373: obj = (Object) idata;
0374: break;
0375:
0376: case DataBuffer.TYPE_SHORT:
0377:
0378: short[] sdata;
0379:
0380: if (obj == null)
0381: sdata = new short[numDataElems];
0382: else
0383: sdata = (short[]) obj;
0384:
0385: for (int i = 0; i < numDataElems; i++) {
0386: sdata[i] = (short) data.getElem(bankIndices[i],
0387: pixelOffset + bandOffsets[i]);
0388: }
0389:
0390: obj = (Object) sdata;
0391: break;
0392:
0393: case DataBuffer.TYPE_FLOAT:
0394:
0395: float[] fdata;
0396:
0397: if (obj == null)
0398: fdata = new float[numDataElems];
0399: else
0400: fdata = (float[]) obj;
0401:
0402: for (int i = 0; i < numDataElems; i++) {
0403: fdata[i] = data.getElemFloat(bankIndices[i],
0404: pixelOffset + bandOffsets[i]);
0405: }
0406:
0407: obj = (Object) fdata;
0408: break;
0409:
0410: case DataBuffer.TYPE_DOUBLE:
0411:
0412: double[] ddata;
0413:
0414: if (obj == null)
0415: ddata = new double[numDataElems];
0416: else
0417: ddata = (double[]) obj;
0418:
0419: for (int i = 0; i < numDataElems; i++) {
0420: ddata[i] = data.getElemDouble(bankIndices[i],
0421: pixelOffset + bandOffsets[i]);
0422: }
0423:
0424: obj = (Object) ddata;
0425: break;
0426:
0427: default:
0428: throw new RuntimeException(JaiI18N
0429: .getString("RasterFactory3"));
0430:
0431: }
0432:
0433: return obj;
0434: }
0435:
0436: /**
0437: * Returns the pixel data for the specified rectangle of pixels in a
0438: * primitive array of type TransferType.
0439: * For image data supported by the Java 2D API, this
0440: * will be one of the dataTypes supported by java.awt.image.DataBuffer.
0441: * Data may be returned in a packed format, thus increasing efficiency
0442: * for data transfers. Generally, obj should be passed in as null, so
0443: * that the <code>Object</code> will be created automatically and will be of the right
0444: * primitive data type.
0445: * <p>
0446: * The following code illustrates transferring data for a rectangular
0447: * region of pixels from
0448: * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
0449: * <code>SampleModel</code> <code>sm1</code>, to <code>DataBuffer</code> <code>db2</code>, whose
0450: * storage layout is described by <code>SampleModel</code> <code>sm2</code>.
0451: * The transfer will generally be more efficient than using
0452: * getPixels/setPixels.
0453: * <pre>
0454: * SampleModel sm1, sm2;
0455: * DataBuffer db1, db2;
0456: * sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w,
0457: * h, null, db1), db2);
0458: * </pre>
0459: * Using getDataElements/setDataElements to transfer between two
0460: * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
0461: * the same number of bands, corresponding bands have the same number of
0462: * bits per sample, and the TransferTypes are the same.
0463: * <p>
0464: * @param x The minimum X coordinate of the pixel rectangle.
0465: * @param y The minimum Y coordinate of the pixel rectangle.
0466: * @param w The width of the pixel rectangle.
0467: * @param h The height of the pixel rectangle.
0468: * @param obj If non-null, a primitive array in which to return
0469: * the pixel data.
0470: * @param data The <code>DataBuffer</code> containing the image data.
0471: * @see #getNumDataElements
0472: * @see #getTransferType
0473: * @see java.awt.image.DataBuffer
0474: * @throws <code>ClassCastException</code> if obj is non-null and is not
0475: * a primitive array of type TransferType.
0476: * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
0477: * are not in bounds, or if obj is non-null and is not large
0478: * enough to hold the pixel data.
0479: */
0480: public Object getDataElements(int x, int y, int w, int h,
0481: Object obj, DataBuffer data) {
0482:
0483: int type = getTransferType();
0484: int numDataElems = getNumDataElements();
0485: int cnt = 0;
0486: Object o = null;
0487:
0488: switch (type) {
0489:
0490: case DataBuffer.TYPE_BYTE: {
0491: byte[] btemp;
0492: byte[] bdata;
0493:
0494: if (obj == null)
0495: bdata = new byte[numDataElems * w * h];
0496: else
0497: bdata = (byte[]) obj;
0498:
0499: for (int i = y; i < y + h; i++) {
0500: for (int j = x; j < x + w; j++) {
0501: o = getDataElements(j, i, o, data);
0502: btemp = (byte[]) o;
0503: for (int k = 0; k < numDataElems; k++) {
0504: bdata[cnt++] = btemp[k];
0505: }
0506: }
0507: }
0508: obj = (Object) bdata;
0509: break;
0510: }
0511:
0512: case DataBuffer.TYPE_USHORT: {
0513:
0514: short[] usdata;
0515: short[] ustemp;
0516:
0517: if (obj == null)
0518: usdata = new short[numDataElems * w * h];
0519: else
0520: usdata = (short[]) obj;
0521:
0522: for (int i = y; i < y + h; i++) {
0523: for (int j = x; j < x + w; j++) {
0524: o = getDataElements(j, i, o, data);
0525: ustemp = (short[]) o;
0526: for (int k = 0; k < numDataElems; k++) {
0527: usdata[cnt++] = ustemp[k];
0528: }
0529: }
0530: }
0531:
0532: obj = (Object) usdata;
0533: break;
0534: }
0535:
0536: case DataBuffer.TYPE_INT: {
0537:
0538: int[] idata;
0539: int[] itemp;
0540:
0541: if (obj == null)
0542: idata = new int[numDataElems * w * h];
0543: else
0544: idata = (int[]) obj;
0545:
0546: for (int i = y; i < y + h; i++) {
0547: for (int j = x; j < x + w; j++) {
0548: o = getDataElements(j, i, o, data);
0549: itemp = (int[]) o;
0550: for (int k = 0; k < numDataElems; k++) {
0551: idata[cnt++] = itemp[k];
0552: }
0553: }
0554: }
0555:
0556: obj = (Object) idata;
0557: break;
0558: }
0559:
0560: case DataBuffer.TYPE_SHORT: {
0561:
0562: short[] sdata;
0563: short[] stemp;
0564:
0565: if (obj == null)
0566: sdata = new short[numDataElems * w * h];
0567: else
0568: sdata = (short[]) obj;
0569:
0570: for (int i = y; i < y + h; i++) {
0571: for (int j = x; j < x + w; j++) {
0572: o = getDataElements(j, i, o, data);
0573: stemp = (short[]) o;
0574: for (int k = 0; k < numDataElems; k++) {
0575: sdata[cnt++] = stemp[k];
0576: }
0577: }
0578: }
0579:
0580: obj = (Object) sdata;
0581: break;
0582: }
0583:
0584: case DataBuffer.TYPE_FLOAT: {
0585:
0586: float[] fdata;
0587: float[] ftemp;
0588:
0589: if (obj == null)
0590: fdata = new float[numDataElems * w * h];
0591: else
0592: fdata = (float[]) obj;
0593:
0594: for (int i = y; i < y + h; i++) {
0595: for (int j = x; j < x + w; j++) {
0596: o = getDataElements(j, i, o, data);
0597: ftemp = (float[]) o;
0598: for (int k = 0; k < numDataElems; k++) {
0599: fdata[cnt++] = ftemp[k];
0600: }
0601: }
0602: }
0603:
0604: obj = (Object) fdata;
0605: break;
0606: }
0607:
0608: case DataBuffer.TYPE_DOUBLE: {
0609:
0610: double[] ddata;
0611: double[] dtemp;
0612:
0613: if (obj == null)
0614: ddata = new double[numDataElems * w * h];
0615: else
0616: ddata = (double[]) obj;
0617:
0618: for (int i = y; i < y + h; i++) {
0619: for (int j = x; j < x + w; j++) {
0620: o = getDataElements(j, i, o, data);
0621: dtemp = (double[]) o;
0622: for (int k = 0; k < numDataElems; k++) {
0623: ddata[cnt++] = dtemp[k];
0624: }
0625: }
0626: }
0627:
0628: obj = (Object) ddata;
0629: break;
0630: }
0631:
0632: default:
0633: throw new RuntimeException(JaiI18N
0634: .getString("RasterFactory3"));
0635: }
0636:
0637: return obj;
0638: }
0639:
0640: /**
0641: * Sets the data for a single pixel in the specified <code>DataBuffer</code> from a
0642: * primitive array of type TransferType. For a <code>ComponentSampleModel</code>,
0643: * this will be the same as the data type, and samples are transferred
0644: * one per array element.
0645: * <p>
0646: * The following code illustrates transferring data for one pixel from
0647: * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
0648: * <code>ComponentSampleModel</code> <code>csm1</code>, to <code>DataBuffer</code> <code>db2</code>,
0649: * whose storage layout is described by
0650: * <code>ComponentSampleModel</code> <code>csm2</code>.
0651: * The transfer will generally be more efficient than using
0652: * getPixel/setPixel.
0653: * <pre>
0654: * ComponentSampleModel csm1, csm2;
0655: * DataBufferInt db1, db2;
0656: * csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
0657: * db2);
0658: * </pre>
0659: * Using getDataElements/setDataElements to transfer between two
0660: * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
0661: * the same number of bands, corresponding bands have the same number of
0662: * bits per sample, and the TransferTypes are the same.
0663: * <p>
0664: * @param x The X coordinate of the pixel location.
0665: * @param y The Y coordinate of the pixel location.
0666: * @param obj A primitive array containing pixel data.
0667: * @param data The <code>DataBuffer</code> containing the image data.
0668: * @throws <code>ClassCastException</code> if obj is non-null and is not
0669: * a primitive array of type TransferType.
0670: * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
0671: * are not in bounds, or if obj is non-null and is not large
0672: * enough to hold the pixel data.
0673: */
0674: public void setDataElements(int x, int y, Object obj,
0675: DataBuffer data) {
0676:
0677: int type = getTransferType();
0678: int numDataElems = getNumDataElements();
0679: int pixelOffset = y * scanlineStride + x * pixelStride;
0680:
0681: switch (type) {
0682:
0683: case DataBuffer.TYPE_BYTE:
0684:
0685: byte[] barray = (byte[]) obj;
0686:
0687: for (int i = 0; i < numDataElems; i++) {
0688: data.setElem(bankIndices[i], pixelOffset
0689: + bandOffsets[i], ((int) barray[i]) & 0xff);
0690: }
0691: break;
0692:
0693: case DataBuffer.TYPE_USHORT:
0694:
0695: short[] usarray = (short[]) obj;
0696:
0697: for (int i = 0; i < numDataElems; i++) {
0698: data.setElem(bankIndices[i], pixelOffset
0699: + bandOffsets[i], ((int) usarray[i]) & 0xffff);
0700: }
0701: break;
0702:
0703: case DataBuffer.TYPE_INT:
0704:
0705: int[] iarray = (int[]) obj;
0706:
0707: for (int i = 0; i < numDataElems; i++) {
0708: data.setElem(bankIndices[i], pixelOffset
0709: + bandOffsets[i], iarray[i]);
0710: }
0711: break;
0712:
0713: case DataBuffer.TYPE_SHORT:
0714:
0715: short[] sarray = (short[]) obj;
0716:
0717: for (int i = 0; i < numDataElems; i++) {
0718: data.setElem(bankIndices[i], pixelOffset
0719: + bandOffsets[i], sarray[i]);
0720: }
0721: break;
0722:
0723: case DataBuffer.TYPE_FLOAT:
0724:
0725: float[] farray = (float[]) obj;
0726:
0727: for (int i = 0; i < numDataElems; i++) {
0728: data.setElemFloat(bankIndices[i], pixelOffset
0729: + bandOffsets[i], farray[i]);
0730: }
0731: break;
0732:
0733: case DataBuffer.TYPE_DOUBLE:
0734:
0735: double[] darray = (double[]) obj;
0736:
0737: for (int i = 0; i < numDataElems; i++) {
0738: data.setElemDouble(bankIndices[i], pixelOffset
0739: + bandOffsets[i], darray[i]);
0740: }
0741: break;
0742:
0743: default:
0744: throw new RuntimeException(JaiI18N
0745: .getString("RasterFactory3"));
0746: }
0747: }
0748:
0749: /**
0750: * Sets the data for a rectangle of pixels in the specified <code>DataBuffer</code>
0751: * from a primitive array of type TransferType. For image data supported
0752: * by the Java 2D API, this will be one of the dataTypes supported by
0753: * java.awt.image.DataBuffer. Data in the array may be in a packed
0754: * format, thus increasing efficiency for data transfers.
0755: * <p>
0756: * The following code illustrates transferring data for a rectangular
0757: * region of pixels from
0758: * <code>DataBuffer</code> <code>db1</code>, whose storage layout is described by
0759: * <code>SampleModel</code> <code>sm1</code>, to <code>DataBuffer</code> <code>db2</code>, whose
0760: * storage layout is described by <code>SampleModel</code> <code>sm2</code>.
0761: * The transfer will generally be more efficient than using
0762: * getPixels/setPixels.
0763: * <pre>
0764: * SampleModel sm1, sm2;
0765: * DataBuffer db1, db2;
0766: * sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h,
0767: * null, db1), db2);
0768: * </pre>
0769: * Using getDataElements/setDataElements to transfer between two
0770: * <code>DataBuffer</code>/SampleModel pairs is legitimate if the <code>SampleModel</code>s have
0771: * the same number of bands, corresponding bands have the same number of
0772: * bits per sample, and the TransferTypes are the same.
0773: * <p>
0774: * @param x The minimum X coordinate of the pixel rectangle.
0775: * @param y The minimum Y coordinate of the pixel rectangle.
0776: * @param w The width of the pixel rectangle.
0777: * @param h The height of the pixel rectangle.
0778: * @param obj A primitive array containing pixel data.
0779: * @param data The <code>DataBuffer</code> containing the image data.
0780: * @throws <code>ClassCastException</code> if obj is non-null and is not
0781: * a primitive array of type TransferType.
0782: * @throws <code>ArrayIndexOutOfBoundsException</code> if the coordinates
0783: * are not in bounds, or if obj is non-null and is not large
0784: * enough to hold the pixel data.
0785: * @see #getNumDataElements
0786: * @see #getTransferType
0787: * @see java.awt.image.DataBuffer
0788: */
0789: public void setDataElements(int x, int y, int w, int h, Object obj,
0790: DataBuffer data) {
0791: int cnt = 0;
0792: Object o = null;
0793: int type = getTransferType();
0794: int numDataElems = getNumDataElements();
0795:
0796: switch (type) {
0797:
0798: case DataBuffer.TYPE_BYTE: {
0799:
0800: byte[] barray = (byte[]) obj;
0801: byte[] btemp = new byte[numDataElems];
0802:
0803: for (int i = y; i < y + h; i++) {
0804: for (int j = x; j < x + w; j++) {
0805: for (int k = 0; k < numDataElems; k++) {
0806: btemp[k] = barray[cnt++];
0807: }
0808:
0809: setDataElements(j, i, btemp, data);
0810: }
0811: }
0812: break;
0813: }
0814:
0815: case DataBuffer.TYPE_USHORT: {
0816:
0817: short[] usarray = (short[]) obj;
0818: short[] ustemp = new short[numDataElems];
0819:
0820: for (int i = y; i < y + h; i++) {
0821: for (int j = x; j < x + w; j++) {
0822: for (int k = 0; k < numDataElems; k++) {
0823: ustemp[k] = usarray[cnt++];
0824: }
0825: setDataElements(j, i, ustemp, data);
0826: }
0827: }
0828: break;
0829: }
0830:
0831: case DataBuffer.TYPE_INT: {
0832:
0833: int[] iArray = (int[]) obj;
0834: int[] itemp = new int[numDataElems];
0835:
0836: for (int i = y; i < y + h; i++) {
0837: for (int j = x; j < x + w; j++) {
0838: for (int k = 0; k < numDataElems; k++) {
0839: itemp[k] = iArray[cnt++];
0840: }
0841:
0842: setDataElements(j, i, itemp, data);
0843: }
0844: }
0845: break;
0846: }
0847:
0848: case DataBuffer.TYPE_SHORT: {
0849:
0850: short[] sArray = (short[]) obj;
0851: short[] stemp = new short[numDataElems];
0852:
0853: for (int i = y; i < y + h; i++) {
0854: for (int j = x; j < x + w; j++) {
0855: for (int k = 0; k < numDataElems; k++) {
0856: stemp[k] = sArray[cnt++];
0857: }
0858:
0859: setDataElements(j, i, stemp, data);
0860: }
0861: }
0862: break;
0863: }
0864:
0865: case DataBuffer.TYPE_FLOAT: {
0866:
0867: float[] fArray = (float[]) obj;
0868: float[] ftemp = new float[numDataElems];
0869:
0870: for (int i = y; i < y + h; i++) {
0871: for (int j = x; j < x + w; j++) {
0872: for (int k = 0; k < numDataElems; k++) {
0873: ftemp[k] = fArray[cnt++];
0874: }
0875:
0876: setDataElements(j, i, ftemp, data);
0877: }
0878: }
0879: break;
0880: }
0881:
0882: case DataBuffer.TYPE_DOUBLE: {
0883:
0884: double[] dArray = (double[]) obj;
0885: double[] dtemp = new double[numDataElems];
0886:
0887: for (int i = y; i < y + h; i++) {
0888: for (int j = x; j < x + w; j++) {
0889: for (int k = 0; k < numDataElems; k++) {
0890: dtemp[k] = dArray[cnt++];
0891: }
0892:
0893: setDataElements(j, i, dtemp, data);
0894: }
0895: }
0896: break;
0897: }
0898:
0899: default:
0900: throw new RuntimeException(JaiI18N
0901: .getString("RasterFactory3"));
0902: }
0903: }
0904:
0905: /**
0906: * Sets a sample in the specified band for the pixel located at (x,y)
0907: * in the <code>DataBuffer</code> using a <code>float</code> for input.
0908: * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
0909: * not in bounds.
0910: * @param x The X coordinate of the pixel location.
0911: * @param y The Y coordinate of the pixel location.
0912: * @param b The band to set.
0913: * @param s The input sample as a <code>float</code>.
0914: * @param data The <code>DataBuffer</code> containing the image data.
0915: *
0916: * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
0917: */
0918: public void setSample(int x, int y, int b, float s, DataBuffer data) {
0919: data.setElemFloat(bankIndices[b], y * scanlineStride + x
0920: * pixelStride + bandOffsets[b], s);
0921: }
0922:
0923: /**
0924: * Returns the sample in a specified band
0925: * for the pixel located at (x,y) as a <code>float</code>.
0926: * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
0927: * not in bounds.
0928: * @param x The X coordinate of the pixel location.
0929: * @param y The Y coordinate of the pixel location.
0930: * @param b The band to return.
0931: * @param data The <code>DataBuffer</code> containing the image data.
0932: * @return sample The floating point sample value
0933: * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
0934: */
0935: public float getSampleFloat(int x, int y, int b, DataBuffer data) {
0936: float sample = data.getElemFloat(bankIndices[b], y
0937: * scanlineStride + x * pixelStride + bandOffsets[b]);
0938: return sample;
0939: }
0940:
0941: /**
0942: * Sets a sample in the specified band for the pixel located at (x,y)
0943: * in the <code>DataBuffer</code> using a <code>double</code> for input.
0944: * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
0945: * not in bounds.
0946: * @param x The X coordinate of the pixel location.
0947: * @param y The Y coordinate of the pixel location.
0948: * @param b The band to set.
0949: * @param s The input sample as a <code>double</code>.
0950: * @param data The <code>DataBuffer</code> containing the image data.
0951: *
0952: * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
0953: */
0954: public void setSample(int x, int y, int b, double s, DataBuffer data) {
0955: data.setElemDouble(bankIndices[b], y * scanlineStride + x
0956: * pixelStride + bandOffsets[b], s);
0957: }
0958:
0959: /**
0960: * Returns the sample in a specified band
0961: * for a pixel located at (x,y) as a <code>double</code>.
0962: * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
0963: * not in bounds.
0964: * @param x The X coordinate of the pixel location.
0965: * @param y The Y coordinate of the pixel location.
0966: * @param b The band to return.
0967: * @param data The <code>DataBuffer</code> containing the image data.
0968: * @return sample The <code>double</code> sample value
0969: * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
0970: */
0971: public double getSampleDouble(int x, int y, int b, DataBuffer data) {
0972: double sample = data.getElemDouble(bankIndices[b], y
0973: * scanlineStride + x * pixelStride + bandOffsets[b]);
0974: return sample;
0975: }
0976:
0977: /**
0978: * Returns all samples for a rectangle of pixels in a <code>double</code>
0979: * array, one sample per array element.
0980: * <code>ArrayIndexOutOfBoundsException</code> may be thrown if the coordinates are
0981: * not in bounds.
0982: * @param x The X coordinate of the upper left pixel location.
0983: * @param y The Y coordinate of the upper left pixel location.
0984: * @param w The width of the pixel rectangle.
0985: * @param h The height of the pixel rectangle.
0986: * @param dArray If non-null, returns the samples in this array.
0987: * @param data The <code>DataBuffer</code> containing the image data.
0988: * @throws <code>ArrayIndexOutOfBoundsException</code> if coordinates are not in bounds
0989: */
0990: public double[] getPixels(int x, int y, int w, int h,
0991: double dArray[], DataBuffer data) {
0992: double pixels[];
0993: int Offset = 0;
0994:
0995: if (dArray != null)
0996: pixels = dArray;
0997: else
0998: pixels = new double[numBands * w * h];
0999:
1000: for (int i = y; i < (h + y); i++) {
1001: for (int j = x; j < (w + x); j++) {
1002: for (int k = 0; k < numBands; k++) {
1003: pixels[Offset++] = getSampleDouble(j, i, k, data);
1004: }
1005: }
1006: }
1007:
1008: return pixels;
1009: }
1010:
1011: /** Returns a <code>String</code> containing the values of all valid fields. */
1012: public String toString() {
1013: String ret = "ComponentSampleModelJAI: " + " dataType="
1014: + this .getDataType() + " numBands="
1015: + this .getNumBands() + " width=" + this .getWidth()
1016: + " height=" + this .getHeight() + " bandOffsets=[ ";
1017: for (int i = 0; i < numBands; i++) {
1018: ret += this .getBandOffsets()[i] + " ";
1019: }
1020: ret += "]";
1021: return ret;
1022: }
1023: }
|