0001: /*
0002: * $RCSfile: ExtremaOpImage.java,v $
0003: *
0004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * Use is subject to license terms.
0007: *
0008: * $Revision: 1.1 $
0009: * $Date: 2005/02/11 04:56:25 $
0010: * $State: Exp $
0011: */
0012: package com.sun.media.jai.opimage;
0013:
0014: import java.awt.Image;
0015: import java.awt.Rectangle;
0016: import java.awt.image.DataBuffer;
0017: import java.awt.image.Raster;
0018: import java.awt.image.RenderedImage;
0019: import java.util.ArrayList;
0020: import java.util.Hashtable;
0021: import java.util.LinkedList;
0022: import java.util.ListIterator;
0023: import javax.media.jai.ImageLayout;
0024: import javax.media.jai.OpImage;
0025: import javax.media.jai.PixelAccessor;
0026: import javax.media.jai.PlanarImage;
0027: import javax.media.jai.ROI;
0028: import javax.media.jai.StatisticsOpImage;
0029: import javax.media.jai.UnpackedImageData;
0030: import com.sun.media.jai.util.ImageUtil;
0031:
0032: /**
0033: * An <code>OpImage</code> implementing the "Extrema" operation as
0034: * described in <code>javax.media.jai.operator.ExtremaDescriptor</code>.
0035: *
0036: * @see javax.media.jai.operator.ExtremaDescriptor
0037: * @see ExtremaCRIF
0038: */
0039: public class ExtremaOpImage extends StatisticsOpImage {
0040:
0041: protected double[][] extrema;
0042:
0043: protected ArrayList[] minLocations;
0044:
0045: protected ArrayList[] maxLocations;
0046:
0047: protected int[] minCounts;
0048:
0049: protected int[] maxCounts;
0050:
0051: protected boolean saveLocations;
0052:
0053: protected int maxRuns;
0054:
0055: protected int numMinLocations = 0;
0056:
0057: protected int numMaxLocations = 0;
0058:
0059: private boolean isInitialized = false;
0060:
0061: private PixelAccessor srcPA;
0062:
0063: private int srcSampleType;
0064:
0065: private final boolean tileIntersectsROI(int tileX, int tileY) {
0066: if (roi == null) { // ROI is entire tile
0067: return true;
0068: } else {
0069: return roi.intersects(tileXToX(tileX), tileYToY(tileY),
0070: tileWidth, tileHeight);
0071: }
0072: }
0073:
0074: /**
0075: * Constructs an <code>ExtremaOpImage</code>.
0076: *
0077: * @param source The source image.
0078: */
0079: public ExtremaOpImage(RenderedImage source, ROI roi, int xStart,
0080: int yStart, int xPeriod, int yPeriod,
0081: boolean saveLocations, int maxRuns) {
0082: super (source, roi, xStart, yStart, xPeriod, yPeriod);
0083:
0084: extrema = null;
0085: this .saveLocations = saveLocations;
0086: this .maxRuns = maxRuns;
0087: }
0088:
0089: /** Returns one of the available statistics as a property. */
0090: public Object getProperty(String name) {
0091: int numBands = sampleModel.getNumBands();
0092:
0093: if (extrema == null) {
0094: // Statistics have not been accumulated: call superclass
0095: // method to do so.
0096: return super .getProperty(name);
0097: } else if (name.equalsIgnoreCase("extrema")) {
0098: double[][] stats = new double[2][numBands];
0099: for (int i = 0; i < numBands; i++) {
0100: stats[0][i] = extrema[0][i];
0101: stats[1][i] = extrema[1][i];
0102: }
0103: return stats;
0104: } else if (name.equalsIgnoreCase("minimum")) {
0105: double[] stats = new double[numBands];
0106: for (int i = 0; i < numBands; i++) {
0107: stats[i] = extrema[0][i];
0108: }
0109: return stats;
0110: } else if (name.equalsIgnoreCase("maximum")) {
0111: double[] stats = new double[numBands];
0112: for (int i = 0; i < numBands; i++) {
0113: stats[i] = extrema[1][i];
0114: }
0115: return stats;
0116: } else if (saveLocations
0117: && name.equalsIgnoreCase("minLocations")) {
0118: return minLocations;
0119: } else if (saveLocations
0120: && name.equalsIgnoreCase("maxLocations")) {
0121: return maxLocations;
0122: }
0123:
0124: return java.awt.Image.UndefinedProperty;
0125: }
0126:
0127: protected String[] getStatisticsNames() {
0128: return new String[] { "extrema", "maximum", "minimum",
0129: "maxLocations", "minLocations" };
0130: }
0131:
0132: protected Object createStatistics(String name) {
0133: int numBands = sampleModel.getNumBands();
0134: Object stats = null;
0135:
0136: if (name.equalsIgnoreCase("extrema")) {
0137: stats = new double[2][numBands];
0138: } else if (name.equalsIgnoreCase("minimum")
0139: || name.equalsIgnoreCase("maximum")) {
0140: stats = new double[numBands];
0141: } else if (saveLocations
0142: && (name.equalsIgnoreCase("minLocations") || name
0143: .equalsIgnoreCase("maxLocations"))) {
0144: stats = new ArrayList[numBands];
0145: } else {
0146: stats = java.awt.Image.UndefinedProperty;
0147: }
0148: return stats;
0149: }
0150:
0151: private final int startPosition(int pos, int start, int period) {
0152: int t = (pos - start) % period;
0153: return t == 0 ? pos : pos + (period - t);
0154: }
0155:
0156: protected void accumulateStatistics(String name, Raster source,
0157: Object stats) {
0158: if (!isInitialized) {
0159: srcPA = new PixelAccessor(getSourceImage(0));
0160: srcSampleType = srcPA.sampleType == PixelAccessor.TYPE_BIT ? DataBuffer.TYPE_BYTE
0161: : srcPA.sampleType;
0162: isInitialized = true;
0163: }
0164:
0165: Rectangle srcBounds = getSourceImage(0).getBounds()
0166: .intersection(source.getBounds());
0167:
0168: LinkedList rectList;
0169: if (roi == null) { // ROI is the whole Raster
0170: rectList = new LinkedList();
0171: rectList.addLast(srcBounds);
0172: } else {
0173: rectList = roi.getAsRectangleList(srcBounds.x, srcBounds.y,
0174: srcBounds.width, srcBounds.height);
0175: if (rectList == null) {
0176: return; // ROI does not intersect with Raster boundary.
0177: }
0178: }
0179: ListIterator iterator = rectList.listIterator(0);
0180:
0181: while (iterator.hasNext()) {
0182: Rectangle rect = srcBounds
0183: .intersection((Rectangle) iterator.next());
0184: int tx = rect.x;
0185: int ty = rect.y;
0186:
0187: // Find the actual ROI based on start and period.
0188: rect.x = startPosition(tx, xStart, xPeriod);
0189: rect.y = startPosition(ty, yStart, yPeriod);
0190: rect.width = tx + rect.width - rect.x;
0191: rect.height = ty + rect.height - rect.y;
0192:
0193: if (rect.isEmpty()) {
0194: continue; // no pixel to count in this rectangle
0195: }
0196:
0197: initializeState(source);
0198:
0199: UnpackedImageData uid = srcPA.getPixels(source, rect,
0200: srcSampleType, false);
0201: switch (uid.type) {
0202: case DataBuffer.TYPE_BYTE:
0203: accumulateStatisticsByte(uid);
0204: break;
0205: case DataBuffer.TYPE_USHORT:
0206: accumulateStatisticsUShort(uid);
0207: break;
0208: case DataBuffer.TYPE_SHORT:
0209: accumulateStatisticsShort(uid);
0210: break;
0211: case DataBuffer.TYPE_INT:
0212: accumulateStatisticsInt(uid);
0213: break;
0214: case DataBuffer.TYPE_FLOAT:
0215: accumulateStatisticsFloat(uid);
0216: break;
0217: case DataBuffer.TYPE_DOUBLE:
0218: accumulateStatisticsDouble(uid);
0219: break;
0220: }
0221: }
0222:
0223: if (name.equalsIgnoreCase("extrema")) {
0224: double[][] ext = (double[][]) stats;
0225: for (int i = 0; i < srcPA.numBands; i++) {
0226: ext[0][i] = extrema[0][i];
0227: ext[1][i] = extrema[1][i];
0228: }
0229: } else if (name.equalsIgnoreCase("minimum")) {
0230: double[] min = (double[]) stats;
0231: for (int i = 0; i < srcPA.numBands; i++) {
0232: min[i] = extrema[0][i];
0233: }
0234: } else if (name.equalsIgnoreCase("maximum")) {
0235: double[] max = (double[]) stats;
0236: for (int i = 0; i < srcPA.numBands; i++) {
0237: max[i] = extrema[1][i];
0238: }
0239: } else if (name.equalsIgnoreCase("minLocations")) {
0240: ArrayList[] minLoc = (ArrayList[]) stats;
0241: for (int i = 0; i < srcPA.numBands; i++) {
0242: minLoc[i] = minLocations[i];
0243: }
0244: } else if (name.equalsIgnoreCase("maxLocations")) {
0245: ArrayList[] maxLoc = (ArrayList[]) stats;
0246: for (int i = 0; i < srcPA.numBands; i++)
0247: maxLoc[i] = maxLocations[i];
0248: }
0249: }
0250:
0251: private void accumulateStatisticsByte(UnpackedImageData uid) {
0252: Rectangle rect = uid.rect;
0253: byte[][] data = uid.getByteData();
0254: int lineStride = uid.lineStride;
0255: int pixelStride = uid.pixelStride;
0256:
0257: int lineInc = lineStride * yPeriod;
0258: int pixelInc = pixelStride * xPeriod;
0259:
0260: if (!saveLocations) {
0261: for (int b = 0; b < srcPA.numBands; b++) {
0262: int min = (int) extrema[0][b]; // minimum
0263: int max = (int) extrema[1][b]; // maximum
0264:
0265: byte[] d = data[b];
0266: int lastLine = uid.bandOffsets[b] + rect.height
0267: * lineStride;
0268:
0269: for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineInc) {
0270: int lastPixel = lo + rect.width * pixelStride;
0271:
0272: for (int po = lo; po < lastPixel; po += pixelInc) {
0273: int p = d[po] & 0xff;
0274:
0275: if (p < min) {
0276: min = p;
0277: } else if (p > max) {
0278: max = p;
0279: }
0280: }
0281: }
0282: extrema[0][b] = min;
0283: extrema[1][b] = max;
0284: }
0285: } else {
0286: for (int b = 0; b < srcPA.numBands; b++) {
0287: int min = (int) extrema[0][b]; // minimum
0288: int max = (int) extrema[1][b]; // maximum
0289: ArrayList minList = minLocations[b];
0290: ArrayList maxList = maxLocations[b];
0291: int minCount = minCounts[b];
0292: int maxCount = maxCounts[b];
0293:
0294: byte[] d = data[b];
0295: int lastLine = uid.bandOffsets[b] + rect.height
0296: * lineStride;
0297:
0298: for (int lo = uid.bandOffsets[b], y = rect.y; lo < lastLine; lo += lineInc, y += yPeriod) {
0299:
0300: int lastPixel = lo + rect.width * pixelStride;
0301: int minStart = 0;
0302: int maxStart = 0;
0303: int minLength = 0;
0304: int maxLength = 0;
0305:
0306: for (int po = lo, x = rect.x; po < lastPixel; po += pixelInc, x += xPeriod) {
0307:
0308: int p = d[po] & 0xff;
0309:
0310: if (p < min) {
0311: min = p;
0312: minStart = x;
0313: minLength = 1;
0314: minList.clear();
0315: minCount = 0;
0316: } else if (p > max) {
0317: max = p;
0318: maxStart = x;
0319: maxLength = 1;
0320: maxList.clear();
0321: maxCount = 0;
0322: } else {
0323: if (p == min) {
0324: if (minLength == 0)
0325: minStart = x;
0326: minLength++;
0327: } else if (minLength > 0
0328: && minCount < maxRuns) {
0329: minList.add(new int[] { minStart, y,
0330: minLength });
0331: minCount++;
0332: minLength = 0;
0333: }
0334:
0335: if (p == max) {
0336: if (maxLength == 0)
0337: maxStart = x;
0338: maxLength++;
0339: } else if (maxLength > 0
0340: && maxCount < maxRuns) {
0341: maxList.add(new int[] { maxStart, y,
0342: maxLength });
0343: maxCount++;
0344: maxLength = 0;
0345: }
0346: }
0347: }
0348:
0349: if (maxLength > 0 && maxCount < maxRuns) {
0350: maxList
0351: .add(new int[] { maxStart, y, maxLength });
0352: maxCount++;
0353: }
0354:
0355: if (minLength > 0 && minCount < maxRuns) {
0356: minList
0357: .add(new int[] { minStart, y, minLength });
0358: minCount++;
0359: }
0360: }
0361:
0362: extrema[0][b] = min;
0363: extrema[1][b] = max;
0364: minCounts[b] = minCount;
0365: maxCounts[b] = maxCount;
0366: }
0367: }
0368: }
0369:
0370: private void accumulateStatisticsUShort(UnpackedImageData uid) {
0371: Rectangle rect = uid.rect;
0372: short[][] data = uid.getShortData();
0373: int lineStride = uid.lineStride;
0374: int pixelStride = uid.pixelStride;
0375:
0376: int lineInc = lineStride * yPeriod;
0377: int pixelInc = pixelStride * xPeriod;
0378:
0379: if (!saveLocations) {
0380: for (int b = 0; b < srcPA.numBands; b++) {
0381: int min = (int) extrema[0][b]; // minimum
0382: int max = (int) extrema[1][b]; // maximum
0383:
0384: short[] d = data[b];
0385: int lastLine = uid.bandOffsets[b] + rect.height
0386: * lineStride;
0387:
0388: for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineInc) {
0389: int lastPixel = lo + rect.width * pixelStride;
0390:
0391: for (int po = lo; po < lastPixel; po += pixelInc) {
0392: int p = d[po] & 0xffff;
0393:
0394: if (p < min) {
0395: min = p;
0396: } else if (p > max) {
0397: max = p;
0398: }
0399: }
0400: }
0401: extrema[0][b] = min;
0402: extrema[1][b] = max;
0403: }
0404: } else {
0405: for (int b = 0; b < srcPA.numBands; b++) {
0406: int min = (int) extrema[0][b]; // minimum
0407: int max = (int) extrema[1][b]; // maximum
0408: ArrayList minList = minLocations[b];
0409: ArrayList maxList = maxLocations[b];
0410: int minCount = minCounts[b];
0411: int maxCount = maxCounts[b];
0412:
0413: short[] d = data[b];
0414: int lastLine = uid.bandOffsets[b] + rect.height
0415: * lineStride;
0416:
0417: for (int lo = uid.bandOffsets[b], y = rect.y; lo < lastLine; lo += lineInc, y += yPeriod) {
0418:
0419: int lastPixel = lo + rect.width * pixelStride;
0420: int minStart = 0;
0421: int maxStart = 0;
0422: int minLength = 0;
0423: int maxLength = 0;
0424:
0425: for (int po = lo, x = rect.x; po < lastPixel; po += pixelInc, x += xPeriod) {
0426:
0427: int p = d[po] & 0xffff;
0428:
0429: if (p < min) {
0430: min = p;
0431: minStart = x;
0432: minLength = 1;
0433: minList.clear();
0434: minCount = 0;
0435: } else if (p > max) {
0436: max = p;
0437: maxStart = x;
0438: maxLength = 1;
0439: maxList.clear();
0440: maxCount = 0;
0441: } else {
0442: if (p == min) {
0443: if (minLength == 0)
0444: minStart = x;
0445: minLength++;
0446: } else if (minLength > 0
0447: && minCount < maxRuns) {
0448: minList.add(new int[] { minStart, y,
0449: minLength });
0450: minCount++;
0451: minLength = 0;
0452: }
0453:
0454: if (p == max) {
0455: if (maxLength == 0)
0456: maxStart = x;
0457: maxLength++;
0458: } else if (maxLength > 0
0459: && maxCount < maxRuns) {
0460: maxList.add(new int[] { maxStart, y,
0461: maxLength });
0462: maxCount++;
0463: maxLength = 0;
0464: }
0465: }
0466: }
0467:
0468: if (maxLength > 0 && maxCount < maxRuns) {
0469: maxList
0470: .add(new int[] { maxStart, y, maxLength });
0471: maxCount++;
0472: }
0473:
0474: if (minLength > 0 && minCount < maxRuns) {
0475: minList
0476: .add(new int[] { minStart, y, minLength });
0477: minCount++;
0478: }
0479: }
0480:
0481: extrema[0][b] = min;
0482: extrema[1][b] = max;
0483: minCounts[b] = minCount;
0484: maxCounts[b] = maxCount;
0485: }
0486: }
0487: }
0488:
0489: private void accumulateStatisticsShort(UnpackedImageData uid) {
0490: Rectangle rect = uid.rect;
0491: short[][] data = uid.getShortData();
0492: int lineStride = uid.lineStride;
0493: int pixelStride = uid.pixelStride;
0494:
0495: int lineInc = lineStride * yPeriod;
0496: int pixelInc = pixelStride * xPeriod;
0497:
0498: if (!saveLocations) {
0499: for (int b = 0; b < srcPA.numBands; b++) {
0500: int min = (int) extrema[0][b]; // minimum
0501: int max = (int) extrema[1][b]; // maximum
0502:
0503: short[] d = data[b];
0504: int lastLine = uid.bandOffsets[b] + rect.height
0505: * lineStride;
0506:
0507: for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineInc) {
0508: int lastPixel = lo + rect.width * pixelStride;
0509:
0510: for (int po = lo; po < lastPixel; po += pixelInc) {
0511: int p = d[po];
0512:
0513: if (p < min) {
0514: min = p;
0515: } else if (p > max) {
0516: max = p;
0517: }
0518: }
0519: }
0520: extrema[0][b] = min;
0521: extrema[1][b] = max;
0522: }
0523: } else {
0524: for (int b = 0; b < srcPA.numBands; b++) {
0525: int min = (int) extrema[0][b]; // minimum
0526: int max = (int) extrema[1][b]; // maximum
0527: ArrayList minList = minLocations[b];
0528: ArrayList maxList = maxLocations[b];
0529: int minCount = minCounts[b];
0530: int maxCount = maxCounts[b];
0531:
0532: short[] d = data[b];
0533: int lastLine = uid.bandOffsets[b] + rect.height
0534: * lineStride;
0535:
0536: for (int lo = uid.bandOffsets[b], y = rect.y; lo < lastLine; lo += lineInc, y += yPeriod) {
0537:
0538: int lastPixel = lo + rect.width * pixelStride;
0539: int minStart = 0;
0540: int maxStart = 0;
0541: int minLength = 0;
0542: int maxLength = 0;
0543:
0544: for (int po = lo, x = rect.x; po < lastPixel; po += pixelInc, x += xPeriod) {
0545:
0546: int p = d[po];
0547:
0548: if (p < min) {
0549: min = p;
0550: minStart = x;
0551: minLength = 1;
0552: minList.clear();
0553: minCount = 0;
0554: } else if (p > max) {
0555: max = p;
0556: maxStart = x;
0557: maxLength = 1;
0558: maxList.clear();
0559: maxCount = 0;
0560: } else {
0561: if (p == min) {
0562: if (minLength == 0)
0563: minStart = x;
0564: minLength++;
0565: } else if (minLength > 0
0566: && minCount < maxRuns) {
0567: minList.add(new int[] { minStart, y,
0568: minLength });
0569: minCount++;
0570: minLength = 0;
0571: }
0572:
0573: if (p == max) {
0574: if (maxLength == 0)
0575: maxStart = x;
0576: maxLength++;
0577: } else if (maxLength > 0
0578: && maxCount < maxRuns) {
0579: maxList.add(new int[] { maxStart, y,
0580: maxLength });
0581: maxCount++;
0582: maxLength = 0;
0583: }
0584: }
0585: }
0586:
0587: if (maxLength > 0 && maxCount < maxRuns) {
0588: maxList
0589: .add(new int[] { maxStart, y, maxLength });
0590: maxCount++;
0591: }
0592:
0593: if (minLength > 0 && minCount < maxRuns) {
0594: minList
0595: .add(new int[] { minStart, y, minLength });
0596: minCount++;
0597: }
0598: }
0599:
0600: extrema[0][b] = min;
0601: extrema[1][b] = max;
0602: minCounts[b] = minCount;
0603: maxCounts[b] = maxCount;
0604: }
0605: }
0606: }
0607:
0608: private void accumulateStatisticsInt(UnpackedImageData uid) {
0609: Rectangle rect = uid.rect;
0610: int[][] data = uid.getIntData();
0611: int lineStride = uid.lineStride;
0612: int pixelStride = uid.pixelStride;
0613:
0614: int lineInc = lineStride * yPeriod;
0615: int pixelInc = pixelStride * xPeriod;
0616:
0617: if (!saveLocations) {
0618: for (int b = 0; b < srcPA.numBands; b++) {
0619: int min = (int) extrema[0][b]; // minimum
0620: int max = (int) extrema[1][b]; // maximum
0621:
0622: int[] d = data[b];
0623: int lastLine = uid.bandOffsets[b] + rect.height
0624: * lineStride;
0625:
0626: for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineInc) {
0627: int lastPixel = lo + rect.width * pixelStride;
0628:
0629: for (int po = lo; po < lastPixel; po += pixelInc) {
0630: int p = d[po];
0631:
0632: if (p < min) {
0633: min = p;
0634: } else if (p > max) {
0635: max = p;
0636: }
0637: }
0638: }
0639: extrema[0][b] = min;
0640: extrema[1][b] = max;
0641: }
0642: } else {
0643: for (int b = 0; b < srcPA.numBands; b++) {
0644: int min = (int) extrema[0][b]; // minimum
0645: int max = (int) extrema[1][b]; // maximum
0646: ArrayList minList = minLocations[b];
0647: ArrayList maxList = maxLocations[b];
0648: int minCount = minCounts[b];
0649: int maxCount = maxCounts[b];
0650:
0651: int[] d = data[b];
0652: int lastLine = uid.bandOffsets[b] + rect.height
0653: * lineStride;
0654:
0655: for (int lo = uid.bandOffsets[b], y = rect.y; lo < lastLine; lo += lineInc, y += yPeriod) {
0656:
0657: int lastPixel = lo + rect.width * pixelStride;
0658: int minStart = 0;
0659: int maxStart = 0;
0660: int minLength = 0;
0661: int maxLength = 0;
0662:
0663: for (int po = lo, x = rect.x; po < lastPixel; po += pixelInc, x += xPeriod) {
0664:
0665: int p = d[po];
0666:
0667: if (p < min) {
0668: min = p;
0669: minStart = x;
0670: minLength = 1;
0671: minList.clear();
0672: minCount = 0;
0673: } else if (p > max) {
0674: max = p;
0675: maxStart = x;
0676: maxLength = 1;
0677: maxList.clear();
0678: maxCount = 0;
0679: } else {
0680: if (p == min) {
0681: if (minLength == 0)
0682: minStart = x;
0683: minLength++;
0684: } else if (minLength > 0
0685: && minCount < maxRuns) {
0686: minList.add(new int[] { minStart, y,
0687: minLength });
0688: minCount++;
0689: minLength = 0;
0690: }
0691:
0692: if (p == max) {
0693: if (maxLength == 0)
0694: maxStart = x;
0695: maxLength++;
0696: } else if (maxLength > 0
0697: && maxCount < maxRuns) {
0698: maxList.add(new int[] { maxStart, y,
0699: maxLength });
0700: maxCount++;
0701: maxLength = 0;
0702: }
0703: }
0704: }
0705:
0706: if (maxLength > 0 && maxCount < maxRuns) {
0707: maxList
0708: .add(new int[] { maxStart, y, maxLength });
0709: maxCount++;
0710: }
0711:
0712: if (minLength > 0 && minCount < maxRuns) {
0713: minList
0714: .add(new int[] { minStart, y, minLength });
0715: minCount++;
0716: }
0717: }
0718:
0719: extrema[0][b] = min;
0720: extrema[1][b] = max;
0721: minCounts[b] = minCount;
0722: maxCounts[b] = maxCount;
0723: }
0724: }
0725: }
0726:
0727: private void accumulateStatisticsFloat(UnpackedImageData uid) {
0728: Rectangle rect = uid.rect;
0729: float[][] data = uid.getFloatData();
0730: int lineStride = uid.lineStride;
0731: int pixelStride = uid.pixelStride;
0732:
0733: int lineInc = lineStride * yPeriod;
0734: int pixelInc = pixelStride * xPeriod;
0735:
0736: if (!saveLocations) {
0737: for (int b = 0; b < srcPA.numBands; b++) {
0738: float min = (float) extrema[0][b]; // minimum
0739: float max = (float) extrema[1][b]; // maximum
0740:
0741: float[] d = data[b];
0742: int lastLine = uid.bandOffsets[b] + rect.height
0743: * lineStride;
0744:
0745: for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineInc) {
0746: int lastPixel = lo + rect.width * pixelStride;
0747:
0748: for (int po = lo; po < lastPixel; po += pixelInc) {
0749: float p = d[po];
0750:
0751: if (p < min) {
0752: min = p;
0753: } else if (p > max) {
0754: max = p;
0755: }
0756: }
0757: }
0758: extrema[0][b] = min;
0759: extrema[1][b] = max;
0760: }
0761: } else {
0762: for (int b = 0; b < srcPA.numBands; b++) {
0763: float min = (float) extrema[0][b]; // minimum
0764: float max = (float) extrema[1][b]; // maximum
0765: ArrayList minList = minLocations[b];
0766: ArrayList maxList = maxLocations[b];
0767: int minCount = minCounts[b];
0768: int maxCount = maxCounts[b];
0769:
0770: float[] d = data[b];
0771: int lastLine = uid.bandOffsets[b] + rect.height
0772: * lineStride;
0773:
0774: for (int lo = uid.bandOffsets[b], y = rect.y; lo < lastLine; lo += lineInc, y += yPeriod) {
0775:
0776: int lastPixel = lo + rect.width * pixelStride;
0777: int minStart = 0;
0778: int maxStart = 0;
0779: int minLength = 0;
0780: int maxLength = 0;
0781:
0782: for (int po = lo, x = rect.x; po < lastPixel; po += pixelInc, x += xPeriod) {
0783:
0784: float p = d[po];
0785:
0786: if (p < min) {
0787: min = p;
0788: minStart = x;
0789: minLength = 1;
0790: minList.clear();
0791: minCount = 0;
0792: } else if (p > max) {
0793: max = p;
0794: maxStart = x;
0795: maxLength = 1;
0796: maxList.clear();
0797: maxCount = 0;
0798: } else {
0799: if (p == min) {
0800: if (minLength == 0)
0801: minStart = x;
0802: minLength++;
0803: } else if (minLength > 0
0804: && minCount < maxRuns) {
0805: minList.add(new int[] { minStart, y,
0806: minLength });
0807: minCount++;
0808: minLength = 0;
0809: }
0810:
0811: if (p == max) {
0812: if (maxLength == 0)
0813: maxStart = x;
0814: maxLength++;
0815: } else if (maxLength > 0
0816: && maxCount < maxRuns) {
0817: maxList.add(new int[] { maxStart, y,
0818: maxLength });
0819: maxCount++;
0820: maxLength = 0;
0821: }
0822: }
0823: }
0824:
0825: if (maxLength > 0 && maxCount < maxRuns) {
0826: maxList
0827: .add(new int[] { maxStart, y, maxLength });
0828: maxCount++;
0829: }
0830:
0831: if (minLength > 0 && minCount < maxRuns) {
0832: minList
0833: .add(new int[] { minStart, y, minLength });
0834: minCount++;
0835: }
0836: }
0837:
0838: extrema[0][b] = min;
0839: extrema[1][b] = max;
0840: minCounts[b] = minCount;
0841: maxCounts[b] = maxCount;
0842: }
0843: }
0844: }
0845:
0846: private void accumulateStatisticsDouble(UnpackedImageData uid) {
0847: Rectangle rect = uid.rect;
0848: double[][] data = uid.getDoubleData();
0849: int lineStride = uid.lineStride;
0850: int pixelStride = uid.pixelStride;
0851:
0852: int lineInc = lineStride * yPeriod;
0853: int pixelInc = pixelStride * xPeriod;
0854:
0855: if (!saveLocations) {
0856: for (int b = 0; b < srcPA.numBands; b++) {
0857: double min = extrema[0][b]; // minimum
0858: double max = extrema[1][b]; // maximum
0859:
0860: double[] d = data[b];
0861: int lastLine = uid.bandOffsets[b] + rect.height
0862: * lineStride;
0863:
0864: for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineInc) {
0865: int lastPixel = lo + rect.width * pixelStride;
0866:
0867: for (int po = lo; po < lastPixel; po += pixelInc) {
0868: double p = d[po];
0869:
0870: if (p < min) {
0871: min = p;
0872: } else if (p > max) {
0873: max = p;
0874: }
0875: }
0876: }
0877: extrema[0][b] = min;
0878: extrema[1][b] = max;
0879: }
0880: } else {
0881: for (int b = 0; b < srcPA.numBands; b++) {
0882: double min = extrema[0][b]; // minimum
0883: double max = extrema[1][b]; // maximum
0884: ArrayList minList = minLocations[b];
0885: ArrayList maxList = maxLocations[b];
0886: int minCount = minCounts[b];
0887: int maxCount = maxCounts[b];
0888:
0889: double[] d = data[b];
0890: int lastLine = uid.bandOffsets[b] + rect.height
0891: * lineStride;
0892:
0893: for (int lo = uid.bandOffsets[b], y = rect.y; lo < lastLine; lo += lineInc, y += yPeriod) {
0894:
0895: int lastPixel = lo + rect.width * pixelStride;
0896: int minStart = 0;
0897: int maxStart = 0;
0898: int minLength = 0;
0899: int maxLength = 0;
0900:
0901: for (int po = lo, x = rect.x; po < lastPixel; po += pixelInc, x += xPeriod) {
0902:
0903: double p = d[po];
0904:
0905: if (p < min) {
0906: min = p;
0907: minStart = x;
0908: minLength = 1;
0909: minList.clear();
0910: minCount = 0;
0911: } else if (p > max) {
0912: max = p;
0913: maxStart = x;
0914: maxLength = 1;
0915: maxList.clear();
0916: maxCount = 0;
0917: } else {
0918: if (p == min) {
0919: if (minLength == 0)
0920: minStart = x;
0921: minLength++;
0922: } else if (minLength > 0
0923: && minCount < maxRuns) {
0924: minList.add(new int[] { minStart, y,
0925: minLength });
0926: minCount++;
0927: minLength = 0;
0928: }
0929:
0930: if (p == max) {
0931: if (maxLength == 0)
0932: maxStart = x;
0933: maxLength++;
0934: } else if (maxLength > 0
0935: && maxCount < maxRuns) {
0936: maxList.add(new int[] { maxStart, y,
0937: maxLength });
0938: maxCount++;
0939: maxLength = 0;
0940: }
0941: }
0942: }
0943:
0944: if (maxLength > 0 && maxCount < maxRuns) {
0945: maxList
0946: .add(new int[] { maxStart, y, maxLength });
0947: maxCount++;
0948: }
0949:
0950: if (minLength > 0 && minCount < maxRuns) {
0951: minList
0952: .add(new int[] { minStart, y, minLength });
0953: minCount++;
0954: }
0955: }
0956:
0957: extrema[0][b] = min;
0958: extrema[1][b] = max;
0959: minCounts[b] = minCount;
0960: maxCounts[b] = maxCount;
0961: }
0962: }
0963: }
0964:
0965: protected void initializeState(Raster source) {
0966: if (extrema == null) {
0967: int numBands = sampleModel.getNumBands();
0968: extrema = new double[2][numBands];
0969:
0970: Rectangle rect = source.getBounds();
0971:
0972: // Initialize extrema with the first pixel value.
0973: // Fix 4810617: Extrema intialization problem; When a ROI
0974: // parameter is used, the ROI may not include the fix pixel
0975: // of the image. So initializing with the first pixel value
0976: // of the image is not correct.
0977: if (roi != null) {
0978: LinkedList rectList = roi.getAsRectangleList(rect.x,
0979: rect.y, rect.width, rect.height);
0980: if (rectList == null) {
0981: return; // ROI does not intersect with Raster boundary.
0982: }
0983: ListIterator iterator = rectList.listIterator(0);
0984: if (iterator.hasNext())
0985: rect = rect.intersection((Rectangle) iterator
0986: .next());
0987: }
0988:
0989: // Find the actual ROI based on start and period.
0990: rect.x = startPosition(rect.x, xStart, xPeriod);
0991: rect.y = startPosition(rect.y, yStart, yPeriod);
0992: source.getPixel(rect.x, rect.y, extrema[0]);
0993:
0994: for (int i = 0; i < numBands; i++) {
0995: extrema[1][i] = extrema[0][i];
0996: }
0997:
0998: if (saveLocations) {
0999: minLocations = new ArrayList[numBands];
1000: maxLocations = new ArrayList[numBands];
1001: minCounts = new int[numBands];
1002: maxCounts = new int[numBands];
1003: for (int i = 0; i < numBands; i++) {
1004: minLocations[i] = new ArrayList();
1005: maxLocations[i] = new ArrayList();
1006: minCounts[i] = maxCounts[i] = 0;
1007: }
1008: }
1009: }
1010: }
1011:
1012: }
|