001: /*
002: * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/opimage/UnaryFunctionOpImage.java,v 1.2 2007/07/03 19:20:16 forklabs Exp $
003: *
004: * Copyright (C) 2007 Forklabs Daniel Léonard
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: */
020:
021: package ca.forklabs.media.jai.opimage;
022:
023: import java.awt.Rectangle;
024: import java.awt.image.ColorModel;
025: import java.awt.image.DataBuffer;
026: import java.awt.image.Raster;
027: import java.awt.image.RenderedImage;
028: import java.awt.image.WritableRaster;
029: import java.util.Map;
030: import javax.media.jai.ColormapOpImage;
031: import javax.media.jai.ImageLayout;
032: import javax.media.jai.OpImage;
033: import javax.media.jai.PlanarImage;
034: import javax.media.jai.RasterAccessor;
035: import javax.media.jai.RasterFormatTag;
036: import ca.forklabs.baselib.util.UnaryFunction;
037: import ca.forklabs.media.jai.operator.UnaryFunctionDescriptor;
038:
039: /**
040: * Class {@code UnaryFunctionOpImage} is an {@link OpImage} implementing the
041: * <em>unaryfunction</em> operation as described in
042: * {@link UnaryFunctionDescriptor}.
043: *
044: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.opimage.UnaryFunctionOpImage">Daniel Léonard</a>
045: * @version $Revision: 1.2 $
046: */
047: public class UnaryFunctionOpImage extends ColormapOpImage {
048: // TODO : add an aspect that will cache the calculation value for any type
049: //---------------------------
050: // Instance variables
051: //---------------------------
052:
053: /** The unary function. */
054: private UnaryFunction<Double, Double> function;
055:
056: //---------------------------
057: // Constructors
058: //---------------------------
059:
060: /**
061: * Constructor.
062: * <p>
063: * The layout of the source is used as the fall-back for the layout of the
064: * destination. Any layout parameters not specified in the {@code layout}
065: * argument are set to the same value as that of the source.
066: * @param source the source image.
067: * @param function the function to apply to the source image.
068: * @param layout the image layout of the destination image.
069: * @param config the configuration of the operation.
070: */
071: public UnaryFunctionOpImage(RenderedImage source,
072: UnaryFunction<Double, Double> function, ImageLayout layout,
073: Map<?, ?> config) {
074: super (source, layout, config, true);
075: this .setup(function);
076: }
077:
078: //---------------------------
079: // Accessors and mutators
080: //---------------------------
081:
082: /**
083: * Changes the function to apply to the image.
084: * @param function the new function.
085: */
086: protected void setUnaryFunction(
087: UnaryFunction<Double, Double> function) {
088: this .function = function;
089: }
090:
091: /**
092: * Gets the function to appy to the image.
093: * @return the function.
094: */
095: protected UnaryFunction<Double, Double> getUnaryFunction() {
096: return this .function;
097: }
098:
099: //---------------------------
100: // Implemented methods from javax.media.jai.ColormapOpImage;
101: //---------------------------
102:
103: /**
104: * Transforms the colormap.
105: * @param color_map the color map.
106: */
107: @SuppressWarnings({"boxing","hiding"})
108: @Override
109: protected void transformColormap(byte[][] color_map) {
110: UnaryFunction<Double, Double> function = this
111: .getUnaryFunction();
112: for (int b = 0, bands = color_map.length; b < bands; b++) {
113: byte[] map = color_map[b];
114: for (int e = 0, entries = map.length; e < entries; e++) {
115: double value = map[e] & 0xFF;
116: map[e] = (byte) (function.invoke(value) + 0.5);
117: }
118: }
119: }
120:
121: //---------------------------
122: // Instance methods
123: //---------------------------
124:
125: /**
126: * Sets up this {@link OpImage}.
127: * @param function the function to apply.
128: */
129: protected void setup(UnaryFunction<Double, Double> function) {
130: this .setUnaryFunction(function);
131: this .permitInPlaceOperation();
132: this .initializeColormapOperation();
133: }
134:
135: /**
136: * Gets the raster format tag for the raster at the given index.
137: * @param index the index of the image.
138: * @return the raster format tag.
139: */
140: protected RasterFormatTag getFormatTag(int index) {
141: RasterFormatTag[] tags = this .getFormatTags();
142: RasterFormatTag tag = tags[index];
143: return tag;
144: }
145:
146: /**
147: * Gets the raster format tag for the given source raster.
148: * @param index the index of the source image.
149: * @return the raster format tag.
150: */
151: protected RasterFormatTag getSourceFormatTag(int index) {
152: RasterFormatTag tag = this .getFormatTag(index);
153: return tag;
154: }
155:
156: /**
157: * Gets the raster format tag for the sink raster.
158: * @return the raster format tag.
159: */
160: protected RasterFormatTag getSinkFormatTag() {
161: // the index of the sink image is the number of images,
162: // all the previous indices are for source images
163: int index = this .getNumSources();
164: RasterFormatTag tag = this .getFormatTag(index);
165: return tag;
166: }
167:
168: /**
169: * Builds a raster accessor for rasters associated with this operation.
170: * @param raster the raster the accessor is for.
171: * @param tag the format tag for the raster.
172: * @param bounds the bounds.
173: * @param color_model the color model.
174: * @return the raster accessor.
175: */
176: protected RasterAccessor buildRasterAccessor(Raster raster,
177: RasterFormatTag tag, Rectangle bounds,
178: ColorModel color_model) {
179: RasterAccessor accessor = new RasterAccessor(raster, bounds,
180: tag, color_model);
181: return accessor;
182: }
183:
184: /**
185: * Builds a raster accessor for the sink raster.
186: * @param raster the sink raster.
187: * @param bounds the bounds.
188: * @return the raster accessor.
189: */
190: protected RasterAccessor buildSinkRasterAccessor(
191: WritableRaster raster, Rectangle bounds) {
192: RasterFormatTag tag = this .getSinkFormatTag();
193: ColorModel color_model = this .getColorModel();
194: RasterAccessor sink_raster_accessor = this .buildRasterAccessor(
195: raster, tag, bounds, color_model);
196: return sink_raster_accessor;
197: }
198:
199: /**
200: * Builds the raster accessor for the source raster at the given index.
201: * @param raster the source raster.
202: * @param bounds the bounds on the sink image.
203: * @param index the index of the source image.
204: * @return the raster accessor.
205: */
206: protected RasterAccessor buildSourceRasterAccessor(Raster raster,
207: Rectangle bounds, int index) {
208: Rectangle source_bounds = this .mapDestRect(bounds, index);
209: RasterFormatTag format_tag = this .getSourceFormatTag(index);
210: PlanarImage source = this .getSourceImage(index);
211: ColorModel color_model = source.getColorModel();
212: RasterAccessor accessor = this .buildRasterAccessor(raster,
213: format_tag, source_bounds, color_model);
214: return accessor;
215: }
216:
217: /**
218: * Builds all the source raster accessors.
219: * @param rasters the source rasters.
220: * @param bounds the bounds.
221: * @return the raster accessors.
222: */
223: protected RasterAccessor[] buildSourceRasterAccessors(
224: Raster[] rasters, Rectangle bounds) {
225: int len = this .getNumSources();
226: RasterAccessor[] accessors = new RasterAccessor[len];
227: for (int i = 0; i < len; i++) {
228: Raster raster = rasters[i];
229: RasterAccessor accessor = this .buildSourceRasterAccessor(
230: raster, bounds, i);
231: accessors[i] = accessor;
232: }
233: return accessors;
234: }
235:
236: /**
237: * Builds the 3-dimensional source matrix.
238: * @param <A> the type of pixels.
239: * @param sources the source rasters.
240: * @param specialization the specialization for the type of pixels.
241: * @return the 3-dimensional source matrix.
242: */
243: protected <A> A[][] buildAllSourceData(RasterAccessor[] sources,
244: PixelSpecialization<A> specialization) {
245: int len = sources.length;
246: A[][] data = specialization.buildAllData(len);
247: for (int i = 0; i < len; i++) {
248: RasterAccessor source = sources[i];
249: data[i] = specialization.extractData(source);
250: }
251: return data;
252: }
253:
254: /**
255: * Resets the line offsets by setting them to their corresponding band
256: * offset.
257: * @param band the current band.
258: * @param band_offsets the band offsets.
259: * @param line_offsets the line offsets.
260: */
261: protected void resetLineOffsets(int band, int[][] band_offsets,
262: int[] line_offsets) {
263: for (int i = 0, len = line_offsets.length; i < len; i++) {
264: line_offsets[i] = band_offsets[i][band];
265: }
266: }
267:
268: /**
269: * Resets the pixel offsets by setting them to their corresponding line
270: * offset.
271: * @param line_offsets the line offsets.
272: * @param pixel_offsets the pixel offsets.
273: */
274: protected void resetPixelOffsets(int[] line_offsets,
275: int[] pixel_offsets) {
276: for (int i = 0, len = pixel_offsets.length; i < len; i++) {
277: pixel_offsets[i] = line_offsets[i];
278: }
279: }
280:
281: /**
282: * Increments the pixel offsets by their corresponding pixel strides.
283: * @param pixel_offsets the pixel offsets.
284: * @param pixel_strides the pixel strides.
285: */
286: protected void incrementPixelOffsets(int[] pixel_offsets,
287: int[] pixel_strides) {
288: for (int i = 0, len = pixel_offsets.length; i < len; i++) {
289: pixel_offsets[i] += pixel_strides[i];
290: }
291: }
292:
293: /**
294: * Increments the line offsets by their corresponding line strides.
295: * @param line_offsets the line offsets.
296: * @param line_strides the line strides.
297: */
298: protected void incrementLineOffsets(int[] line_offsets,
299: int[] line_strides) {
300: for (int i = 0, len = line_offsets.length; i < len; i++) {
301: line_offsets[i] += line_strides[i];
302: }
303: }
304:
305: /**
306: * Really computes the image.
307: * @param sources the source raster accessors.
308: * @param sink the sink raster accessor.
309: * @param specialization the pixel specialization.
310: * @param <A> the type of pixel (as an array of that type).
311: */
312: @SuppressWarnings({"boxing","hiding"})
313: protected <A> void compute(RasterAccessor[] sources,
314: RasterAccessor sink, PixelSpecialization<A> specialization) {
315: // If an image is broken into tiles, method computeRect() is called once for
316: // each tile, the rectangle bounds defining the tile.
317: //
318: // The band offset give the position of the first pixel (in a band), that is the
319: // pixel at position (0, 0) IN the tile - which can be anywhere in the image.
320: //
321: // The line stride gives the distance from a pixel on one line to the
322: // corresponding pixel on the next line. It can be seen as the width of the
323: // whole image (an NOT the width of the tile).
324: //
325: // The pixel stride gives the distance between to pixels on the same row.
326: //
327: // The formula to get to any pixel in the tile is as follow :
328: //
329: // pixel_offset = band_offset + (y * line_stride) + (x * pixel_stride)
330: //
331: // where 'x' and 'y' are the coordinate of the pixel IN the tile space (and not
332: // in the image space).
333: //
334: // The image data structure as represented as a matrix. All the pixels of one
335: // band are laid out in row major configuration in a single array (see the
336: // formula above) and all the bands are put together in another array, giving
337: // the matrix. Thus the first dimension of the array represents the band and
338: // the second represents the pixel. A pixel in band 'b' at position 'p' is
339: // accessed like that :
340: //
341: // data[b][p]
342: //
343: //
344: // Now, given that, here is how this code works. The pixels are traversed top to
345: // bottom, left to right (loops on 'w' and on 'h'). Finally this process is
346: // repeated for each band (loop on 'b').
347: //
348: // To prevent the calculation of the pixel offset at each pixel with the formula
349: // above, and since at any given time we are interested with the same
350: // corresponding pixel in all images, source and sink alike, the pixel offset
351: // are calculated incrementally. In any given band, the offset of the first
352: // pixel, (0, 0) is 'band_offset'. This value, for each image, is kept in the
353: // line offset memory, the beginning of each new line being :
354: //
355: // 'band_offset + (h * line_stride)'
356: //
357: // or :
358: //
359: // 'band_offset += line_stride'
360: //
361: // for each new line after the first one. Using the 'line_offset', the position
362: // of each pixel is calculated by incrementing a copy of that offset by the
363: // 'pixel_stride'.
364:
365: int images = sources.length;
366:
367: // the values of each source image is stored at its corresponding index
368: // while the values of the sink image are stored at the last position, at
369: // index 'images'
370: int[] line_strides = new int[images + 1];
371: int[] pixel_strides = new int[images + 1];
372: int[][] band_offsets = new int[images + 1][];
373: for (int i = 0; i < images; i++) {
374: RasterAccessor source = sources[i];
375: line_strides[i] = source.getScanlineStride();
376: pixel_strides[i] = source.getPixelStride();
377: band_offsets[i] = source.getBandOffsets();
378: }
379: line_strides[images] = sink.getScanlineStride();
380: pixel_strides[images] = sink.getPixelStride();
381: band_offsets[images] = sink.getBandOffsets();
382:
383: int[] line_offsets = new int[images + 1];
384: int[] pixel_offsets = new int[images + 1];
385:
386: A[][] all_source_data = this .buildAllSourceData(sources,
387: specialization);
388: A[] sink_data = specialization.extractData(sink);
389: int bands = sink.getNumBands();
390: int height = sink.getHeight();
391: int width = sink.getWidth();
392: UnaryFunction<Double, Double> function = this
393: .getUnaryFunction();
394:
395: for (int b = 0; b < bands; b++) {
396: this .resetLineOffsets(b, band_offsets, line_offsets);
397: for (int h = 0; h < height; h++) {
398: this .resetPixelOffsets(line_offsets, pixel_offsets);
399: for (int w = 0; w < width; w++) {
400: int source_index = 0;
401: double value = specialization.extractPixelValueAt(
402: all_source_data, source_index, b,
403: pixel_offsets[0]);
404:
405: value = function.invoke(value);
406:
407: specialization.setPixelValueAt(value, sink_data, b,
408: pixel_offsets[images]);
409:
410: this .incrementPixelOffsets(pixel_offsets,
411: pixel_strides);
412: }
413: this .incrementLineOffsets(line_offsets, line_strides);
414: }
415: }
416: }
417:
418: /**
419: * Compute the image for images with bytes as the data type.
420: * @param sources the source images.
421: * @param sink the sink image.
422: */
423: protected void computeByte(RasterAccessor[] sources,
424: RasterAccessor sink) {
425: PixelSpecialization<byte[]> specialization = UnaryFunctionOpImage.BYTE_SPECIALIZATION;
426: this .compute(sources, sink, specialization);
427: }
428:
429: /**
430: * Compute the image for images with shorts as the data type.
431: * @param sources the source images.
432: * @param sink the sink image.
433: */
434: protected void computeShort(RasterAccessor[] sources,
435: RasterAccessor sink) {
436: PixelSpecialization<short[]> specialization = UnaryFunctionOpImage.SHORT_SPECIALIZATION;
437: this .compute(sources, sink, specialization);
438: }
439:
440: /**
441: * Compute the image for images with unsigned shorts as the data type.
442: * @param sources the source images.
443: * @param sink the sink image.
444: */
445: protected void computeUShort(RasterAccessor[] sources,
446: RasterAccessor sink) {
447: PixelSpecialization<short[]> specialization = UnaryFunctionOpImage.U_SHORT_SPECIALIZATION;
448: this .compute(sources, sink, specialization);
449: }
450:
451: /**
452: * Compute the image for images with integers as the data type.
453: * @param sources the source images.
454: * @param sink the sink image.
455: */
456: protected void computeInt(RasterAccessor[] sources,
457: RasterAccessor sink) {
458: PixelSpecialization<int[]> specialization = UnaryFunctionOpImage.INT_SPECIALIZATION;
459: this .compute(sources, sink, specialization);
460: }
461:
462: /**
463: * Compute the image for images with floats as the data type.
464: * @param sources the source images.
465: * @param sink the sink image.
466: */
467: protected void computeFloat(RasterAccessor[] sources,
468: RasterAccessor sink) {
469: PixelSpecialization<float[]> specialization = UnaryFunctionOpImage.FLOAT_SPECIALIZATION;
470: this .compute(sources, sink, specialization);
471: }
472:
473: /**
474: * Compute the image for images with doubles as the data type.
475: * @param sources the source images.
476: * @param sink the sink image.
477: */
478: protected void computeDouble(RasterAccessor[] sources,
479: RasterAccessor sink) {
480: PixelSpecialization<double[]> specialization = UnaryFunctionOpImage.DOUBLE_SPECIALIZATION;
481: this .compute(sources, sink, specialization);
482: }
483:
484: /**
485: * Computes the image.
486: * @param sources the source image.
487: * @param sink the median image.
488: */
489: protected void compute(RasterAccessor[] sources, RasterAccessor sink) {
490: int data_type = sink.getDataType();
491: switch (data_type) {
492: case DataBuffer.TYPE_BYTE:
493: this .computeByte(sources, sink);
494: break;
495: case DataBuffer.TYPE_USHORT:
496: this .computeUShort(sources, sink);
497: break;
498: case DataBuffer.TYPE_SHORT:
499: this .computeShort(sources, sink);
500: break;
501: case DataBuffer.TYPE_INT:
502: this .computeInt(sources, sink);
503: break;
504: case DataBuffer.TYPE_FLOAT:
505: this .computeFloat(sources, sink);
506: break;
507: case DataBuffer.TYPE_DOUBLE:
508: this .computeDouble(sources, sink);
509: break;
510: default:
511: String message = this
512: .getUnknownDataTypeErrorMessage(data_type);
513: throw new IllegalStateException(message);
514: }
515: }
516:
517: /**
518: * Gets the error message telling that the raster data type is unknown.
519: * @param type the bad type.
520: * @return the formatted error message.
521: */
522: @SuppressWarnings("boxing")
523: protected String getUnknownDataTypeErrorMessage(int type) {
524: String key = Resources.UNKNOWN_DATA_TYPE;
525: String message = Resources.getLocalizedString(key, type);
526: return message;
527: }
528:
529: //---------------------------
530: // Overriden methods from javax.media.jai.OpImage
531: //---------------------------
532:
533: /**
534: * Calculates the median of the corresponding pixels of the source images
535: * within a specified rectangle.
536: * @param sources the cobbled sources.
537: * @param sink the raster for each calculation.
538: * @param bounds the region of interest.
539: */
540: @Override
541: protected void computeRect(Raster[] sources, WritableRaster sink,
542: Rectangle bounds) {
543: RasterAccessor[] source_accessors = this
544: .buildSourceRasterAccessors(sources, bounds);
545: RasterAccessor sink_accessor = this .buildSinkRasterAccessor(
546: sink, bounds);
547:
548: this .compute(source_accessors, sink_accessor);
549:
550: if (sink_accessor.needsClamping()) {
551: sink_accessor.clampDataArrays();
552: }
553: sink_accessor.copyDataToRaster();
554: }
555:
556: //---------------------------
557: // Inner classes
558: //---------------------------
559:
560: /**
561: * Class {@code PixelSpecialization} specializes pixel manipulation on the
562: * array type.
563: * <p>
564: * It is impossible to use generics on primitive data types, but not on
565: * <em>arrays</em> of primitive data type.
566: *
567: * @param <A> the array type (such as {@code byte[]} or {@code int[]}).
568: *
569: * @author <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.operator.UnaryFunctionOpImage$PixelSpecialization">Daniel Léonard</a>
570: * @version $Revision: 1.2 $
571: */
572: protected static abstract class PixelSpecialization<A> {
573:
574: /**
575: * Builds the 3-dimensional source matrix. The first dimension represents
576: * the different source images, the second dimension represents individual
577: * bands inside a single source image and the last dimension contains all
578: * the pixels.
579: * @param len the size of the first dimension, the number of source
580: * images.
581: * @return the source matrix.
582: */
583: public abstract A[][] buildAllData(int len);
584:
585: /**
586: * Extracts the 2-dimensional data matrix from the given image raster. The
587: * first dimension represents the individual bands inside the image and
588: * the last dimension contains all the pixels.
589: * @param accessor the raster accessor over the image raster.
590: * @return the image matrix.
591: */
592: public abstract A[] extractData(RasterAccessor accessor);
593:
594: /**
595: * Extracts the specified pixel, basically doing :
596: * <blockquote><code>
597: * double value = all_data[image][band][pixel];
598: * return value;
599: * </code></blockquote>
600: * @param all_data the 3-dimensional source matrix
601: * @param image the image position in the source matrix.
602: * @param band the band position in the source image.
603: * @param pixel the pixel position in the band.
604: * @return the pixel value.
605: */
606: public abstract double extractPixelValueAt(A[][] all_data,
607: int image, int band, int pixel);
608:
609: /**
610: * Changes the given pixel.
611: * @param value the new pixel value.
612: * @param data the image data.
613: * @param band the band position in the image.
614: * @param pixel the pixel position in the band.
615: */
616: public abstract void setPixelValueAt(double value, A[] data,
617: int band, int pixel);
618:
619: }
620:
621: //---------------------------
622: // Class variables
623: //---------------------------
624:
625: /** Specialization for data of type <em>byte</em>. */
626: protected static PixelSpecialization<byte[]> BYTE_SPECIALIZATION = new PixelSpecialization<byte[]>() {
627:
628: @Override
629: public byte[][][] buildAllData(int len) {
630: byte[][][] all_data = new byte[len][][];
631: return all_data;
632: }
633:
634: @Override
635: public byte[][] extractData(RasterAccessor raster_accessor) {
636: byte[][] data = raster_accessor.getByteDataArrays();
637: return data;
638: }
639:
640: @Override
641: public double extractPixelValueAt(byte[][][] all_data,
642: int image, int band, int pixel) {
643: double value = all_data[image][band][pixel] & 0xff;
644: return value;
645: }
646:
647: @Override
648: public void setPixelValueAt(double value, byte[][] sink_data,
649: int band, int pixel) {
650: sink_data[band][pixel] = (byte) (value + 0.5);
651: }
652:
653: };
654:
655: /** Specialization for data of type <em>short</em>. */
656: protected static PixelSpecialization<short[]> SHORT_SPECIALIZATION = new PixelSpecialization<short[]>() {
657:
658: @Override
659: public short[][][] buildAllData(int len) {
660: short[][][] all_data = new short[len][][];
661: return all_data;
662: }
663:
664: @Override
665: public short[][] extractData(RasterAccessor raster_accessor) {
666: short[][] data = raster_accessor.getShortDataArrays();
667: return data;
668: }
669:
670: @Override
671: public double extractPixelValueAt(short[][][] all_data,
672: int image, int band, int pixel) {
673: double value = all_data[image][band][pixel];
674: return value;
675: }
676:
677: @Override
678: public void setPixelValueAt(double value, short[][] sink_data,
679: int band, int pixel) {
680: sink_data[band][pixel] = (short) (value + 0.5);
681: }
682:
683: };
684:
685: /** Specialization for data of type <em>unsigned short</em>. */
686: protected static PixelSpecialization<short[]> U_SHORT_SPECIALIZATION = new PixelSpecialization<short[]>() {
687:
688: @Override
689: public short[][][] buildAllData(int len) {
690: short[][][] all_data = new short[len][][];
691: return all_data;
692: }
693:
694: @Override
695: public short[][] extractData(RasterAccessor raster_accessor) {
696: short[][] data = raster_accessor.getShortDataArrays();
697: return data;
698: }
699:
700: @Override
701: public double extractPixelValueAt(short[][][] all_data,
702: int image, int band, int pixel) {
703: double value = all_data[image][band][pixel] & 0xffff;
704: return value;
705: }
706:
707: @Override
708: public void setPixelValueAt(double value, short[][] sink_data,
709: int band, int pixel) {
710: sink_data[band][pixel] = (short) (value + 0.5);
711: }
712:
713: };
714:
715: /** Specialization for data of type <em>int</em>. */
716: protected static PixelSpecialization<int[]> INT_SPECIALIZATION = new PixelSpecialization<int[]>() {
717:
718: @Override
719: public int[][][] buildAllData(int len) {
720: int[][][] all_data = new int[len][][];
721: return all_data;
722: }
723:
724: @Override
725: public int[][] extractData(RasterAccessor raster_accessor) {
726: int[][] data = raster_accessor.getIntDataArrays();
727: return data;
728: }
729:
730: @Override
731: public double extractPixelValueAt(int[][][] all_data,
732: int image, int band, int pixel) {
733: double value = all_data[image][band][pixel];
734: return value;
735: }
736:
737: @Override
738: public void setPixelValueAt(double value, int[][] sink_data,
739: int band, int pixel) {
740: sink_data[band][pixel] = (int) (value + 0.5);
741: }
742:
743: };
744:
745: /** Specialization for data of type <em>float</em>. */
746: protected static PixelSpecialization<float[]> FLOAT_SPECIALIZATION = new PixelSpecialization<float[]>() {
747:
748: @Override
749: public float[][][] buildAllData(int len) {
750: float[][][] all_data = new float[len][][];
751: return all_data;
752: }
753:
754: @Override
755: public float[][] extractData(RasterAccessor raster_accessor) {
756: float[][] data = raster_accessor.getFloatDataArrays();
757: return data;
758: }
759:
760: @Override
761: public double extractPixelValueAt(float[][][] all_data,
762: int image, int band, int pixel) {
763: double value = all_data[image][band][pixel];
764: return value;
765: }
766:
767: @Override
768: public void setPixelValueAt(double value, float[][] sink_data,
769: int band, int pixel) {
770: sink_data[band][pixel] = (float) value;
771: }
772:
773: };
774:
775: /** Specialization for data of type <em>double</em>. */
776: protected static PixelSpecialization<double[]> DOUBLE_SPECIALIZATION = new PixelSpecialization<double[]>() {
777:
778: @Override
779: public double[][][] buildAllData(int len) {
780: double[][][] all_data = new double[len][][];
781: return all_data;
782: }
783:
784: @Override
785: public double[][] extractData(RasterAccessor raster_accessor) {
786: double[][] data = raster_accessor.getDoubleDataArrays();
787: return data;
788: }
789:
790: @Override
791: public double extractPixelValueAt(double[][][] all_data,
792: int image, int band, int pixel) {
793: double value = all_data[image][band][pixel];
794: return value;
795: }
796:
797: @Override
798: public void setPixelValueAt(double value, double[][] sink_data,
799: int band, int pixel) {
800: sink_data[band][pixel] = value;
801: }
802:
803: };
804:
805: }
806:
807: /*
808: * $Log: UnaryFunctionOpImage.java,v $
809: * Revision 1.2 2007/07/03 19:20:16 forklabs
810: * * javadoc *
811: *
812: * Revision 1.1 2007/05/03 18:32:29 forklabs
813: * Initial commit for the unaryfunction operator.
814: *
815: */
|