001: /*
002: * $RCSfile: RasterFormatTag.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:57:18 $
010: * $State: Exp $
011: */
012: package javax.media.jai;
013:
014: import java.awt.image.SampleModel;
015: import java.awt.image.ComponentSampleModel;
016: import java.awt.Rectangle;
017:
018: /**
019: * This class encapsulates the information needed for
020: * RasterAccessor to understand how a Raster is laid out. It's
021: * designed so that one RasterFormatTag can be constructed per
022: * source and that RasterFormatTag can cache information that
023: * the RasterAccessor would otherwise have to extract from the
024: * Raster each time it's constructed (generally each time
025: * OpImage.computeRect() is called.) Additionally, it can
026: * cache various arrays (i.e. bankIndices[] and bandOffsets[])
027: * that would otherwise be cloned everytime they were requested.
028: *
029: * Because of the way SampleModel.createCompatibleSampleModel()
030: * is designed not all fields of a particular SampleModel will
031: * match those of the SampleModel returned by
032: * SampleModel.createCompatibleSampleModel(). Values like
033: * pixelStride and numBands won't change, but values like
034: * bankIndicies[] and bandOffsets[] might if the underlying
035: * Raster is not pixelSequential. Rasters which are pixelSequential
036: * meet the following conditions 1) The SampleModel is a
037: * ComponentSampleModel. 2) The pixelStride is equal to the number
038: * of bands. 3) All the bankIndices[] are equal. 4) All the
039: * bandOffsets[] values are less than pixelStride 5) No two
040: * bandOffsets[] values are equal. For that reason,
041: * RasterFormatTags representing non pixelSequential rasters don't
042: * attempt to cache the bandOffsets[] or bankIndices[]. For such
043: * rasters, this information should be taken directly from the
044: * raster itself. Note that any RasterFormatTag that will cause
045: * data to be copied from the Raster will be pixelSequential as that
046: * is the format in which data is returned from Raster.getPixels()
047: * returns.
048: *
049: */
050: public final class RasterFormatTag {
051:
052: private static final int COPY_MASK = RasterAccessor.COPY_MASK;
053: private static final int UNCOPIED = RasterAccessor.UNCOPIED;
054: private static final int COPIED = RasterAccessor.COPIED;
055:
056: private int formatTagID;
057: private int bankIndices[];
058: private int numBands;
059: private int bandOffsets[];
060: private int pixelStride;
061:
062: private boolean isPixelSequential;
063:
064: /**
065: * Constructs a RasterFormatTag given a sampleModel and a
066: * formatTagID. Generally, this constructor is called by
067: * RasterAccessor.findCompatibleTags(RenderedImage[] srcs,
068: * RenderedImage dst) and it takes care of setting the values
069: * correctly. In special cases, OpImages need to construct
070: * a RasterFormatTag without creating a RenderedImage. In this
071: * case a RasterFormatTag can be created using a formatTagID
072: * returned from
073: * RasterAccessor.findCompatibleTag(SampleModel[] srcs, SampleModel dst)
074: * and a sampleModel that was either passed in to the
075: * findCompatibleTag() call or one that was created using
076: * createCompatibleSampleModel() on one of the passed in
077: * SampleModels. Attempting to use arbitrary SampleModels
078: * with arbitrary formatTagIDs has undefined results.
079: *
080: * param sampleModel A <code>SampleModel</code> for the RasterFormagTag
081: * param formatTagID An <code>int</code> to indicate format tag id
082: *
083: */
084: public RasterFormatTag(SampleModel sampleModel, int formatTagID) {
085: this .formatTagID = formatTagID;
086: if ((formatTagID & COPY_MASK) == UNCOPIED) {
087: ComponentSampleModel csm = (ComponentSampleModel) sampleModel;
088: this .bankIndices = csm.getBankIndices();
089: this .numBands = csm.getNumDataElements();
090: this .bandOffsets = csm.getBandOffsets();
091: this .pixelStride = csm.getPixelStride();
092:
093: if (pixelStride != bandOffsets.length) {
094: isPixelSequential = false;
095: } else {
096: isPixelSequential = true;
097: for (int i = 0; i < bandOffsets.length; i++) {
098: if (bandOffsets[i] >= pixelStride
099: || bankIndices[i] != bankIndices[0]) {
100: isPixelSequential = false;
101: }
102: for (int j = i + 1; j < bandOffsets.length; j++) {
103: if (bandOffsets[i] == bandOffsets[j]) {
104: isPixelSequential = false;
105: }
106: }
107: if (!isPixelSequential)
108: break;
109: }
110: }
111: } else if ((formatTagID & COPY_MASK) == COPIED) {
112: numBands = sampleModel.getNumBands();
113: bandOffsets = new int[numBands];
114: pixelStride = numBands;
115: bankIndices = new int[numBands];
116:
117: for (int i = 0; i < numBands; i++) {
118: bandOffsets[i] = i;
119: bankIndices[i] = 0;
120: }
121: isPixelSequential = true;
122: }
123: }
124:
125: /**
126: * Returns whether or not the SampleModel represented by the
127: * RasterFormatTag is PixelSequential.
128: * Note that RasterFormatTag's that indicate
129: * data should be copied out of the Raster by the RasterAccessor
130: * will always return true for isPixelSequential().
131: * RasterFormatTags that indicate no copying is needed will only
132: * return true, if 1) The SampleModel is a ComponentSampleModel.
133: * 2) The pixelStride is equal to the number of bands.
134: * 3) All the bankIndices[] are equal. 4) All the bandOffsets[]
135: * values are less than pixelStride 5) No two bandOffset values
136: * are equal.
137: */
138: public final boolean isPixelSequential() {
139: return isPixelSequential;
140: }
141:
142: /**
143: * Returns the FormatTagID used to construct this RasterFormatTag.
144: * Valid values are defined in javax.media.jai.RasterAccessor.
145: */
146: public final int getFormatTagID() {
147: return formatTagID;
148: }
149:
150: /**
151: * Returns the bankIndices for the Raster if isPixelSequential()
152: * is true. Returns null otherwise. In the COPIED case, the
153: * bankIndices will all be 0.
154: */
155: public final int[] getBankIndices() {
156: if (isPixelSequential) {
157: return bankIndices;
158: } else {
159: return null;
160: }
161: }
162:
163: /** Returns the number of bands in the underlying Raster */
164: public final int getNumBands() {
165: return numBands;
166: }
167:
168: /**
169: * Returns the bandOffsets for the Raster if isPixelSequential() is
170: * true. Returns null otherwise. In the COPIED case, bankIndices
171: * will be numBands sequential integers starting with 0.
172: */
173: public final int[] getBandOffsets() {
174: if (isPixelSequential) {
175: return bandOffsets;
176: } else {
177: return null;
178: }
179: }
180:
181: /** Returns the pixelStride of the underlying Raster */
182: public final int getPixelStride() {
183: return pixelStride;
184: }
185: }
|