001: /*
002: * $RCSfile: BandSelectOpImage.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:15 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Point;
015: import java.awt.Rectangle;
016: import java.awt.image.ColorModel;
017: import java.awt.image.ComponentSampleModel;
018: import java.awt.image.DataBuffer;
019: import java.awt.image.PixelInterleavedSampleModel;
020: import java.awt.image.Raster;
021: import java.awt.image.RenderedImage;
022: import java.awt.image.SampleModel;
023: import java.awt.image.SinglePixelPackedSampleModel;
024: import java.awt.image.WritableRaster;
025: import java.util.Map;
026: import javax.media.jai.ImageLayout;
027: import javax.media.jai.PointOpImage;
028: import com.sun.media.jai.util.JDKWorkarounds;
029:
030: /**
031: * An <code>OpImage</code> implementing the "BandSelect" operation.
032: *
033: * <p>This <code>OpImage</code> copies the specified bands of the source
034: * image to the destination image in the order that is specified.
035: *
036: * @see javax.media.jai.operator.BandSelectDescriptor
037: * @see BandSelectCRIF
038: *
039: *
040: * @since EA2
041: */
042: final class BandSelectOpImage extends PointOpImage {
043:
044: // Set if the source has a SinglePixelPackedSampleModel and
045: // bandIndices.length < 3.
046: private boolean areDataCopied;
047:
048: private int[] bandIndices;
049:
050: private static ImageLayout layoutHelper(ImageLayout layout,
051: RenderedImage source, int[] bandIndices) {
052: ImageLayout il = layout == null ? new ImageLayout()
053: : (ImageLayout) layout.clone();
054:
055: // Create a sub-banded SampleModel.
056: SampleModel sourceSM = source.getSampleModel();
057: int numBands = bandIndices.length;
058:
059: // The only ColorModel compatible with a SinglePixelPackedSampleModel
060: // in the J2SE is a DirectColorModel which is by definition of
061: // ColorSpace.TYPE_RGB. Therefore if there are fewer than 3 bands
062: // a data copy is obligatory if a ColorModel will be possible.
063: SampleModel sm = null;
064: if (sourceSM instanceof SinglePixelPackedSampleModel
065: && numBands < 3) {
066: sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
067: sourceSM.getWidth(), sourceSM.getHeight(),
068: numBands, sourceSM.getWidth() * numBands,
069: numBands == 1 ? new int[] { 0 }
070: : new int[] { 0, 1 });
071: } else {
072: sm = sourceSM.createSubsetSampleModel(bandIndices);
073: }
074: il.setSampleModel(sm);
075:
076: // Clear the ColorModel mask if needed.
077: ColorModel cm = il.getColorModel(null);
078: if (cm != null
079: && !JDKWorkarounds.areCompatibleDataModels(sm, cm)) {
080: // Clear the mask bit if incompatible.
081: il.unsetValid(ImageLayout.COLOR_MODEL_MASK);
082: }
083:
084: // Force the tile grid to be identical to that of the source.
085: il.setTileGridXOffset(source.getTileGridXOffset());
086: il.setTileGridYOffset(source.getTileGridYOffset());
087: il.setTileWidth(source.getTileWidth());
088: il.setTileHeight(source.getTileHeight());
089:
090: return il;
091: }
092:
093: /**
094: * Constructor.
095: *
096: * @param source The source image.
097: * @param layout The destination image layout.
098: * @param bandIndices The selected band indices of the source.
099: * The number of bands of the destination is
100: * determined by <code>bandIndices.length</code>.
101: */
102: public BandSelectOpImage(RenderedImage source, Map config,
103: ImageLayout layout, int[] bandIndices) {
104: super (vectorize(source), layoutHelper(layout, source,
105: bandIndices), config, true);
106:
107: this .areDataCopied = source.getSampleModel() instanceof SinglePixelPackedSampleModel
108: && bandIndices.length < 3;
109: this .bandIndices = (int[]) bandIndices.clone();
110: }
111:
112: public boolean computesUniqueTiles() {
113: return areDataCopied;
114: }
115:
116: public Raster computeTile(int tileX, int tileY) {
117: Raster tile = getSourceImage(0).getTile(tileX, tileY);
118:
119: if (areDataCopied) {
120: // Copy the data as there is no concrete ColorModel for
121: // a SinglePixelPackedSampleModel with numBands < 3.
122: tile = tile.createChild(tile.getMinX(), tile.getMinY(),
123: tile.getWidth(), tile.getHeight(), tile.getMinX(),
124: tile.getMinY(), bandIndices);
125: WritableRaster raster = createTile(tileX, tileY);
126: raster.setRect(tile);
127:
128: return raster;
129: } else {
130: // Simply return a child of the corresponding source tile.
131: return tile.createChild(tile.getMinX(), tile.getMinY(),
132: tile.getWidth(), tile.getHeight(), tile.getMinX(),
133: tile.getMinY(), bandIndices);
134: }
135: }
136:
137: public Raster getTile(int tileX, int tileY) {
138: // Just to return computeTile() result so as to avoid caching.
139: return computeTile(tileX, tileY);
140: }
141: }
|