Source Code Cross Referenced for MedianCollectionOpImage.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » ca » forklabs » media » jai » opimage » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » ca.forklabs.media.jai.opimage 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#) $Header: /cvs/jai-operators/src/main/ca/forklabs/media/jai/opimage/MedianCollectionOpImage.java,v 1.2 2007/07/05 18:24:15 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.WritableRaster;
028:        import java.util.Arrays;
029:        import java.util.Map;
030:        import javax.media.jai.CollectionImage;
031:        import javax.media.jai.ImageLayout;
032:        import javax.media.jai.OpImage;
033:        import javax.media.jai.PlanarImage;
034:        import javax.media.jai.PointOpImage;
035:        import javax.media.jai.RasterAccessor;
036:        import javax.media.jai.RasterFormatTag;
037:        import ca.forklabs.media.jai.OpImageUtil;
038:        import ca.forklabs.media.jai.operator.MedianCollectionDescriptor;
039:
040:        /**
041:         * Class {@link MedianCollectionOpImage} is an {@link OpImage} implementing the
042:         * <em>MedianCollection</em> operation.
043:         *
044:         * @author   <a href="mailto:forklabs at dev.java.net?subject=ca.forklabs.media.jai.opimage.MedianCollectionOpImage">Daniel Léonard</a>
045:         * @version $Revision: 1.2 $
046:         * @see MedianCollectionDescriptor
047:         * @see MedianCollectionCRIF
048:         */
049:        public class MedianCollectionOpImage extends PointOpImage {
050:
051:            //---------------------------
052:            // Class variables
053:            //---------------------------
054:
055:            // exceptionnally, class variables are at the end of the file
056:
057:            //---------------------------
058:            // Constructor
059:            //---------------------------
060:
061:            /**
062:             * Constructor.
063:             * @param   sources   the collection of rendered images.
064:             * @param   config   the rendering hints.
065:             * @param   layout   the image layout.
066:             */
067:            @SuppressWarnings("unchecked")
068:            public MedianCollectionOpImage(CollectionImage sources,
069:                    Map<?, ?> config, ImageLayout layout) {
070:                super (OpImageUtil.vectorize(sources), layout, config, true);
071:            }
072:
073:            //---------------------------
074:            // Instance methods
075:            //---------------------------
076:
077:            /**
078:             * Gets the raster format tag for the image at the given index.
079:             * @param   index   the index of the image.
080:             * @return   the raster format tag.
081:             */
082:            protected RasterFormatTag getFormatTag(int index) {
083:                RasterFormatTag[] tags = this .getFormatTags();
084:                RasterFormatTag tag = tags[index];
085:                return tag;
086:            }
087:
088:            /**
089:             * Gets the raster format tag for the given source image.
090:             * @param   index   the index of the source image.
091:             * @return   the raster format tag.
092:             */
093:            protected RasterFormatTag getSourceFormatTag(int index) {
094:                RasterFormatTag tag = this .getFormatTag(index);
095:                return tag;
096:            }
097:
098:            /**
099:             * Gets the raster format tag for the sink image.
100:             * @return   the raster format tag.
101:             */
102:            protected RasterFormatTag getSinkFormatTag() {
103:                // the index of the sink image is the number of images,
104:                // all the previous indices are for source images
105:                int index = this .getNumSources();
106:                RasterFormatTag tag = this .getFormatTag(index);
107:                return tag;
108:            }
109:
110:            /**
111:             * Builds a raster accessor for rasters associated with this operation.
112:             * @param   raster   the raster the accessor is for.
113:             * @param   tag   the format tag for the raster.
114:             * @param   bounds   the bounds.
115:             * @param   color_model   the color model.
116:             * @return   the raster accessor.
117:             */
118:            protected RasterAccessor buildRasterAccessor(Raster raster,
119:                    RasterFormatTag tag, Rectangle bounds,
120:                    ColorModel color_model) {
121:                RasterAccessor accessor = new RasterAccessor(raster, bounds,
122:                        tag, color_model);
123:                return accessor;
124:            }
125:
126:            /**
127:             * Builds a raster accessor for the sink image.
128:             * @param   raster   the raster of the sink image.
129:             * @param   bounds   the bounds.
130:             * @return   the raster accessor.
131:             */
132:            protected RasterAccessor buildSinkRasterAccessor(
133:                    WritableRaster raster, Rectangle bounds) {
134:                RasterFormatTag tag = this .getSinkFormatTag();
135:                ColorModel color_model = this .getColorModel();
136:                RasterAccessor sink_raster_accessor = this .buildRasterAccessor(
137:                        raster, tag, bounds, color_model);
138:                return sink_raster_accessor;
139:            }
140:
141:            /**
142:             * Builds the raster accessor for the source image at the given index.
143:             * @param   raster   the source raster.
144:             * @param   bounds   the bounds on the sink image.
145:             * @param   index   the index of the source image.
146:             * @return   the raster accessor.
147:             */
148:            protected RasterAccessor buildSourceRasterAccessor(Raster raster,
149:                    Rectangle bounds, int index) {
150:                Rectangle source_bounds = this .mapDestRect(bounds, index);
151:                RasterFormatTag format_tag = this .getSourceFormatTag(index);
152:                PlanarImage source = this .getSourceImage(index);
153:                ColorModel color_model = source.getColorModel();
154:                RasterAccessor accessor = this .buildRasterAccessor(raster,
155:                        format_tag, source_bounds, color_model);
156:                return accessor;
157:            }
158:
159:            /**
160:             * Builds all the source raster accessors.
161:             * @param   rasters   the source rasters.
162:             * @param   bounds   the bounds.
163:             * @return   the raster accessors.
164:             */
165:            protected RasterAccessor[] buildSourceRasterAccessors(
166:                    Raster[] rasters, Rectangle bounds) {
167:                int len = this .getNumSources();
168:                RasterAccessor[] accessors = new RasterAccessor[len];
169:                for (int i = 0; i < len; i++) {
170:                    Raster raster = rasters[i];
171:                    RasterAccessor accessor = this .buildSourceRasterAccessor(
172:                            raster, bounds, i);
173:                    accessors[i] = accessor;
174:                }
175:                return accessors;
176:            }
177:
178:            /**
179:             * Finds the median value.
180:             * @param   values   the population to find the median in.
181:             * @return   the median.
182:             * @exception   ArithmeticException   if the population size is <em>0</em>.
183:             */
184:            protected double computeMedian(double[] values) {
185:                Arrays.sort(values);
186:
187:                // there is are no checks to see if the array is
188:                // null or of length 0, that would mean there are
189:                // no source images, a much bigger problem
190:                int len = values.length;
191:                int middle = len / 2;
192:                boolean is_even = (0 == (len % 2));
193:
194:                double median;
195:                if (is_even) {
196:                    double d1 = values[middle - 1];
197:                    double d2 = values[middle - 0];
198:                    median = (d1 + d2) / 2;
199:                } else {
200:                    median = values[middle];
201:                }
202:
203:                return median;
204:            }
205:
206:            /**
207:             * Builds the 3-dimensional source matrix.
208:             * @param   <A>   the type of pixels.
209:             * @param   sources   the source rasters.
210:             * @param   specialization   the specialization for the type of pixels.
211:             * @return   the 3-dimensional source matrix.
212:             */
213:            protected <A> A[][] buildAllSourceData(RasterAccessor[] sources,
214:                    PixelSpecialization<A> specialization) {
215:                int len = sources.length;
216:                A[][] data = specialization.buildAllData(len);
217:                for (int i = 0; i < len; i++) {
218:                    RasterAccessor source = sources[i];
219:                    data[i] = specialization.extractData(source);
220:                }
221:                return data;
222:            }
223:
224:            /**
225:             * Resets the line offsets by setting them to their corresponding band
226:             * offset.
227:             * @param   band   the current band.
228:             * @param   band_offsets   the band offsets.
229:             * @param   line_offsets   the line offsets.
230:             */
231:            protected void resetLineOffsets(int band, int[][] band_offsets,
232:                    int[] line_offsets) {
233:                for (int i = 0, len = line_offsets.length; i < len; i++) {
234:                    line_offsets[i] = band_offsets[i][band];
235:                }
236:            }
237:
238:            /**
239:             * Resets the pixel offsets by setting them to their corresponding line
240:             * offset.
241:             * @param   line_offsets   the line offsets.
242:             * @param   pixel_offsets   the pixel offsets.
243:             */
244:            protected void resetPixelOffsets(int[] line_offsets,
245:                    int[] pixel_offsets) {
246:                for (int i = 0, len = pixel_offsets.length; i < len; i++) {
247:                    pixel_offsets[i] = line_offsets[i];
248:                }
249:            }
250:
251:            /**
252:             * Increments the pixel offsets by their corresponding pixel strides.
253:             * @param   pixel_offsets   the pixel offsets.
254:             * @param   pixel_strides   the pixel strides.
255:             */
256:            protected void incrementPixelOffsets(int[] pixel_offsets,
257:                    int[] pixel_strides) {
258:                for (int i = 0, len = pixel_offsets.length; i < len; i++) {
259:                    pixel_offsets[i] += pixel_strides[i];
260:                }
261:            }
262:
263:            /**
264:             * Increments the line offsets by their corresponding line strides.
265:             * @param   line_offsets   the line offsets.
266:             * @param   line_strides   the line strides.
267:             */
268:            protected void incrementLineOffsets(int[] line_offsets,
269:                    int[] line_strides) {
270:                for (int i = 0, len = line_offsets.length; i < len; i++) {
271:                    line_offsets[i] += line_strides[i];
272:                }
273:            }
274:
275:            /**
276:             * Computes the median of the source images.
277:             * @param   <A>   the type of pixels.
278:             * @param   sources   the source rasters.
279:             * @param   sink   the sink raster.
280:             * @param   specialization   the specialization for the type of pixels.
281:             */
282:            @SuppressWarnings("hiding")
283:            protected <A> void computeMedian(RasterAccessor[] sources,
284:                    RasterAccessor sink, PixelSpecialization<A> specialization) {
285:                // If an image is broken into tiles, method computeRect() is called once for
286:                // each tile, the rectangle bounds defining the tile.
287:                //
288:                // The band offset give the position of the first pixel (in a band), that is the
289:                // pixel at position (0, 0) IN the tile - which can be anywhere in the image.
290:                //
291:                // The line stride gives the distance from a pixel on one line to the
292:                // corresponding pixel on the next line. It can be seen as the width of the
293:                // whole image (an NOT the width of the tile).
294:                //
295:                // The pixel stride gives the distance between to pixels on the same row.
296:                //
297:                // The formula to get to any pixel in the tile is as follow :
298:                //
299:                //   pixel_offset = band_offset + (y * line_stride) + (x * pixel_stride)
300:                //
301:                // where 'x' and 'y' are the coordinate of the pixel IN the tile space (and not
302:                // in the image space).
303:                //
304:                // The image data structure as represented as a matrix. All the pixels of one
305:                // band are laid out in row major configuration in a single array (see the
306:                // formula above) and all the bands are put together in another array, giving
307:                // the matrix. Thus the first dimension of the array represents the band and
308:                // the second represents the pixel. A pixel in band 'b' at position 'p' is
309:                // accessed like that :
310:                //
311:                //    data[b][p]
312:                //
313:                //
314:                // Now, given that, here is how this code works. To calculate the median of any
315:                // pixel, we need the value of each corresponding pixel in all the images. The
316:                // inner loop (on 'i') is thus on the source images. The pixels are traversed
317:                // top to bottom, left to right (loops on 'w' and on 'h'). Finally this process
318:                // is repeated for each band (loop on 'b').
319:                //
320:                // To prevent the calculation of the pixel offset at each pixel with the formula
321:                // above, and since at any given time we are interested with the same
322:                // corresponding pixel in all images, source and sink alike, the pixel offset
323:                // are calculated incrementally. In any given band, the offset of the first
324:                // pixel, (0, 0) is 'band_offset'. This value, for each image, is kept in the
325:                // line offset memory, the beginning of each new line being :
326:                //
327:                //    'band_offset + (h * line_stride)'
328:                //
329:                // or :
330:                //
331:                //    'band_offset += line_stride'
332:                //
333:                // for each new line after the first one. Using the 'line_offset', the position
334:                // of each pixel is calculated by incrementing a copy of that offset by the
335:                // 'pixel_stride'.
336:
337:                int images = sources.length;
338:
339:                // the values of each source image is stored at its corresponding index
340:                // while the values of the sink image are stored at the last position, at
341:                // index 'images'
342:                int[] line_strides = new int[images + 1];
343:                int[] pixel_strides = new int[images + 1];
344:                int[][] band_offsets = new int[images + 1][];
345:                for (int i = 0; i < images; i++) {
346:                    RasterAccessor source = sources[i];
347:                    line_strides[i] = source.getScanlineStride();
348:                    pixel_strides[i] = source.getPixelStride();
349:                    band_offsets[i] = source.getBandOffsets();
350:                }
351:                line_strides[images] = sink.getScanlineStride();
352:                pixel_strides[images] = sink.getPixelStride();
353:                band_offsets[images] = sink.getBandOffsets();
354:
355:                int[] line_offsets = new int[images + 1];
356:                int[] pixel_offsets = new int[images + 1];
357:
358:                A[][] all_source_data = this .buildAllSourceData(sources,
359:                        specialization);
360:                A[] sink_data = specialization.extractData(sink);
361:                double[] values = new double[images];
362:                int bands = sink.getNumBands();
363:                int height = sink.getHeight();
364:                int width = sink.getWidth();
365:
366:                for (int b = 0; b < bands; b++) {
367:                    this .resetLineOffsets(b, band_offsets, line_offsets);
368:                    for (int h = 0; h < height; h++) {
369:                        this .resetPixelOffsets(line_offsets, pixel_offsets);
370:                        for (int w = 0; w < width; w++) {
371:                            for (int i = 0; i < images; i++) {
372:                                values[i] = specialization
373:                                        .extractPixelValueAt(all_source_data,
374:                                                i, b, pixel_offsets[i]);
375:                            }
376:                            double median = this .computeMedian(values);
377:                            specialization.setPixelValueAt(median, sink_data,
378:                                    b, pixel_offsets[images]);
379:                            this .incrementPixelOffsets(pixel_offsets,
380:                                    pixel_strides);
381:                        }
382:                        this .incrementLineOffsets(line_offsets, line_strides);
383:                    }
384:                }
385:            }
386:
387:            /**
388:             * Compute the median image for images with bytes as the data type.
389:             * @param   sources   the source images.
390:             * @param   sink   the sink image.
391:             */
392:            protected void computeMedianByte(RasterAccessor[] sources,
393:                    RasterAccessor sink) {
394:                PixelSpecialization<byte[]> specialization = MedianCollectionOpImage.BYTE_SPECIALIZATION;
395:                this .computeMedian(sources, sink, specialization);
396:            }
397:
398:            /**
399:             * Compute the median image for images with shorts as the data type.
400:             * @param   sources   the source images.
401:             * @param   sink   the sink image.
402:             */
403:            protected void computeMedianShort(RasterAccessor[] sources,
404:                    RasterAccessor sink) {
405:                PixelSpecialization<short[]> specialization = MedianCollectionOpImage.SHORT_SPECIALIZATION;
406:                this .computeMedian(sources, sink, specialization);
407:            }
408:
409:            /**
410:             * Compute the median image for images with integers as the data type.
411:             * @param   sources   the source images.
412:             * @param   sink   the sink image.
413:             */
414:            protected void computeMedianInt(RasterAccessor[] sources,
415:                    RasterAccessor sink) {
416:                PixelSpecialization<int[]> specialization = MedianCollectionOpImage.INT_SPECIALIZATION;
417:                this .computeMedian(sources, sink, specialization);
418:            }
419:
420:            /**
421:             * Compute the median image for images with floats as the data type.
422:             * @param   sources   the source images.
423:             * @param   sink   the sink image.
424:             */
425:            protected void computeMedianFloat(RasterAccessor[] sources,
426:                    RasterAccessor sink) {
427:                PixelSpecialization<float[]> specialization = MedianCollectionOpImage.FLOAT_SPECIALIZATION;
428:                this .computeMedian(sources, sink, specialization);
429:            }
430:
431:            /**
432:             * Compute the median image for images with doubles as the data type.
433:             * @param   sources   the source images.
434:             * @param   sink   the sink image.
435:             */
436:            protected void computeMedianDouble(RasterAccessor[] sources,
437:                    RasterAccessor sink) {
438:                PixelSpecialization<double[]> specialization = MedianCollectionOpImage.DOUBLE_SPECIALIZATION;
439:                this .computeMedian(sources, sink, specialization);
440:            }
441:
442:            /**
443:             * Computes the median image.
444:             * @param   sources   the source image.
445:             * @param   sink   the median image.
446:             */
447:            protected void computeMedian(RasterAccessor[] sources,
448:                    RasterAccessor sink) {
449:                int data_type = sink.getDataType();
450:                switch (data_type) {
451:                case DataBuffer.TYPE_BYTE:
452:                    this .computeMedianByte(sources, sink);
453:                    break;
454:                case DataBuffer.TYPE_USHORT:
455:                case DataBuffer.TYPE_SHORT:
456:                    this .computeMedianShort(sources, sink);
457:                    break;
458:                case DataBuffer.TYPE_INT:
459:                    this .computeMedianInt(sources, sink);
460:                    break;
461:                case DataBuffer.TYPE_FLOAT:
462:                    this .computeMedianFloat(sources, sink);
463:                    break;
464:                case DataBuffer.TYPE_DOUBLE:
465:                    this .computeMedianDouble(sources, sink);
466:                    break;
467:                default:
468:                    String message = this 
469:                            .getUnknownDataTypeErrorMessage(data_type);
470:                    throw new IllegalStateException(message);
471:                }
472:            }
473:
474:            /**
475:             * Gets the error message telling that the raster data type is unknown.
476:             * @param   type   the bad type.
477:             * @return   the formatted error message.
478:             */
479:            @SuppressWarnings("boxing")
480:            protected String getUnknownDataTypeErrorMessage(int type) {
481:                String key = Resources.UNKNOWN_DATA_TYPE;
482:                String message = Resources.getLocalizedString(key, type);
483:                return message;
484:            }
485:
486:            //---------------------------
487:            // Overriden methods from javax.media.jai.OpImage
488:            //---------------------------
489:
490:            /**
491:             * Calculates the median of the corresponding pixels of the source images
492:             * within a specified rectangle.
493:             * @param   sources   the cobbled sources.
494:             * @param   sink      the raster for each calculation.
495:             * @param   bounds   the region of interest.
496:             */
497:            @Override
498:            protected void computeRect(Raster[] sources, WritableRaster sink,
499:                    Rectangle bounds) {
500:                RasterAccessor[] source_accessors = this 
501:                        .buildSourceRasterAccessors(sources, bounds);
502:                RasterAccessor sink_accessor = this .buildSinkRasterAccessor(
503:                        sink, bounds);
504:
505:                this .computeMedian(source_accessors, sink_accessor);
506:
507:                if (sink_accessor.needsClamping()) {
508:                    sink_accessor.clampDataArrays();
509:                }
510:                sink_accessor.copyDataToRaster();
511:            }
512:
513:            //---------------------------
514:            // Inner classes
515:            //---------------------------
516:
517:            /**
518:             * Class {@code PixelSpecialization} specializes the median calculation
519:             * algorithm on the array type.
520:             * <p>
521:             * It is impossible to use generics on primitive data types, but not on
522:             * <em>arrays</em> of primitive data type. The median calculation algorithm,
523:             * making extensive uses of multi-dimensional arrays, is a good candidate for
524:             * a <em>template method</em> (especially since its inspiration is the core
525:             * algorithm from <em>AddCollection</em>, algorithm duplicated for each
526:             * numeric data type).
527:             *
528:             * @param   <A>   the array type (such as {@code byte[]} or {@code int[]}).
529:             *
530:             * @author   <a href="mailto:daniel.leonard at umontreal.ca?subject=ca.umontreal.iro.image.arcticice.media.jai.operator.MedianCollectionOpImage$PixelSpecialization">Daniel Léonard</a>
531:             * @version $Revision: 1.2 $
532:             */
533:            protected static abstract class PixelSpecialization<A> {
534:
535:                /**
536:                 * Builds the 3-dimensional source matrix. The first dimension represents
537:                 * the different source images, the second dimension represents individual
538:                 * bands inside a single source image and the last dimension contains all
539:                 * the pixels.
540:                 * @param   len   the size of the first dimension, the number of source
541:                 *                images.
542:                 * @return   the source matrix.
543:                 */
544:                public abstract A[][] buildAllData(int len);
545:
546:                /**
547:                 * Extracts the 2-dimensional data matrix from the given image raster. The
548:                 * first dimension represents the individual bands inside the image and
549:                 * the last dimension contains all the pixels.
550:                 * @param    accessor   the raster accessor over the image raster.
551:                 * @return   the image matrix.
552:                 */
553:                public abstract A[] extractData(RasterAccessor accessor);
554:
555:                /**
556:                 * Extracts the specified pixel, basically doing :
557:                 * <blockquote><code>
558:                 * double value = all_data[image][band][pixel];
559:                 * return value;
560:                 * </code></blockquote>
561:                 * @param   all_data   the 3-dimensional source matrix
562:                 * @param   image   the image position in the source matrix.
563:                 * @param   band   the band position in the source image.
564:                 * @param   pixel   the pixel position in the band.
565:                 * @return   the pixel value.
566:                 */
567:                public abstract double extractPixelValueAt(A[][] all_data,
568:                        int image, int band, int pixel);
569:
570:                /**
571:                 * Changes the given pixel.
572:                 * @param   value   the new pixel value.
573:                 * @param   data   the image data.
574:                 * @param   band   the band position in the image.
575:                 * @param   pixel   the pixel position in the band.
576:                 */
577:                public abstract void setPixelValueAt(double value, A[] data,
578:                        int band, int pixel);
579:
580:            }
581:
582:            //---------------------------
583:            // Class variables
584:            //---------------------------
585:
586:            /** Specialization for data of type <em>byte</em>. */
587:            protected static PixelSpecialization<byte[]> BYTE_SPECIALIZATION = new PixelSpecialization<byte[]>() {
588:
589:                @Override
590:                public byte[][][] buildAllData(int len) {
591:                    byte[][][] all_data = new byte[len][][];
592:                    return all_data;
593:                }
594:
595:                @Override
596:                public byte[][] extractData(RasterAccessor raster_accessor) {
597:                    byte[][] data = raster_accessor.getByteDataArrays();
598:                    return data;
599:                }
600:
601:                @Override
602:                public double extractPixelValueAt(byte[][][] all_data,
603:                        int image, int band, int pixel) {
604:                    double value = all_data[image][band][pixel];
605:                    return value;
606:                }
607:
608:                @Override
609:                public void setPixelValueAt(double value, byte[][] sink_data,
610:                        int band, int pixel) {
611:                    sink_data[band][pixel] = (byte) value;
612:                }
613:
614:            };
615:
616:            /** Specialization for data of type <em>short</em>. */
617:            protected static PixelSpecialization<short[]> SHORT_SPECIALIZATION = new PixelSpecialization<short[]>() {
618:
619:                @Override
620:                public short[][][] buildAllData(int len) {
621:                    short[][][] all_data = new short[len][][];
622:                    return all_data;
623:                }
624:
625:                @Override
626:                public short[][] extractData(RasterAccessor raster_accessor) {
627:                    short[][] data = raster_accessor.getShortDataArrays();
628:                    return data;
629:                }
630:
631:                @Override
632:                public double extractPixelValueAt(short[][][] all_data,
633:                        int image, int band, int pixel) {
634:                    double value = all_data[image][band][pixel];
635:                    return value;
636:                }
637:
638:                @Override
639:                public void setPixelValueAt(double value, short[][] sink_data,
640:                        int band, int pixel) {
641:                    sink_data[band][pixel] = (short) value;
642:                }
643:
644:            };
645:
646:            /** Specialization for data of type <em>int</em>. */
647:            protected static PixelSpecialization<int[]> INT_SPECIALIZATION = new PixelSpecialization<int[]>() {
648:
649:                @Override
650:                public int[][][] buildAllData(int len) {
651:                    int[][][] all_data = new int[len][][];
652:                    return all_data;
653:                }
654:
655:                @Override
656:                public int[][] extractData(RasterAccessor raster_accessor) {
657:                    int[][] data = raster_accessor.getIntDataArrays();
658:                    return data;
659:                }
660:
661:                @Override
662:                public double extractPixelValueAt(int[][][] all_data,
663:                        int image, int band, int pixel) {
664:                    double value = all_data[image][band][pixel];
665:                    return value;
666:                }
667:
668:                @Override
669:                public void setPixelValueAt(double value, int[][] sink_data,
670:                        int band, int pixel) {
671:                    sink_data[band][pixel] = (int) value;
672:                }
673:
674:            };
675:
676:            /** Specialization for data of type <em>float</em>. */
677:            protected static PixelSpecialization<float[]> FLOAT_SPECIALIZATION = new PixelSpecialization<float[]>() {
678:
679:                @Override
680:                public float[][][] buildAllData(int len) {
681:                    float[][][] all_data = new float[len][][];
682:                    return all_data;
683:                }
684:
685:                @Override
686:                public float[][] extractData(RasterAccessor raster_accessor) {
687:                    float[][] data = raster_accessor.getFloatDataArrays();
688:                    return data;
689:                }
690:
691:                @Override
692:                public double extractPixelValueAt(float[][][] all_data,
693:                        int image, int band, int pixel) {
694:                    double value = all_data[image][band][pixel];
695:                    return value;
696:                }
697:
698:                @Override
699:                public void setPixelValueAt(double value, float[][] sink_data,
700:                        int band, int pixel) {
701:                    sink_data[band][pixel] = (float) value;
702:                }
703:
704:            };
705:
706:            /** Specialization for data of type <em>double</em>. */
707:            protected static PixelSpecialization<double[]> DOUBLE_SPECIALIZATION = new PixelSpecialization<double[]>() {
708:
709:                @Override
710:                public double[][][] buildAllData(int len) {
711:                    double[][][] all_data = new double[len][][];
712:                    return all_data;
713:                }
714:
715:                @Override
716:                public double[][] extractData(RasterAccessor raster_accessor) {
717:                    double[][] data = raster_accessor.getDoubleDataArrays();
718:                    return data;
719:                }
720:
721:                @Override
722:                public double extractPixelValueAt(double[][][] all_data,
723:                        int image, int band, int pixel) {
724:                    double value = all_data[image][band][pixel];
725:                    return value;
726:                }
727:
728:                @Override
729:                public void setPixelValueAt(double value, double[][] sink_data,
730:                        int band, int pixel) {
731:                    sink_data[band][pixel] = value;
732:                }
733:
734:            };
735:
736:        }
737:
738:        /*
739:         * $Log: MedianCollectionOpImage.java,v $
740:         * Revision 1.2  2007/07/05 18:24:15  forklabs
741:         * Now uses CollectionImage instead of lists.
742:         *
743:         * Revision 1.1  2007/06/13 18:56:37  forklabs
744:         * Operator mediancollection.
745:         *
746:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.