Source Code Cross Referenced for UnaryFunctionOpImage.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/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:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.