001: /*
002: * $RCSfile: XorConstOpImage.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:48 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import javax.media.jai.ColormapOpImage;
015: import com.sun.media.jai.util.ImageUtil;
016: import java.awt.Rectangle;
017: import java.awt.image.DataBuffer;
018: import java.awt.image.Raster;
019: import java.awt.image.RenderedImage;
020: import java.awt.image.WritableRaster;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.RasterAccessor;
023: import javax.media.jai.RasterFormatTag;
024: import java.util.Map;
025:
026: /**
027: * An <code>OpImage</code> implementing the "XorConst" operation.
028: *
029: * <p>This <code>OpImage</code> logically "xors" the pixels of a rendered
030: * image with a set of constants, one for each band of the source image.
031: * The destination pixel values are calculated as:
032: * <pre>
033: * for (int h = 0; h < dstHeight; h++) {
034: * for (int w = 0; w < dstWidth; w++) {
035: * for (int b = 0; b < dstNumBands; b++) {
036: * if (constants.length < dstNumBands) {
037: * dst[h][w][b] = srcs[h][w][b] ^ constants[0];
038: * } else {
039: * dst[h][w][b] = srcs[h][w][b] ^ constants[b];
040: * }
041: * }
042: * }
043: * }
044: * </pre>
045: *
046: * @see javax.media.jai.operator.XorConstDescriptor
047: * @see XorConstCRIF
048: *
049: *
050: * @since EA2
051: */
052: final class XorConstOpImage extends ColormapOpImage {
053:
054: /** The constants to be xored, one for each band. */
055: protected int[] constants;
056:
057: /**
058: * Constructor.
059: *
060: * @param source The source image.
061: * @param layout The destination image layout.
062: * @param constants The constants to be xored, stored as reference.
063: */
064: public XorConstOpImage(RenderedImage source, Map config,
065: ImageLayout layout, int[] constants) {
066: super (source, layout, config, true);
067:
068: int numBands = getSampleModel().getNumBands();
069:
070: if (constants.length < numBands) {
071: this .constants = new int[numBands];
072: for (int i = 0; i < numBands; i++) {
073: this .constants[i] = constants[0];
074: }
075: } else {
076: this .constants = (int[]) constants.clone();
077: }
078:
079: // Set flag to permit in-place operation.
080: permitInPlaceOperation();
081:
082: // Initialize the colormap if necessary.
083: initializeColormapOperation();
084: }
085:
086: /**
087: * Transform the colormap according to the rescaling parameters.
088: */
089: protected void transformColormap(byte[][] colormap) {
090: for (int b = 0; b < 3; b++) {
091: byte[] map = colormap[b];
092: int mapSize = map.length;
093:
094: int c = b < constants.length ? constants[b] : constants[0];
095:
096: for (int i = 0; i < mapSize; i++) {
097: map[i] = ImageUtil.clampRoundByte((map[i] & 0xFF) ^ c);
098: }
099: }
100: }
101:
102: /**
103: * Logically "xors" a constant with the pixel values within a specified
104: * rectangle.
105: *
106: * @param sources Cobbled sources, guaranteed to provide all the
107: * source data necessary for computing the rectangle.
108: * @param dest The tile containing the rectangle to be computed.
109: * @param destRect The rectangle within the tile to be computed.
110: */
111: protected void computeRect(Raster[] sources, WritableRaster dest,
112: Rectangle destRect) {
113: // Retrieve format tags.
114: RasterFormatTag[] formatTags = getFormatTags();
115:
116: Rectangle srcRect = mapDestRect(destRect, 0);
117:
118: RasterAccessor dst = new RasterAccessor(dest, destRect,
119: formatTags[1], getColorModel());
120: RasterAccessor src = new RasterAccessor(sources[0], srcRect,
121: formatTags[0], getSource(0).getColorModel());
122:
123: switch (dst.getDataType()) {
124: case DataBuffer.TYPE_BYTE:
125: computeRectByte(src, dst);
126: break;
127: case DataBuffer.TYPE_USHORT:
128: case DataBuffer.TYPE_SHORT:
129: computeRectShort(src, dst);
130: break;
131: case DataBuffer.TYPE_INT:
132: computeRectInt(src, dst);
133: break;
134: }
135:
136: /* Do not clamp dst data. */
137: dst.copyDataToRaster();
138: }
139:
140: private void computeRectByte(RasterAccessor src, RasterAccessor dst) {
141: int dstWidth = dst.getWidth();
142: int dstHeight = dst.getHeight();
143: int dstBands = dst.getNumBands();
144:
145: int dstLineStride = dst.getScanlineStride();
146: int dstPixelStride = dst.getPixelStride();
147: int[] dstBandOffsets = dst.getBandOffsets();
148: byte[][] dstData = dst.getByteDataArrays();
149:
150: int srcLineStride = src.getScanlineStride();
151: int srcPixelStride = src.getPixelStride();
152: int[] srcBandOffsets = src.getBandOffsets();
153: byte[][] srcData = src.getByteDataArrays();
154:
155: for (int b = 0; b < dstBands; b++) {
156: int c = constants[b];
157: byte[] d = dstData[b];
158: byte[] s = srcData[b];
159:
160: int dstLineOffset = dstBandOffsets[b];
161: int srcLineOffset = srcBandOffsets[b];
162:
163: for (int h = 0; h < dstHeight; h++) {
164: int dstPixelOffset = dstLineOffset;
165: int srcPixelOffset = srcLineOffset;
166:
167: dstLineOffset += dstLineStride;
168: srcLineOffset += srcLineStride;
169:
170: for (int w = 0; w < dstWidth; w++) {
171: d[dstPixelOffset] = (byte) (s[srcPixelOffset] ^ c);
172:
173: dstPixelOffset += dstPixelStride;
174: srcPixelOffset += srcPixelStride;
175: }
176: }
177: }
178: }
179:
180: private void computeRectShort(RasterAccessor src, RasterAccessor dst) {
181: int dstWidth = dst.getWidth();
182: int dstHeight = dst.getHeight();
183: int dstBands = dst.getNumBands();
184:
185: int dstLineStride = dst.getScanlineStride();
186: int dstPixelStride = dst.getPixelStride();
187: int[] dstBandOffsets = dst.getBandOffsets();
188: short[][] dstData = dst.getShortDataArrays();
189:
190: int srcLineStride = src.getScanlineStride();
191: int srcPixelStride = src.getPixelStride();
192: int[] srcBandOffsets = src.getBandOffsets();
193: short[][] srcData = src.getShortDataArrays();
194:
195: for (int b = 0; b < dstBands; b++) {
196: int c = constants[b];
197: short[] d = dstData[b];
198: short[] s = srcData[b];
199:
200: int dstLineOffset = dstBandOffsets[b];
201: int srcLineOffset = srcBandOffsets[b];
202:
203: for (int h = 0; h < dstHeight; h++) {
204: int dstPixelOffset = dstLineOffset;
205: int srcPixelOffset = srcLineOffset;
206:
207: dstLineOffset += dstLineStride;
208: srcLineOffset += srcLineStride;
209:
210: for (int w = 0; w < dstWidth; w++) {
211: d[dstPixelOffset] = (short) (s[srcPixelOffset] ^ c);
212:
213: dstPixelOffset += dstPixelStride;
214: srcPixelOffset += srcPixelStride;
215: }
216: }
217: }
218: }
219:
220: private void computeRectInt(RasterAccessor src, RasterAccessor dst) {
221: int dstWidth = dst.getWidth();
222: int dstHeight = dst.getHeight();
223: int dstBands = dst.getNumBands();
224:
225: int dstLineStride = dst.getScanlineStride();
226: int dstPixelStride = dst.getPixelStride();
227: int[] dstBandOffsets = dst.getBandOffsets();
228: int[][] dstData = dst.getIntDataArrays();
229:
230: int srcLineStride = src.getScanlineStride();
231: int srcPixelStride = src.getPixelStride();
232: int[] srcBandOffsets = src.getBandOffsets();
233: int[][] srcData = src.getIntDataArrays();
234:
235: for (int b = 0; b < dstBands; b++) {
236: int c = constants[b];
237: int[] d = dstData[b];
238: int[] s = srcData[b];
239:
240: int dstLineOffset = dstBandOffsets[b];
241: int srcLineOffset = srcBandOffsets[b];
242:
243: for (int h = 0; h < dstHeight; h++) {
244: int dstPixelOffset = dstLineOffset;
245: int srcPixelOffset = srcLineOffset;
246:
247: dstLineOffset += dstLineStride;
248: srcLineOffset += srcLineStride;
249:
250: for (int w = 0; w < dstWidth; w++) {
251: d[dstPixelOffset] = s[srcPixelOffset] ^ c;
252:
253: dstPixelOffset += dstPixelStride;
254: srcPixelOffset += srcPixelStride;
255: }
256: }
257: }
258: }
259:
260: public static void main(String args[]) {
261: System.out.println("XorConstOpImage Test");
262: }
263: }
|