001: /*
002: * $RCSfile: MlibExtremaOpImage.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:56 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.mlib;
013:
014: import java.awt.Point;
015: import java.awt.Rectangle;
016: import java.awt.image.Raster;
017: import java.awt.image.WritableRaster;
018: import java.awt.image.RenderedImage;
019: import java.awt.image.SampleModel;
020: import java.awt.image.DataBuffer;
021: import java.awt.image.PixelInterleavedSampleModel;
022: import java.util.ArrayList;
023: import javax.media.jai.OpImage;
024: import javax.media.jai.ImageLayout;
025: import javax.media.jai.PlanarImage;
026: import javax.media.jai.ROI;
027: import javax.media.jai.StatisticsOpImage;
028: import com.sun.media.jai.opimage.ExtremaOpImage;
029: import com.sun.medialib.mlib.*;
030:
031: /**
032: * An OpImage that performs the Extrema operation on an image through mediaLib.
033: *
034: */
035: final class MlibExtremaOpImage extends ExtremaOpImage {
036: /** Buffer for the minimum location count. */
037: private int[] minCount;
038:
039: /** Buffer for the maximum location count. */
040: private int[] maxCount;
041:
042: /** Buffer for the minimum location. */
043: private int[][] minLocs;
044:
045: /** Buffer for the maximum location. */
046: private int[][] maxLocs;
047:
048: /**
049: * Constructs an MlibExtremaOpImage. The image dimensions are copied
050: * from the source image. The tile grid layout, SampleModel, and
051: * ColorModel may optionally be specified by an ImageLayout object.
052: *
053: * @param source The source image.
054: */
055: public MlibExtremaOpImage(RenderedImage source, ROI roi,
056: int xStart, int yStart, int xPeriod, int yPeriod,
057: boolean saveLocations, int maxRuns) {
058: super (source, roi, xStart, yStart, xPeriod, yPeriod,
059: saveLocations, maxRuns);
060: }
061:
062: protected void accumulateStatistics(String name, Raster source,
063: Object stats) {
064: int numBands = sampleModel.getNumBands();
065:
066: initializeState(source);
067:
068: // Determine the required region of this tile. (Note
069: // that getTileRect() instersects tile and image bounds.)
070: Rectangle tileRect = source.getBounds();
071:
072: // Set the starting offset in the mediaLib image.
073: int offsetX = (xPeriod - ((tileRect.x - xStart) % xPeriod))
074: % xPeriod;
075: int offsetY = (yPeriod - ((tileRect.y - yStart) % yPeriod))
076: % yPeriod;
077:
078: // If this offset specifies a position outside of the
079: // tile then go to the next tile. This test is likely
080: // redundant to a similar test in StatisticsOpImage.
081: if (offsetX >= tileRect.width || offsetY >= tileRect.height) {
082: return;
083: }
084:
085: // Determine the format tag and create an accessor.
086: int formatTag = MediaLibAccessor
087: .findCompatibleTag(null, source);
088: MediaLibAccessor srcAccessor = new MediaLibAccessor(source,
089: tileRect, formatTag);
090:
091: // Get the mediaLib image.
092: mediaLibImage[] srcML = srcAccessor.getMediaLibImages();
093:
094: // NOTE: currently srcML.length always equals 1
095:
096: if (!saveLocations) {
097: switch (srcAccessor.getDataType()) {
098: case DataBuffer.TYPE_BYTE:
099: case DataBuffer.TYPE_USHORT:
100: case DataBuffer.TYPE_SHORT:
101: case DataBuffer.TYPE_INT:
102: int[] imin = new int[numBands];
103: int[] imax = new int[numBands];
104:
105: for (int i = 0; i < srcML.length; i++) {
106: Image.Extrema2(imin, imax, srcML[i], offsetX,
107: offsetY, xPeriod, yPeriod);
108: }
109:
110: imin = srcAccessor.getIntParameters(0, imin);
111: imax = srcAccessor.getIntParameters(0, imax);
112:
113: // Update the extrema.
114: for (int i = 0; i < numBands; i++) {
115: extrema[0][i] = Math.min((double) imin[i],
116: extrema[0][i]);
117: extrema[1][i] = Math.max((double) imax[i],
118: extrema[1][i]);
119: }
120: break;
121:
122: case DataBuffer.TYPE_FLOAT:
123: case DataBuffer.TYPE_DOUBLE:
124: double[] dmin = new double[numBands];
125: double[] dmax = new double[numBands];
126: for (int i = 0; i < srcML.length; i++) {
127: Image.Extrema2_Fp(dmin, dmax, srcML[i], offsetX,
128: offsetY, xPeriod, yPeriod);
129: }
130:
131: dmin = srcAccessor.getDoubleParameters(0, dmin);
132: dmax = srcAccessor.getDoubleParameters(0, dmax);
133:
134: // Update the extrema.
135: for (int i = 0; i < numBands; i++) {
136: extrema[0][i] = Math.min((double) dmin[i],
137: extrema[0][i]);
138: extrema[1][i] = Math.max((double) dmax[i],
139: extrema[1][i]);
140: }
141: break;
142: }
143: } else {
144: Rectangle loc = source.getBounds();
145: int xOffset = loc.x;
146: int yOffset = loc.y;
147:
148: switch (srcAccessor.getDataType()) {
149: case DataBuffer.TYPE_BYTE:
150: case DataBuffer.TYPE_USHORT:
151: case DataBuffer.TYPE_SHORT:
152: case DataBuffer.TYPE_INT:
153: int[] imin = new int[numBands];
154: int[] imax = new int[numBands];
155:
156: for (int i = 0; i < numBands; i++) {
157: imin[i] = (int) extrema[0][i];
158: imax[i] = (int) extrema[1][i];
159: }
160:
161: for (int i = 0; i < srcML.length; i++) {
162: Image.ExtremaLocations(imin, imax, srcML[i],
163: offsetX, offsetY, xPeriod, yPeriod,
164: saveLocations, maxRuns, minCount, maxCount,
165: minLocs, maxLocs);
166: }
167:
168: imin = srcAccessor.getIntParameters(0, imin);
169: imax = srcAccessor.getIntParameters(0, imax);
170: minCount = srcAccessor.getIntParameters(0, minCount);
171: maxCount = srcAccessor.getIntParameters(0, maxCount);
172: minLocs = srcAccessor.getIntArrayParameters(0, minLocs);
173: maxLocs = srcAccessor.getIntArrayParameters(0, maxLocs);
174:
175: // Update the extrema.
176: for (int i = 0; i < numBands; i++) {
177: ArrayList minList = minLocations[i];
178: ArrayList maxList = maxLocations[i];
179: if (imin[i] < extrema[0][i]) {
180: minList.clear();
181: extrema[0][i] = imin[i];
182: }
183:
184: int[] minBuf = minLocs[i];
185: int[] maxBuf = maxLocs[i];
186:
187: for (int j = 0, k = 0; j < minCount[i]; j++)
188: minList.add(new int[] { minBuf[k++] + xOffset,
189: minBuf[k++] + yOffset, minBuf[k++] });
190:
191: if (imax[i] > extrema[1][i]) {
192: maxList.clear();
193: extrema[1][i] = imax[i];
194: }
195:
196: for (int j = 0, k = 0; j < maxCount[i]; j++)
197: maxList.add(new int[] { maxBuf[k++] + xOffset,
198: maxBuf[k++] + yOffset, maxBuf[k++] });
199: }
200: break;
201:
202: case DataBuffer.TYPE_FLOAT:
203: case DataBuffer.TYPE_DOUBLE:
204: double[] dmin = new double[numBands];
205: double[] dmax = new double[numBands];
206:
207: for (int i = 0; i < numBands; i++) {
208: dmin[i] = extrema[0][i];
209: dmax[i] = extrema[1][i];
210: }
211:
212: for (int i = 0; i < srcML.length; i++) {
213: Image.ExtremaLocations_Fp(dmin, dmax, srcML[i],
214: offsetX, offsetY, xPeriod, yPeriod,
215: saveLocations, maxRuns, minCount, maxCount,
216: minLocs, maxLocs);
217: }
218:
219: dmin = srcAccessor.getDoubleParameters(0, dmin);
220: dmax = srcAccessor.getDoubleParameters(0, dmax);
221: minCount = srcAccessor.getIntParameters(0, minCount);
222: maxCount = srcAccessor.getIntParameters(0, maxCount);
223: minLocs = srcAccessor.getIntArrayParameters(0, minLocs);
224: maxLocs = srcAccessor.getIntArrayParameters(0, maxLocs);
225:
226: // Update the extrema.
227: for (int i = 0; i < numBands; i++) {
228: ArrayList minList = minLocations[i];
229: ArrayList maxList = maxLocations[i];
230: if (dmin[i] < extrema[0][i]) {
231: minList.clear();
232: extrema[0][i] = dmin[i];
233: }
234:
235: int[] minBuf = minLocs[i];
236: int[] maxBuf = maxLocs[i];
237:
238: for (int j = 0, k = 0; j < minCount[i]; j++)
239: minList.add(new int[] { minBuf[k++] + xOffset,
240: minBuf[k++] + yOffset, minBuf[k++] });
241:
242: if (dmax[i] > extrema[1][i]) {
243: maxList.clear();
244: extrema[1][i] = dmax[i];
245: }
246:
247: for (int j = 0, k = 0; j < maxCount[i]; j++)
248: maxList.add(new int[] { maxBuf[k++] + xOffset,
249: maxBuf[k++] + yOffset, maxBuf[k++] });
250: }
251: break;
252: }
253: }
254:
255: if (name.equalsIgnoreCase("extrema")) {
256: double[][] ext = (double[][]) stats;
257: for (int i = 0; i < numBands; i++) {
258: ext[0][i] = extrema[0][i];
259: ext[1][i] = extrema[1][i];
260: }
261: } else if (name.equalsIgnoreCase("minimum")) {
262: double[] min = (double[]) stats;
263: for (int i = 0; i < numBands; i++) {
264: min[i] = extrema[0][i];
265: }
266: } else if (name.equalsIgnoreCase("maximum")) {
267: double[] max = (double[]) stats;
268: for (int i = 0; i < numBands; i++) {
269: max[i] = extrema[1][i];
270: }
271: } else if (name.equalsIgnoreCase("minLocations")) {
272: ArrayList[] minLoc = (ArrayList[]) stats;
273: for (int i = 0; i < numBands; i++) {
274: minLoc[i] = minLocations[i];
275: }
276: } else if (name.equalsIgnoreCase("maxLocations")) {
277: ArrayList[] maxLoc = (ArrayList[]) stats;
278: for (int i = 0; i < numBands; i++)
279: maxLoc[i] = maxLocations[i];
280: }
281: }
282:
283: protected void initializeState(Raster source) {
284: if (extrema == null) {
285: int numBands = sampleModel.getNumBands();
286: minCount = new int[numBands];
287: maxCount = new int[numBands];
288:
289: minLocs = new int[numBands][];
290: maxLocs = new int[numBands][];
291:
292: int size = (getTileWidth() + 1) / 2 * getTileHeight();
293:
294: for (int i = 0; i < numBands; i++) {
295: minLocs[i] = new int[size];
296: maxLocs[i] = new int[size];
297: }
298:
299: super.initializeState(source);
300: }
301: }
302: }
|