001: /*
002: * $RCSfile: MlibBandCombineOpImage.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:55:50 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.mlib;
013:
014: import java.awt.Rectangle;
015: import java.awt.image.ComponentSampleModel;
016: import java.awt.image.DataBuffer;
017: import java.awt.image.Raster;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.WritableRaster;
020: import java.util.Map;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.OpImage;
023: import javax.media.jai.PlanarImage;
024: import javax.media.jai.PointOpImage;
025: import javax.media.jai.RasterFactory;
026: import com.sun.media.jai.util.ImageUtil;
027: import com.sun.media.jai.util.JDKWorkarounds;
028: import com.sun.medialib.mlib.*;
029:
030: /**
031: * An OpImage class that performs a "BandCombine" operation for 3x3 images.
032: *
033: */
034: final class MlibBandCombineOpImage extends PointOpImage {
035: /* Color conversion matrix. */
036: private double[] cmat = new double[9];
037:
038: /* Offset vector. */
039: private double[] offset = new double[3];
040:
041: /* Flag indicating whether the offset is non-zero. */
042: private boolean isOffsetNonZero = false;
043:
044: /**
045: * Constructs an MlibBandCombineOpImage. The image dimensions are copied
046: * from the source image. The tile grid layout, SampleModel, and
047: * ColorModel may optionally be specified by an ImageLayout object.
048: *
049: * @param source a RenderedImage.
050: * @param layout an ImageLayout optionally containing the tile
051: * grid layout, SampleModel, and ColorModel, or null.
052: */
053: public MlibBandCombineOpImage(RenderedImage source, Map config,
054: ImageLayout layout, double[][] matrix) {
055: super (source, layout, config, true);
056:
057: int numBands = matrix.length; // matrix height is dst numBands
058: if (getSampleModel().getNumBands() != numBands) {
059: sampleModel = RasterFactory.createComponentSampleModel(
060: sampleModel, sampleModel.getDataType(), tileWidth,
061: tileHeight, numBands);
062:
063: if (colorModel != null
064: && !JDKWorkarounds.areCompatibleDataModels(
065: sampleModel, colorModel)) {
066: colorModel = ImageUtil.getCompatibleColorModel(
067: sampleModel, config);
068: }
069: }
070:
071: // Class of SampleModel should have been verified in the RIF
072: // by isMediaLibCompatible().
073: ComponentSampleModel csm = (ComponentSampleModel) source
074: .getSampleModel();
075: int[] bankIndices = csm.getBankIndices();
076: int[] bandOffsets = csm.getBandOffsets();
077:
078: // The matrix must be 3-by-4 for this to work: the check is done
079: // in the RIF. Note that the matrix may be modified to simulate the
080: // required interchange of bands 1 and 3.
081: if (bankIndices[0] == bankIndices[1]
082: && bankIndices[0] == bankIndices[2]
083: && bandOffsets[0] > bandOffsets[2]) {
084: for (int j = 0; j < 3; j++) {
085: int k = 8 - 3 * j;
086: for (int i = 0; i < 3; i++) {
087: cmat[k--] = matrix[j][i];
088: }
089: offset[2 - j] = matrix[j][3];
090: if (offset[j] != 0.0) {
091: isOffsetNonZero = true;
092: }
093: }
094: } else {
095: for (int j = 0; j < 3; j++) {
096: int k = 3 * j;
097: for (int i = 0; i < 3; i++) {
098: cmat[k++] = matrix[j][i];
099: }
100: offset[j] = matrix[j][3];
101: if (offset[j] != 0.0) {
102: isOffsetNonZero = true;
103: }
104: }
105: }
106: }
107:
108: /**
109: * Combine the selected bands.
110: * The sources are cobbled.
111: *
112: * @param sources an array of sources, guarantee to provide all
113: * necessary source data for computing the rectangle.
114: * @param dest a tile that contains the rectangle to be computed.
115: * @param destRect the rectangle within this OpImage to be processed.
116: */
117: protected void computeRect(Raster[] sources, WritableRaster dest,
118: Rectangle destRect) {
119: Raster source = sources[0];
120: Rectangle srcRect = mapDestRect(destRect, 0);
121:
122: int formatTag = MediaLibAccessor.findCompatibleTag(sources,
123: dest);
124:
125: MediaLibAccessor srcAccessor = new MediaLibAccessor(source,
126: srcRect, formatTag);
127: MediaLibAccessor dstAccessor = new MediaLibAccessor(dest,
128: destRect, formatTag);
129:
130: mediaLibImage[] srcML = srcAccessor.getMediaLibImages();
131: mediaLibImage[] dstML = dstAccessor.getMediaLibImages();
132:
133: switch (dstAccessor.getDataType()) {
134: case DataBuffer.TYPE_BYTE:
135: case DataBuffer.TYPE_USHORT:
136: case DataBuffer.TYPE_SHORT:
137: case DataBuffer.TYPE_INT:
138: for (int i = 0; i < dstML.length; i++) {
139: if (isOffsetNonZero) {
140: Image.ColorConvert2(dstML[i], srcML[i], cmat,
141: offset);
142: } else {
143: Image.ColorConvert1(dstML[i], srcML[i], cmat);
144: }
145: }
146: break;
147:
148: case DataBuffer.TYPE_FLOAT:
149: case DataBuffer.TYPE_DOUBLE:
150: for (int i = 0; i < dstML.length; i++) {
151: if (isOffsetNonZero) {
152: Image.ColorConvert2_Fp(dstML[i], srcML[i], cmat,
153: offset);
154: } else {
155: Image.ColorConvert1_Fp(dstML[i], srcML[i], cmat);
156: }
157: }
158: break;
159:
160: default:
161: String className = this .getClass().getName();
162: throw new RuntimeException(className
163: + JaiI18N.getString("Generic2"));
164: }
165:
166: if (dstAccessor.isDataCopy()) {
167: dstAccessor.clampDataArrays();
168: dstAccessor.copyDataToRaster();
169: }
170: }
171: }
|