Source Code Cross Referenced for PixelAccessor.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » javax » media » jai » 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 » javax.media.jai 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: PixelAccessor.java,v $
0003:         *
0004:         * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * Use is subject to license terms.
0007:         *
0008:         * $Revision: 1.1 $
0009:         * $Date: 2005/02/11 04:57:15 $
0010:         * $State: Exp $
0011:         */
0012:        package javax.media.jai;
0013:
0014:        import java.awt.Rectangle;
0015:        import java.awt.image.ColorModel;
0016:        import java.awt.image.ComponentColorModel;
0017:        import java.awt.image.ComponentSampleModel;
0018:        import java.awt.image.DataBuffer;
0019:        import java.awt.image.DataBufferByte;
0020:        import java.awt.image.DataBufferInt;
0021:        import java.awt.image.DataBufferShort;
0022:        import java.awt.image.DataBufferUShort;
0023:        import java.awt.image.IndexColorModel;
0024:        import java.awt.image.MultiPixelPackedSampleModel;
0025:        import java.awt.image.PackedColorModel;
0026:        import java.awt.image.Raster;
0027:        import java.awt.image.RenderedImage;
0028:        import java.awt.image.SampleModel;
0029:        import java.awt.image.SinglePixelPackedSampleModel;
0030:        import java.awt.image.WritableRaster;
0031:        import java.util.Vector;
0032:        import com.sun.media.jai.util.DataBufferUtils;
0033:        import com.sun.media.jai.util.ImageUtil;
0034:        import com.sun.media.jai.util.JDKWorkarounds;
0035:
0036:        /**
0037:         * This is a utility class that may be used to access the pixel data
0038:         * stored in a <code>RenderedImage</code>'s <code>Raster</code>s, as
0039:         * well as performing pixel-to-color data translation based on the
0040:         * image's <code>SampleModel</code> and <code>ColorModel</code>.  It
0041:         * also provides several static methods to determine information about
0042:         * the image data.
0043:         *
0044:         * <p> This class is intended to help classes that need to access the
0045:         * pixel and/or color data of a <code>RenderedImage</code>, such as an
0046:         * <code>OpImage</code>, in an optimized fashion.  Most of the variables
0047:         * defined in this class are public so that other classes may use them
0048:         * directly.  However, the variables are also declared <code>final</code>
0049:         * so that other classes can not modify their values.
0050:         *
0051:         * <p> In general, the pixel data of a <code>RenderedImage</code> may
0052:         * be obtained by calling the <code>getPixels()</code> method.  By
0053:         * definition, the <i>pixel data</i> of an image are the data described
0054:         * by the image's <code>SampleModel</code> and stored in the image's
0055:         * <code>Raster</code>s.  No consideration of any kind is given to the
0056:         * image's <code>ColorModel</code>.  If no error is found, the pixel
0057:         * data are returned in the primitive arrays of the type specified by
0058:         * the caller in an unpacked format, along with access information.
0059:         * Therefore, the specified data type must be one of the valid types
0060:         * defined in <code>DataBuffer</code> and large enough (in bit depth)
0061:         * to hold the pixel data of the image.
0062:         *
0063:         * <p> The pixel data of a binary image may be obtained in a packed
0064:         * format by calling the <code>getPackedPixels()</code> method.  It
0065:         * returns the data in a packed <code>byte</code> array, with 8 pixels
0066:         * packed into 1 byte.  The format of the data in the array is
0067:         * similar to the format described by the
0068:         * <code>MultiPixelPackedSampleModel</code>, where the end of each
0069:         * scanline is padded to the end of the byte if necessary.  Note that this
0070:         * method returns a valid result only if and only if the image is a
0071:         * single-band bit image, that is, each pixel has only 1 sample with a
0072:         * sample size of 1 bit.
0073:         *
0074:         * <p> Two corresponding "set" methods are also provided for setting the
0075:         * computed pixel data back into the <code>Raster</code>'s
0076:         * <code>DataBuffer</code>: <code>setPixels()</code> for unpacked data,
0077:         * and <code>setPackedPixels()</code> for packed data.  It is very
0078:         * important that the caller uses the correct "set" method that matches
0079:         * the "get" method used to obtain the data, or errors will occur.
0080:         *
0081:         * <p> The color/alpha data of the <code>RenderedImage</code> may be
0082:         * obtained by calling the <code>getComponents()</code> method which
0083:         * returns the unnormalized data in the <code>ColorSpace</code> specified
0084:         * in the <code>ColorModel</code>, or the <code>getComponentsRGB()</code>
0085:         * method which returns the data scaled from 0 to 255 in the default sRGB
0086:         * <code>ColorSpace</code>.  These methods retrieve the pixel data from
0087:         * the <code>Raster</code>, and perform the pixel-to-color translation.
0088:         * Therefore, in order for these two methods to return a valid result, the
0089:         * image must have a valid <code>ColorModel</code>.
0090:         *
0091:         * <p> Similarly, two "set" methods may be used to perform the
0092:         * color-to-pixel translation, and set the pixel data back to the
0093:         * <code>Raster</code>'s <code>DataBuffer</code>.  Again, it is important
0094:         * that the "get" and "set" methods are matched up correctly.
0095:         *
0096:         * <p> In addition, several static methods are included in this class
0097:         * for the convenience of <code>OpImage</code> developers, who may use them to
0098:         * help determine the appropriate destination <code>SampleModel</code>
0099:         * type.
0100:         *
0101:         * @since JAI 1.1
0102:         *
0103:         */
0104:        public final class PixelAccessor {
0105:
0106:            /** Tag for single-bit data type. */
0107:            public static final int TYPE_BIT = -1;
0108:
0109:            /** The image's <code>SampleModel</code>. */
0110:            public final SampleModel sampleModel;
0111:
0112:            /** The image's <code>ColorModel</code>. */
0113:            public final ColorModel colorModel;
0114:
0115:            // The following information comes from the image's SampleModel.
0116:
0117:            /**
0118:             * <code>true</code> if the image has a
0119:             * <code>ComponentSampleModel</code>;
0120:             * <code>false</code> otherwise.
0121:             */
0122:            public final boolean isComponentSM;
0123:
0124:            /**
0125:             * <code>true</code> if the image has a
0126:             * <code>MultiPixelPackedSampleModel</code>;
0127:             * <code>false</code> otherwise.
0128:             */
0129:            public final boolean isMultiPixelPackedSM;
0130:
0131:            /**
0132:             * <code>true</code> if the image has a
0133:             * <code>SinglePixelPackedSampleModel</code>;
0134:             * <code>false</code> otherwise.
0135:             */
0136:            public final boolean isSinglePixelPackedSM;
0137:
0138:            /** The data type of the pixel samples, determined based on the sample size. */
0139:            public final int sampleType;
0140:
0141:            /**
0142:             * The type of the <code>DataBuffer</code>'s data array used to store the
0143:             * pixel data by the image's <code>SampleModel</code>.  This is the same
0144:             * value as that returned by <code>SampleModel.getDataType()</code>.
0145:             */
0146:            public final int bufferType;
0147:
0148:            /**
0149:             * The type of the primitive array used to transfer the pixel data by
0150:             * the image's <code>SampleModel</code>.  This is the same value as
0151:             * that returned by <code>SampleModel.getTransferType()</code>.
0152:             */
0153:            public final int transferType;
0154:
0155:            /**
0156:             * The number of bands (samples) per pixel.  This is the same value
0157:             * as that returned by <code>SampleModel.getNumBands()</code>.
0158:             */
0159:            public final int numBands;
0160:
0161:            /**
0162:             * The size, in number of bits, of all the pixel samples.  This is
0163:             * the same array as that returned by
0164:             * <code>SampleModel.getSampleSize()</code>.
0165:             */
0166:            public final int[] sampleSize;
0167:
0168:            /**
0169:             * Set to <code>true</code> if the pixel data of this image may be
0170:             * packed into a <code>byte</code> array.  That is, each pixel has
0171:             * 1 sample (1 band) with a sample size of 1 bit.  If this variable
0172:             * is <code>true</code>, <code>getPackedPixels()</code> should return
0173:             * a valid result, with 8 pixels packed into 1 byte.
0174:             */
0175:            public final boolean isPacked;
0176:
0177:            // The following information come from the image's ColorModel.
0178:
0179:            /**
0180:             * Set to <code>true</code> if the image has a non-null
0181:             * <code>ColorModel</code> which is compatible with the image's
0182:             * <code>SampleModel</code>; <code>false</code> otherwise.
0183:             */
0184:            public final boolean hasCompatibleCM;
0185:
0186:            /**
0187:             * Set to <code>true</code> if the image has a
0188:             * <code>ComponentColorModel</code>;
0189:             * <code>false</code> otherwise.
0190:             */
0191:            public final boolean isComponentCM;
0192:
0193:            /**
0194:             * Set to <code>true</code> if the image has an
0195:             * <code>IndexColorModel</code>;
0196:             * <code>false</code> otherwise.
0197:             */
0198:            public final boolean isIndexCM;
0199:
0200:            /**
0201:             * Set to <code>true</code> if the image has a
0202:             * <code>PackedColorModel</code>;
0203:             * <code>false</code> otherwise.
0204:             */
0205:            public final boolean isPackedCM;
0206:
0207:            /**
0208:             * The type of the color/alpha components, determined based on the
0209:             * component size.
0210:             */
0211:            public final int componentType;
0212:
0213:            /**
0214:             * The total number of color/alpha components in the image's
0215:             * <code>ColorModel</code>.  This is the same value as that
0216:             * returned by <code>ColorModel.getNumComponents()</code>.
0217:             */
0218:            public final int numComponents;
0219:
0220:            /**
0221:             * The size, in number of bits, of all the color/alpha components.
0222:             * This is the same array as that returned by
0223:             * <code>ColorModel.getComponentSize()</code>.
0224:             */
0225:            public final int[] componentSize;
0226:
0227:            /**
0228:             * Returns the image's <code>SampleModel</code>.
0229:             *
0230:             * @throws IllegalArgumentException if <code>image</code> is
0231:             *         <code>null</code>.
0232:             */
0233:            private static SampleModel getSampleModel(RenderedImage image) {
0234:                if (image == null) {
0235:                    throw new IllegalArgumentException(JaiI18N
0236:                            .getString("Generic0"));
0237:                }
0238:                return image.getSampleModel();
0239:            }
0240:
0241:            /**
0242:             * Constructs a <code>PixelAccessor</code> from a
0243:             * <code>RenderedImage</code>.
0244:             * The <code>RenderedImage</code> must have a valid
0245:             * <code>SampleModel</code>, but may or may not have a valid
0246:             * <code>ColorModel</code>.
0247:             *
0248:             * @param image  The image whose data are to be accessed.
0249:             *
0250:             * @throws IllegalArgumentException  If <code>image</code> is
0251:             *         <code>null</code>, or if the image does not have a valid
0252:             *         <code>SampleModel</code>.
0253:             */
0254:            public PixelAccessor(RenderedImage image) {
0255:                this (getSampleModel(image), image.getColorModel());
0256:            }
0257:
0258:            /**
0259:             * Constructs a <code>PixelAccessor</code> given a valid
0260:             * <code>SampleModel</code> and a (possibly <code>null</code>)
0261:             * <code>ColorModel</code>.
0262:             *
0263:             * @param sm The <code>SampleModel</code> for the image to be accessed.
0264:             *           Must be valid.
0265:             * @param cm The <code>ColorModel</code> for the image to be accessed.
0266:             *           May be null.
0267:             * @throws IllegalArgumentException  If <code>sm</code> is <code>null</code>.
0268:             */
0269:            public PixelAccessor(SampleModel sm, ColorModel cm) {
0270:
0271:                if (sm == null) {
0272:                    throw new IllegalArgumentException(JaiI18N
0273:                            .getString("Generic0"));
0274:                }
0275:
0276:                sampleModel = sm;
0277:                colorModel = cm;
0278:
0279:                // Information from the SampleModel.
0280:                isComponentSM = sampleModel instanceof  ComponentSampleModel;
0281:                isMultiPixelPackedSM = sampleModel instanceof  MultiPixelPackedSampleModel;
0282:                isSinglePixelPackedSM = sampleModel instanceof  SinglePixelPackedSampleModel;
0283:
0284:                bufferType = sampleModel.getDataType();
0285:                transferType = sampleModel.getTransferType();
0286:                numBands = sampleModel.getNumBands();
0287:                sampleSize = sampleModel.getSampleSize();
0288:                sampleType = isComponentSM ? bufferType : getType(sampleSize);
0289:
0290:                // Indicates whether the pixel data may be stored in packed format.
0291:                isPacked = sampleType == TYPE_BIT && numBands == 1;
0292:
0293:                // Information from the ColorModel.
0294:                hasCompatibleCM = colorModel != null
0295:                        && JDKWorkarounds.areCompatibleDataModels(sampleModel,
0296:                                colorModel);
0297:
0298:                if (hasCompatibleCM) {
0299:                    isComponentCM = colorModel instanceof  ComponentColorModel;
0300:                    isIndexCM = colorModel instanceof  IndexColorModel;
0301:                    isPackedCM = colorModel instanceof  PackedColorModel;
0302:
0303:                    numComponents = colorModel.getNumComponents();
0304:                    componentSize = colorModel.getComponentSize();
0305:                    int tempType = getType(componentSize);
0306:
0307:                    componentType = (tempType == TYPE_BIT) ? DataBuffer.TYPE_BYTE
0308:                            : tempType;
0309:                } else {
0310:                    isComponentCM = false;
0311:                    isIndexCM = false;
0312:                    isPackedCM = false;
0313:                    numComponents = numBands;
0314:                    componentSize = sampleSize;
0315:                    componentType = sampleType;
0316:                }
0317:            }
0318:
0319:            /**
0320:             * Determines the data type based on the data sizes in number of bits.
0321:             * Note that for data size between 9 and 16, this method returns
0322:             * <code>TYPE_USHORT</code>, and for size between 17 and 32, this
0323:             * method returns <code>TYPE_INT</code>.  The minimum valid size is 1,
0324:             * and the maximum valid size is 64.
0325:             *
0326:             * @param size An array containing the bit width of each band.
0327:             * @return The minimum size data type which can hold any band.
0328:             */
0329:            private static int getType(int[] size) {
0330:                int maxSize = size[0]; // maximum sample size
0331:                for (int i = 1; i < size.length; i++) {
0332:                    maxSize = Math.max(maxSize, size[i]);
0333:                }
0334:
0335:                int type;
0336:                if (maxSize < 1) {
0337:                    type = DataBuffer.TYPE_UNDEFINED;
0338:                } else if (maxSize == 1) {
0339:                    type = TYPE_BIT;
0340:                } else if (maxSize <= 8) {
0341:                    type = DataBuffer.TYPE_BYTE;
0342:                } else if (maxSize <= 16) {
0343:                    type = DataBuffer.TYPE_USHORT;
0344:                } else if (maxSize <= 32) {
0345:                    type = DataBuffer.TYPE_INT;
0346:                } else if (maxSize <= 64) {
0347:                    type = DataBuffer.TYPE_DOUBLE;
0348:                } else {
0349:                    type = DataBuffer.TYPE_UNDEFINED;
0350:                }
0351:                return type;
0352:            }
0353:
0354:            /**
0355:             * Determines the pixel type based on the <code>SampleModel</code>.
0356:             * The pixel type signifies the data type for a <code>PixelAccessor</code>.
0357:             * For <code>ComponentSampleModel</code>, the pixel type is the same
0358:             * as the type of the <code>DataBuffer</code> used to store the pixel
0359:             * data.  For all other types of <code>SampleModel</code>, the pixel
0360:             * type is determined based on the sample sizes.
0361:             *
0362:             * @param sm The <code>SampleModel</code> of the image.
0363:             * @return The pixel type for this sample model.
0364:             */
0365:            public static int getPixelType(SampleModel sm) {
0366:                return sm instanceof  ComponentSampleModel ? sm.getDataType()
0367:                        : getType(sm.getSampleSize());
0368:            }
0369:
0370:            /**
0371:             * Returns the largest data type of all the sources.  This method
0372:             * may be used to determine the pixel sample type of a destination
0373:             * in the default situation.  It guarantees that the destination can
0374:             * store the resulting pixel values without losing any precision.
0375:             * The pixel type signifies the data type for a <code>PixelAccessor</code>.
0376:             *
0377:             * <p> If all the sources are single-bit images, this method returns
0378:             * <code>TYPE_BIT</code> (defined in this class) so that the
0379:             * destination does not use unnecessary memory for some operations.
0380:             * This includes all images whose <code>SampleModel</code> is
0381:             * single-banded and whose sample size is 1, regardless of the type
0382:             * of <code>ColorModel</code> the image may have.
0383:             * If an operation does not wish to deal with packed data, it
0384:             * should use <code>TYPE_BYTE</code> for pixel computation.
0385:             *
0386:             * <p> If there is no object in the source <code>Vector</code>, this
0387:             * method returns <code>TYPE_UNDEFINED</code>.  All the objects in
0388:             * the source <code>Vector</code> must be <code>RenderedImage</code>s.
0389:             *
0390:             * <p> When determining the result, only information from each image's
0391:             * <code>SampleModel</code> is used.  No consideration is given to the
0392:             * image's <code>ColorModel</code>.
0393:             *
0394:             * @param sources A <code>Vector</code> of <code>RenderedImage</code>
0395:             *                sources.
0396:             * @return The largest data type which can accomodate all sources.
0397:             * @throws IllegalArgumentException  If <code>sources</code> is
0398:             *         <code>null</code>.
0399:             * @throws ClassCastException  If any object in <code>sources</code>
0400:             *         is not a <code>RenderedImage</code>.
0401:             */
0402:            public static int getDestPixelType(Vector sources) {
0403:
0404:                if (sources == null) {
0405:                    throw new IllegalArgumentException(JaiI18N
0406:                            .getString("Generic0"));
0407:                }
0408:
0409:                int type = DataBuffer.TYPE_UNDEFINED;
0410:                int size = sources.size();
0411:
0412:                if (size > 0) {
0413:                    RenderedImage src = (RenderedImage) sources.get(0);
0414:                    SampleModel sm = src.getSampleModel();
0415:
0416:                    type = getPixelType(sm);
0417:
0418:                    for (int i = 1; i < size; i++) {
0419:                        src = (RenderedImage) sources.get(i);
0420:                        sm = src.getSampleModel();
0421:
0422:                        int t = getPixelType(sm);
0423:
0424:                        // Only int can handle ushort/short combination.
0425:                        type = (type == DataBuffer.TYPE_USHORT && t == DataBuffer.TYPE_SHORT)
0426:                                || (type == DataBuffer.TYPE_SHORT && t == DataBuffer.TYPE_USHORT) ? DataBuffer.TYPE_INT
0427:                                : Math.max(type, t);
0428:                    }
0429:                }
0430:                return type;
0431:            }
0432:
0433:            /**
0434:             * Returns the smallest number of bands of all the sources.
0435:             * This method may be used to determine the number of bands a
0436:             * destination should have in the default situation.  It guarantees
0437:             * that every destination band has a corresponding source band.
0438:             *
0439:             * <p> In general, if an operation has multiple sources, and some
0440:             * sources have 1 band and others have multiple bands, the single
0441:             * band may be applied to the multiple bands one at a time. (An
0442:             * example of this would be the <code>MultiplyOpImage</code>). Therefore,
0443:             * in such a case, this method returns the smallest band count among the
0444:             * multi-band sources.
0445:             *
0446:             * <p> If there is no object in the source <code>Vector</code>, this
0447:             * method returns 0.  All the objects in the source <code>Vector</code>
0448:             * must be <code>RenderedImage</code>s.
0449:             *
0450:             * <p> When determining the result, only information from each image's
0451:             * <code>SampleModel</code> are used.  No consideration is given to the
0452:             * image's <code>ColorModel</code>.
0453:             *
0454:             * @param sources A <code>Vector</code> of <code>RenderedImage</code>
0455:             *                sources.
0456:             * @return The minimum number of destination bands.
0457:             * @throws IllegalArgumentException  If <code>sources</code> is
0458:             *         <code>null</code>.
0459:             * @throws ClassCastException  If any object in <code>sources</code>
0460:             *         is not a <code>RenderedImage</code>.
0461:             */
0462:            public static int getDestNumBands(Vector sources) {
0463:
0464:                if (sources == null) {
0465:                    throw new IllegalArgumentException(JaiI18N
0466:                            .getString("Generic0"));
0467:                }
0468:
0469:                int bands = 0;
0470:                int size = sources.size();
0471:
0472:                if (size > 0) {
0473:                    RenderedImage src = (RenderedImage) sources.get(0);
0474:                    SampleModel sm = src.getSampleModel();
0475:
0476:                    bands = sm.getNumBands();
0477:
0478:                    for (int i = 1; i < size; i++) {
0479:                        src = (RenderedImage) sources.get(i);
0480:                        sm = src.getSampleModel();
0481:
0482:                        int b = sm.getNumBands();
0483:
0484:                        bands = bands == 1 || b == 1 ? Math.max(bands, b)
0485:                                : Math.min(bands, b);
0486:                    }
0487:                }
0488:                return bands;
0489:            }
0490:
0491:            /**
0492:             * Returns <code>true</code> if the destination and/or all the
0493:             * sources are single-bit, single-band images, and their pixel
0494:             * data may be packed into a <code>byte</code> array.
0495:             * If so, then the operations may be done in the packed format.
0496:             * @param srcs The array of source <code>PixelAccesor</code>s.
0497:             * @param dst The destination <code>PixelAccesor</code>.
0498:             * @return <code>true</code> if a packed operation is possible.
0499:             */
0500:            public static boolean isPackedOperation(PixelAccessor[] srcs,
0501:                    PixelAccessor dst) {
0502:                boolean canBePacked = dst.isPacked;
0503:                if (canBePacked && srcs != null) {
0504:                    for (int i = 0; i < srcs.length; i++) {
0505:                        canBePacked = canBePacked && srcs[i].isPacked;
0506:                        if (!canBePacked) { // no need to check further
0507:                            break;
0508:                        }
0509:                    }
0510:                }
0511:                return canBePacked;
0512:            }
0513:
0514:            /**
0515:             * Returns <code>true</code> if the destination and the source
0516:             * are both single-bit, single-band images, and their pixel
0517:             * data may be packed into a <code>byte</code> array.
0518:             * If so, then the operations may be done in the packed format.
0519:             * @param srcs The source <code>PixelAccesor</code>.
0520:             * @param dst The destination <code>PixelAccesor</code>.
0521:             * @return <code>true</code> if a packed operation is possible.
0522:             */
0523:            public static boolean isPackedOperation(PixelAccessor src,
0524:                    PixelAccessor dst) {
0525:                return src.isPacked && dst.isPacked;
0526:            }
0527:
0528:            /**
0529:             * Returns <code>true</code> if the destination and both sources
0530:             * are all single-bit, single-band images, and their pixel
0531:             * data may be packed into a <code>byte</code> array.
0532:             * If so, then the operations may be done in the packed format.
0533:             * @param src1 The first source <code>PixelAccesor</code>.
0534:             * @param src2 The second source <code>PixelAccesor</code>.
0535:             * @param dst The destination <code>PixelAccesor</code>.
0536:             * @return <code>true</code> if a packed operation is possible.
0537:             */
0538:            public static boolean isPackedOperation(PixelAccessor src1,
0539:                    PixelAccessor src2, PixelAccessor dst) {
0540:                return src1.isPacked && src2.isPacked && dst.isPacked;
0541:            }
0542:
0543:            /**
0544:             * Returns a region of the pixel data within a <code>Raster</code>
0545:             * in an unpacked primitive array.  The returned data are
0546:             * retrieved from the <code>Raster</code>'s <code>DataBuffer</code>;
0547:             * no pixel-to-color translation is performed.
0548:             *
0549:             * <p> The primitive array is of the type specified by the
0550:             * <code>type</code> argument.  It must be one of the valid data
0551:             * types defined in <code>DataBuffer</code> and large (in bit depth)
0552:             * enough to hold the pixel samples, or an exception will be thrown.
0553:             * This means <code>type</code> should be greater than or equal to
0554:             * <code>sampleType</code>.
0555:             *
0556:             * <p> The <code>Rectangle</code> specifies the region of interest
0557:             * within which the pixel data are to be retrieved.  It must be
0558:             * completely inside the <code>Raster</code>'s boundary, or else
0559:             * this method throws an exception.
0560:             *
0561:             * <p> This method tries to avoid copying data as much as possible.
0562:             * If it is unable to reformat the pixel data in the way requested,
0563:             * or if the pixels do not have enough data to satisfy the request,
0564:             * this method throws an exception.
0565:             *
0566:             * @param raster  The <code>Raster</code> that contains the pixel data.
0567:             * @param rect  The region of interest within the <code>Raster</code>
0568:             *        where the pixels are accessed.
0569:             * @param type  The type of the primitive array used to return the
0570:             *        pixel samples.
0571:             * @param isDest  Indicates whether this <code>Raster</code> is a
0572:             *        destination <code>Raster</code>.  That is, its pixels have
0573:             *        not been computed.
0574:             *
0575:             * @return The pixel data in an <code>UnpackedImageData</code> object.
0576:             * @throws IllegalArgumentException  If <code>type</code> is not a
0577:             *         valid data type defined in <code>DataBuffer</code>, or
0578:             *         is not large enough to hold the pixel samples from the
0579:             *         specified <code>Raster</code>.
0580:             * @throws IllegalArgumentException  If <code>rect</code> is not
0581:             *         contained by the bounds of the specified <code>Raster</code>.
0582:             */
0583:            public UnpackedImageData getPixels(Raster raster, Rectangle rect,
0584:                    int type, boolean isDest) {
0585:                if (!raster.getBounds().contains(rect)) {
0586:                    throw new IllegalArgumentException(JaiI18N
0587:                            .getString("PixelAccessor0"));
0588:                }
0589:
0590:                if (type < DataBuffer.TYPE_BYTE
0591:                        || type > DataBuffer.TYPE_DOUBLE) { // unknown data type
0592:                    throw new IllegalArgumentException(JaiI18N
0593:                            .getString("PixelAccessor1"));
0594:                }
0595:
0596:                if (type < sampleType
0597:                        || (sampleType == DataBuffer.TYPE_USHORT && type == DataBuffer.TYPE_SHORT)) { // type not large enough
0598:                    throw new IllegalArgumentException(JaiI18N
0599:                            .getString("PixelAccessor2"));
0600:                }
0601:
0602:                if (isComponentSM) {
0603:                    return getPixelsCSM(raster, rect, type, isDest);
0604:
0605:                } else {
0606:                    // The total number of data elements needed.
0607:                    int size = rect.width * rect.height * numBands;
0608:
0609:                    Object data = null;
0610:
0611:                    switch (type) {
0612:                    case DataBuffer.TYPE_BYTE:
0613:                        byte[] bd;
0614:
0615:                        if (isDest) {
0616:                            bd = new byte[size];
0617:                        } else {
0618:                            if (isMultiPixelPackedSM
0619:                                    && transferType == DataBuffer.TYPE_BYTE) {
0620:                                bd = (byte[]) raster.getDataElements(rect.x,
0621:                                        rect.y, rect.width, rect.height, null);
0622:                            } else {
0623:                                bd = new byte[size];
0624:                                int[] d = raster.getPixels(rect.x, rect.y,
0625:                                        rect.width, rect.height, (int[]) null);
0626:                                for (int i = 0; i < size; i++) {
0627:                                    bd[i] = (byte) (d[i] & 0xff);
0628:                                }
0629:                            }
0630:                        }
0631:
0632:                        data = repeatBand(bd, numBands);
0633:                        break;
0634:
0635:                    case DataBuffer.TYPE_USHORT:
0636:                        short[] usd;
0637:
0638:                        if (isDest) {
0639:                            usd = new short[size];
0640:                        } else {
0641:                            if (isMultiPixelPackedSM
0642:                                    && transferType == DataBuffer.TYPE_USHORT) {
0643:                                usd = (short[]) raster.getDataElements(rect.x,
0644:                                        rect.y, rect.width, rect.height, null);
0645:                            } else {
0646:                                usd = new short[size];
0647:                                int[] d = raster.getPixels(rect.x, rect.y,
0648:                                        rect.width, rect.height, (int[]) null);
0649:                                for (int i = 0; i < size; i++) {
0650:                                    usd[i] = (short) (d[i] & 0xffff);
0651:                                }
0652:                            }
0653:                        }
0654:
0655:                        data = repeatBand(usd, numBands);
0656:                        break;
0657:
0658:                    case DataBuffer.TYPE_SHORT:
0659:                        short[] sd = new short[size];
0660:
0661:                        if (!isDest) {
0662:                            int[] d = raster.getPixels(rect.x, rect.y,
0663:                                    rect.width, rect.height, (int[]) null);
0664:                            for (int i = 0; i < size; i++) {
0665:                                sd[i] = (short) d[i];
0666:                            }
0667:                        }
0668:
0669:                        data = repeatBand(sd, numBands);
0670:                        break;
0671:
0672:                    case DataBuffer.TYPE_INT:
0673:                        return getPixelsInt(raster, rect, isDest);
0674:
0675:                    case DataBuffer.TYPE_FLOAT:
0676:                        return getPixelsFloat(raster, rect, isDest);
0677:
0678:                    case DataBuffer.TYPE_DOUBLE:
0679:                        return getPixelsDouble(raster, rect, isDest);
0680:                    }
0681:
0682:                    return new UnpackedImageData(raster, rect, type, data,
0683:                            numBands, numBands * rect.width,
0684:                            getInterleavedOffsets(numBands), isDest
0685:                                    & (raster instanceof  WritableRaster));
0686:                }
0687:            }
0688:
0689:            /**
0690:             * Returns the pixel data in a pixel-interleaved, unpacked array
0691:             * where the <code>Raster</code> has a <code>ComponentSampleModel</code>.
0692:             * @return The pixel data in an <code>UnpackedImageData</code> object.
0693:             */
0694:            private UnpackedImageData getPixelsCSM(Raster raster,
0695:                    Rectangle rect, int type, boolean isDest) {
0696:                Object data = null;
0697:                int pixelStride, lineStride;
0698:                int[] offsets;
0699:                boolean set;
0700:
0701:                //ComponentSampleModel sm = (ComponentSampleModel)sampleModel;
0702:                // For bug 4696966: when the raster bounds is not coincide with a
0703:                // tile bounds.
0704:                ComponentSampleModel sm = (ComponentSampleModel) raster
0705:                        .getSampleModel();
0706:
0707:                if (type == sampleType) {
0708:                    // Data are stored in the requested array type; no need to copy.
0709:
0710:                    DataBuffer db = raster.getDataBuffer();
0711:                    int[] bankIndices = sm.getBankIndices();
0712:
0713:                    switch (sampleType) {
0714:                    case DataBuffer.TYPE_BYTE:
0715:                        byte[][] bbd = ((DataBufferByte) db).getBankData();
0716:                        byte[][] bd = new byte[numBands][];
0717:
0718:                        for (int b = 0; b < numBands; b++) {
0719:                            bd[b] = bbd[bankIndices[b]];
0720:                        }
0721:                        data = bd;
0722:                        break;
0723:
0724:                    case DataBuffer.TYPE_USHORT:
0725:                    case DataBuffer.TYPE_SHORT:
0726:                        short[][] sbd = sampleType == DataBuffer.TYPE_USHORT ? ((DataBufferUShort) db)
0727:                                .getBankData()
0728:                                : ((DataBufferShort) db).getBankData();
0729:                        short[][] sd = new short[numBands][];
0730:
0731:                        for (int b = 0; b < numBands; b++) {
0732:                            sd[b] = sbd[bankIndices[b]];
0733:                        }
0734:                        data = sd;
0735:                        break;
0736:
0737:                    case DataBuffer.TYPE_INT:
0738:                        int[][] ibd = ((DataBufferInt) db).getBankData();
0739:                        int[][] id = new int[numBands][];
0740:
0741:                        for (int b = 0; b < numBands; b++) {
0742:                            id[b] = ibd[bankIndices[b]];
0743:                        }
0744:                        data = id;
0745:                        break;
0746:
0747:                    case DataBuffer.TYPE_FLOAT:
0748:                        float[][] fbd = DataBufferUtils.getBankDataFloat(db);
0749:                        float[][] fd = new float[numBands][];
0750:
0751:                        for (int b = 0; b < numBands; b++) {
0752:                            fd[b] = fbd[bankIndices[b]];
0753:                        }
0754:                        data = fd;
0755:                        break;
0756:
0757:                    case DataBuffer.TYPE_DOUBLE:
0758:                        double[][] dbd = DataBufferUtils.getBankDataDouble(db);
0759:                        double[][] dd = new double[numBands][];
0760:
0761:                        for (int b = 0; b < numBands; b++) {
0762:                            dd[b] = dbd[bankIndices[b]];
0763:                        }
0764:                        data = dd;
0765:                        break;
0766:                    }
0767:
0768:                    pixelStride = sm.getPixelStride();
0769:                    lineStride = sm.getScanlineStride();
0770:
0771:                    // Determine offsets.
0772:                    int[] dbOffsets = db.getOffsets(); // DataBuffer offsets
0773:                    int x = rect.x - raster.getSampleModelTranslateX();
0774:                    int y = rect.y - raster.getSampleModelTranslateY();
0775:
0776:                    offsets = new int[numBands];
0777:                    for (int b = 0; b < numBands; b++) {
0778:                        offsets[b] = sm.getOffset(x, y, b)
0779:                                + dbOffsets[bankIndices[b]];
0780:                    }
0781:
0782:                    set = false; // no need to copy
0783:
0784:                } else { // need to reformat data
0785:                    switch (type) {
0786:                    case DataBuffer.TYPE_INT:
0787:                        return getPixelsInt(raster, rect, isDest);
0788:
0789:                    case DataBuffer.TYPE_FLOAT:
0790:                        return getPixelsFloat(raster, rect, isDest);
0791:
0792:                    case DataBuffer.TYPE_DOUBLE:
0793:                        return getPixelsDouble(raster, rect, isDest);
0794:
0795:                        /*
0796:                         * Since the requested type must be greater than or equal to
0797:                         * sampleType, if type is byte, sampleType must also be byte,
0798:                         * because the smallest sampleType of ComponentSampleModel is
0799:                         * byte.  This case falls into the above uncopied case.
0800:                         *
0801:                         * If the Raster is a destination, then the pixel data have
0802:                         * not been computed and stored in the buffer yet.
0803:                         * Just create a new array, but no need to copy anything.
0804:                         */
0805:                    default: // byte to ushort or short
0806:                        // The total number of data elements needed.
0807:                        int size = rect.width * rect.height * numBands;
0808:
0809:                        short[] sd = new short[size];
0810:
0811:                        if (!isDest) { // need to copy byte data
0812:                            // Only byte is smaller than short or ushort.
0813:                            UnpackedImageData uid = getPixelsCSM(raster, rect,
0814:                                    sampleType, isDest);
0815:                            byte[][] bdata = uid.getByteData();
0816:
0817:                            for (int b = 0; b < numBands; b++) {
0818:                                byte[] bd = bdata[b]; // band data
0819:                                int lo = uid.getOffset(b); // line offset
0820:
0821:                                for (int i = b, h = 0; h < rect.height; h++) {
0822:                                    int po = lo; // pixel offset
0823:                                    lo += uid.lineStride;
0824:
0825:                                    for (int w = 0; w < rect.width; w++) {
0826:                                        sd[i] = (short) (bd[po] & 0xff);
0827:
0828:                                        po += uid.pixelStride;
0829:                                        i += numBands;
0830:                                    }
0831:                                }
0832:                            }
0833:                        }
0834:
0835:                        data = repeatBand(sd, numBands);
0836:                        break;
0837:                    }
0838:
0839:                    pixelStride = numBands;
0840:                    lineStride = pixelStride * rect.width;
0841:                    offsets = getInterleavedOffsets(numBands);
0842:                    set = isDest & (raster instanceof  WritableRaster);
0843:                }
0844:
0845:                return new UnpackedImageData(raster, rect, type, data,
0846:                        pixelStride, lineStride, offsets, set);
0847:            }
0848:
0849:            /**
0850:             * Returns the pixel data in an pixel-interleaved, unpacked,
0851:             * integer array.
0852:             * @return The pixel data in an <code>UnpackedImageData</code> object.
0853:             */
0854:            private UnpackedImageData getPixelsInt(Raster raster,
0855:                    Rectangle rect, boolean isDest) {
0856:                // The total number of data elements needed.
0857:                int size = rect.width * rect.height * numBands;
0858:
0859:                /*
0860:                 * If the Raster is destination, then the pixel data have
0861:                 * not been computed and stored in the buffer yet.
0862:                 * Just create a new array, but no need to copy anything.
0863:                 * Otherwise, copy the data from the Raster.
0864:                 */
0865:                int[] d = isDest ? new int[size] : raster.getPixels(rect.x,
0866:                        rect.y, rect.width, rect.height, (int[]) null);
0867:
0868:                return new UnpackedImageData(raster, rect, DataBuffer.TYPE_INT,
0869:                        repeatBand(d, numBands), numBands, numBands
0870:                                * rect.width, getInterleavedOffsets(numBands),
0871:                        isDest & (raster instanceof  WritableRaster));
0872:            }
0873:
0874:            /**
0875:             * Returns the pixel data in an pixel-interleaved, unpacked,
0876:             * float array.
0877:             * @return The pixel data in an <code>UnpackedImageData</code> object.
0878:             */
0879:            private UnpackedImageData getPixelsFloat(Raster raster,
0880:                    Rectangle rect, boolean isDest) {
0881:                // The total number of data elements needed.
0882:                int size = rect.width * rect.height * numBands;
0883:
0884:                /*
0885:                 * If the Raster is destination, then the pixel data have
0886:                 * not been computed and stored in the buffer yet.
0887:                 * Just create a new array, but no need to copy anything.
0888:                 * Otherwise, copy the data from the Raster.
0889:                 */
0890:                float[] d = isDest ? new float[size] : raster.getPixels(rect.x,
0891:                        rect.y, rect.width, rect.height, (float[]) null);
0892:
0893:                return new UnpackedImageData(raster, rect,
0894:                        DataBuffer.TYPE_FLOAT, repeatBand(d, numBands),
0895:                        numBands, numBands * rect.width,
0896:                        getInterleavedOffsets(numBands), isDest
0897:                                & (raster instanceof  WritableRaster));
0898:            }
0899:
0900:            /**
0901:             * Returns the pixel data in an pixel-interleaved, unpacked,
0902:             * double array.
0903:             * @return The pixel data in an <code>UnpackedImageData</code> object.
0904:             */
0905:            private UnpackedImageData getPixelsDouble(Raster raster,
0906:                    Rectangle rect, boolean isDest) {
0907:                // The total number of data elements needed.
0908:                int size = rect.width * rect.height * numBands;
0909:
0910:                /*
0911:                 * If the Raster is destination, then the pixel data have
0912:                 * not been computed and stored in the buffer yet.
0913:                 * Just create a new array, but no need to copy anything.
0914:                 * Otherwise, copy the data from the Raster.
0915:                 */
0916:                double[] d = isDest ? new double[size] : raster.getPixels(
0917:                        rect.x, rect.y, rect.width, rect.height,
0918:                        (double[]) null);
0919:
0920:                return new UnpackedImageData(raster, rect,
0921:                        DataBuffer.TYPE_DOUBLE, repeatBand(d, numBands),
0922:                        numBands, numBands * rect.width,
0923:                        getInterleavedOffsets(numBands), isDest
0924:                                & (raster instanceof  WritableRaster));
0925:            }
0926:
0927:            /** Repeats a one-dimensional array into a two-dimensional array. */
0928:            private byte[][] repeatBand(byte[] d, int numBands) {
0929:                byte[][] data = new byte[numBands][];
0930:                for (int i = 0; i < numBands; i++) {
0931:                    data[i] = d;
0932:                }
0933:                return data;
0934:            }
0935:
0936:            private short[][] repeatBand(short[] d, int numBands) {
0937:                short[][] data = new short[numBands][];
0938:                for (int i = 0; i < numBands; i++) {
0939:                    data[i] = d;
0940:                }
0941:                return data;
0942:            }
0943:
0944:            private int[][] repeatBand(int[] d, int numBands) {
0945:                int[][] data = new int[numBands][];
0946:                for (int i = 0; i < numBands; i++) {
0947:                    data[i] = d;
0948:                }
0949:                return data;
0950:            }
0951:
0952:            private float[][] repeatBand(float[] d, int numBands) {
0953:                float[][] data = new float[numBands][];
0954:                for (int i = 0; i < numBands; i++) {
0955:                    data[i] = d;
0956:                }
0957:                return data;
0958:            }
0959:
0960:            private double[][] repeatBand(double[] d, int numBands) {
0961:                double[][] data = new double[numBands][];
0962:                for (int i = 0; i < numBands; i++) {
0963:                    data[i] = d;
0964:                }
0965:                return data;
0966:            }
0967:
0968:            /** Returns pixel interleaved offsets for copy case. */
0969:            private int[] getInterleavedOffsets(int numBands) {
0970:                int[] offsets = new int[numBands];
0971:                for (int i = 0; i < numBands; i++) {
0972:                    offsets[i] = i;
0973:                }
0974:                return offsets;
0975:            }
0976:
0977:            /**
0978:             * Sets a region of the pixel data within a <code>Raster</code>
0979:             * using a primitive array.  This method copies data only if
0980:             * the <code>set</code> flag in <code>UnpackedImageData</code> is
0981:             * <code>true</code>.  Performs clamping by default.
0982:             *
0983:             * <p> The <code>UnpackedImageData</code> should be obtained by
0984:             * calling the <code>getPixels()</code> method.
0985:             *
0986:             * @param uid The <code>UnpackedImageData</code> object to set.
0987:             * @throws IllegalArgumentException  If the <code>uid</code> is
0988:             *         <code>null</code>.
0989:             */
0990:            public void setPixels(UnpackedImageData uid) {
0991:
0992:                if (uid == null) {
0993:                    throw new IllegalArgumentException(JaiI18N
0994:                            .getString("Generic0"));
0995:                }
0996:
0997:                setPixels(uid, true);
0998:            }
0999:
1000:            /**
1001:             * Sets a region of the pixel data within a <code>Raster</code>
1002:             * using a primitive array.  This method only copies data only if
1003:             * the <code>set</code> flag in <code>UnpackedImageData</code> is
1004:             * <code>true</code>.
1005:             *
1006:             * <p> The <code>UnpackedImageData</code> should be obtained by
1007:             * calling the <code>getPixels()</code> method.
1008:             *
1009:             * @param uid The <code>UnpackedImageData</code> object to set.
1010:             * @param clamp A <code>boolean</code> set to true if clamping
1011:             *              is to be performed.
1012:             * @throws IllegalArgumentException  If the <code>uid</code> is
1013:             *         <code>null</code>.
1014:             */
1015:            public void setPixels(UnpackedImageData uid, boolean clamp) {
1016:
1017:                if (uid == null) {
1018:                    throw new IllegalArgumentException(JaiI18N
1019:                            .getString("Generic0"));
1020:                }
1021:
1022:                if (!uid.convertToDest) {
1023:                    return;
1024:                }
1025:
1026:                if (clamp) { // clamp all array elements
1027:                    switch (sampleType) {
1028:                    case DataBuffer.TYPE_BYTE:
1029:                        clampByte(uid.data, uid.type);
1030:                        break;
1031:                    case DataBuffer.TYPE_USHORT:
1032:                        clampUShort(uid.data, uid.type);
1033:                        break;
1034:                    case DataBuffer.TYPE_SHORT:
1035:                        clampShort(uid.data, uid.type);
1036:                        break;
1037:                    case DataBuffer.TYPE_INT:
1038:                        clampInt(uid.data, uid.type);
1039:                        break;
1040:                    case DataBuffer.TYPE_FLOAT:
1041:                        clampFloat(uid.data, uid.type);
1042:                        break;
1043:                    }
1044:                }
1045:
1046:                WritableRaster raster = (WritableRaster) uid.raster;
1047:                Rectangle rect = uid.rect;
1048:                int type = uid.type;
1049:
1050:                switch (type) {
1051:                case DataBuffer.TYPE_BYTE:
1052:                    byte[] bd = uid.getByteData(0);
1053:
1054:                    if (isMultiPixelPackedSM
1055:                            && transferType == DataBuffer.TYPE_BYTE) {
1056:                        raster.setDataElements(rect.x, rect.y, rect.width,
1057:                                rect.height, bd);
1058:                    } else {
1059:                        int size = bd.length;
1060:                        int[] d = new int[size];
1061:                        for (int i = 0; i < size; i++) {
1062:                            d[i] = bd[i] & 0xff;
1063:                        }
1064:                        raster.setPixels(rect.x, rect.y, rect.width,
1065:                                rect.height, d);
1066:                    }
1067:                    break;
1068:
1069:                case DataBuffer.TYPE_USHORT:
1070:                case DataBuffer.TYPE_SHORT:
1071:                    short[] sd = uid.getShortData(0);
1072:
1073:                    if (isComponentSM) {
1074:                        // The only time this needs to set to is a byte buffer.
1075:                        UnpackedImageData buid = getPixelsCSM(raster, rect,
1076:                                DataBuffer.TYPE_BYTE, true);
1077:                        byte[][] bdata = buid.getByteData();
1078:
1079:                        for (int b = 0; b < numBands; b++) {
1080:                            byte[] d = bdata[b];
1081:                            int lo = buid.getOffset(b);
1082:
1083:                            for (int i = b, h = 0; h < rect.height; h++) {
1084:                                int po = lo;
1085:                                lo += buid.lineStride;
1086:
1087:                                for (int w = 0; w < rect.width; w++) {
1088:                                    d[po] = (byte) sd[i];
1089:
1090:                                    po += buid.pixelStride;
1091:                                    i += numBands;
1092:                                }
1093:                            }
1094:                        }
1095:                    } else if (isMultiPixelPackedSM
1096:                            && transferType == DataBuffer.TYPE_USHORT) {
1097:                        raster.setDataElements(rect.x, rect.y, rect.width,
1098:                                rect.height, sd);
1099:                    } else {
1100:                        int size = sd.length;
1101:                        int[] d = new int[size];
1102:                        if (type == DataBuffer.TYPE_USHORT) {
1103:                            for (int i = 0; i < size; i++) {
1104:                                d[i] = sd[i] & 0xffff;
1105:                            }
1106:                        } else {
1107:                            for (int i = 0; i < size; i++) {
1108:                                d[i] = sd[i];
1109:                            }
1110:                        }
1111:                        raster.setPixels(rect.x, rect.y, rect.width,
1112:                                rect.height, d);
1113:                    }
1114:                    break;
1115:
1116:                case DataBuffer.TYPE_INT:
1117:                    raster.setPixels(rect.x, rect.y, rect.width, rect.height,
1118:                            uid.getIntData(0));
1119:                    break;
1120:
1121:                case DataBuffer.TYPE_FLOAT:
1122:                    raster.setPixels(rect.x, rect.y, rect.width, rect.height,
1123:                            uid.getFloatData(0));
1124:                    break;
1125:
1126:                case DataBuffer.TYPE_DOUBLE:
1127:                    raster.setPixels(rect.x, rect.y, rect.width, rect.height,
1128:                            uid.getDoubleData(0));
1129:                    break;
1130:                }
1131:            }
1132:
1133:            /** Clamps the data array. */
1134:            private void clampByte(Object data, int type) {
1135:                int bands, size;
1136:                switch (type) {
1137:                case DataBuffer.TYPE_USHORT:
1138:                    short[][] usd = (short[][]) data;
1139:                    bands = usd.length;
1140:
1141:                    for (int j = 0; j < bands; j++) {
1142:                        short[] d = usd[j];
1143:                        size = d.length;
1144:
1145:                        for (int i = 0; i < size; i++) {
1146:                            int n = d[i] & 0xffff;
1147:                            d[i] = (short) (n > 0xff ? 0xff : n);
1148:                        }
1149:                    }
1150:                    break;
1151:
1152:                case DataBuffer.TYPE_SHORT:
1153:                    short[][] sd = (short[][]) data;
1154:                    bands = sd.length;
1155:
1156:                    for (int j = 0; j < bands; j++) {
1157:                        short[] d = sd[j];
1158:                        size = d.length;
1159:
1160:                        for (int i = 0; i < size; i++) {
1161:                            int n = d[i];
1162:                            d[i] = (short) (n > 0xff ? 0xff : (n < 0 ? 0 : n));
1163:                        }
1164:                    }
1165:                    break;
1166:
1167:                case DataBuffer.TYPE_INT:
1168:                    int[][] id = (int[][]) data;
1169:                    bands = id.length;
1170:
1171:                    for (int j = 0; j < bands; j++) {
1172:                        int[] d = id[j];
1173:                        size = d.length;
1174:
1175:                        for (int i = 0; i < size; i++) {
1176:                            int n = d[i];
1177:                            d[i] = n > 0xff ? 0xff : (n < 0 ? 0 : n);
1178:                        }
1179:                    }
1180:                    break;
1181:
1182:                case DataBuffer.TYPE_FLOAT:
1183:                    float[][] fd = (float[][]) data;
1184:                    bands = fd.length;
1185:
1186:                    for (int j = 0; j < bands; j++) {
1187:                        float[] d = fd[j];
1188:                        size = d.length;
1189:
1190:                        for (int i = 0; i < size; i++) {
1191:                            float n = d[i];
1192:                            d[i] = n > 0xff ? 0xff : (n < 0 ? 0 : n);
1193:                        }
1194:                    }
1195:                    break;
1196:
1197:                case DataBuffer.TYPE_DOUBLE:
1198:                    double[][] dd = (double[][]) data;
1199:                    bands = dd.length;
1200:
1201:                    for (int j = 0; j < bands; j++) {
1202:                        double[] d = dd[j];
1203:                        size = d.length;
1204:
1205:                        for (int i = 0; i < size; i++) {
1206:                            double n = d[i];
1207:                            d[i] = n > 0xff ? 0xff : (n < 0 ? 0 : n);
1208:                        }
1209:                    }
1210:                    break;
1211:                }
1212:            }
1213:
1214:            private void clampUShort(Object data, int type) {
1215:                int bands, size;
1216:                switch (type) {
1217:                case DataBuffer.TYPE_INT:
1218:                    int[][] id = (int[][]) data;
1219:                    bands = id.length;
1220:
1221:                    for (int j = 0; j < bands; j++) {
1222:                        int[] d = id[j];
1223:                        size = d.length;
1224:
1225:                        for (int i = 0; i < size; i++) {
1226:                            int n = d[i];
1227:                            d[i] = n > 0xffff ? 0xffff : (n < 0 ? 0 : n);
1228:                        }
1229:                    }
1230:                    break;
1231:
1232:                case DataBuffer.TYPE_FLOAT:
1233:                    float[][] fd = (float[][]) data;
1234:                    bands = fd.length;
1235:
1236:                    for (int j = 0; j < bands; j++) {
1237:                        float[] d = fd[j];
1238:                        size = d.length;
1239:
1240:                        for (int i = 0; i < size; i++) {
1241:                            float n = d[i];
1242:                            d[i] = n > 0xffff ? 0xffff : (n < 0 ? 0 : n);
1243:                        }
1244:                    }
1245:                    break;
1246:
1247:                case DataBuffer.TYPE_DOUBLE:
1248:                    double[][] dd = (double[][]) data;
1249:                    bands = dd.length;
1250:
1251:                    for (int j = 0; j < bands; j++) {
1252:                        double[] d = dd[j];
1253:                        size = d.length;
1254:
1255:                        for (int i = 0; i < size; i++) {
1256:                            double n = d[i];
1257:                            d[i] = n > 0xffff ? 0xffff : (n < 0 ? 0 : n);
1258:                        }
1259:                    }
1260:                    break;
1261:                }
1262:            }
1263:
1264:            private void clampShort(Object data, int type) {
1265:                int bands, size;
1266:                switch (type) {
1267:                case DataBuffer.TYPE_INT:
1268:                    int[][] id = (int[][]) data;
1269:                    bands = id.length;
1270:
1271:                    for (int j = 0; j < bands; j++) {
1272:                        int[] d = id[j];
1273:                        size = d.length;
1274:
1275:                        for (int i = 0; i < size; i++) {
1276:                            int n = d[i];
1277:                            d[i] = n > Short.MAX_VALUE ? Short.MAX_VALUE
1278:                                    : (n < Short.MIN_VALUE ? Short.MIN_VALUE
1279:                                            : n);
1280:                        }
1281:                    }
1282:                    break;
1283:
1284:                case DataBuffer.TYPE_FLOAT:
1285:                    float[][] fd = (float[][]) data;
1286:                    bands = fd.length;
1287:
1288:                    for (int j = 0; j < bands; j++) {
1289:                        float[] d = fd[j];
1290:                        size = d.length;
1291:
1292:                        for (int i = 0; i < size; i++) {
1293:                            float n = d[i];
1294:                            d[i] = n > Short.MAX_VALUE ? Short.MAX_VALUE
1295:                                    : (n < Short.MIN_VALUE ? Short.MIN_VALUE
1296:                                            : n);
1297:                        }
1298:                    }
1299:                    break;
1300:
1301:                case DataBuffer.TYPE_DOUBLE:
1302:                    double[][] dd = (double[][]) data;
1303:                    bands = dd.length;
1304:
1305:                    for (int j = 0; j < bands; j++) {
1306:                        double[] d = dd[j];
1307:                        size = d.length;
1308:
1309:                        for (int i = 0; i < size; i++) {
1310:                            double n = d[i];
1311:                            d[i] = n > Short.MAX_VALUE ? Short.MAX_VALUE
1312:                                    : (n < Short.MIN_VALUE ? Short.MIN_VALUE
1313:                                            : n);
1314:                        }
1315:                    }
1316:                    break;
1317:                }
1318:            }
1319:
1320:            private void clampInt(Object data, int type) {
1321:                int bands, size;
1322:                switch (type) {
1323:                case DataBuffer.TYPE_FLOAT:
1324:                    float[][] fd = (float[][]) data;
1325:                    bands = fd.length;
1326:
1327:                    for (int j = 0; j < bands; j++) {
1328:                        float[] d = fd[j];
1329:                        size = d.length;
1330:
1331:                        for (int i = 0; i < size; i++) {
1332:                            float n = d[i];
1333:                            d[i] = n > Integer.MAX_VALUE ? Integer.MAX_VALUE
1334:                                    : (n < Integer.MIN_VALUE ? Integer.MIN_VALUE
1335:                                            : n);
1336:                        }
1337:                    }
1338:                    break;
1339:
1340:                case DataBuffer.TYPE_DOUBLE:
1341:                    double[][] dd = (double[][]) data;
1342:                    bands = dd.length;
1343:
1344:                    for (int j = 0; j < bands; j++) {
1345:                        double[] d = dd[j];
1346:                        size = d.length;
1347:
1348:                        for (int i = 0; i < size; i++) {
1349:                            double n = d[i];
1350:                            d[i] = n > Integer.MAX_VALUE ? Integer.MAX_VALUE
1351:                                    : (n < Integer.MIN_VALUE ? Integer.MIN_VALUE
1352:                                            : n);
1353:                        }
1354:                    }
1355:                    break;
1356:                }
1357:            }
1358:
1359:            private void clampFloat(Object data, int type) {
1360:                int bands, size;
1361:                switch (type) {
1362:                case DataBuffer.TYPE_DOUBLE:
1363:                    double[][] dd = (double[][]) data;
1364:                    bands = dd.length;
1365:
1366:                    for (int j = 0; j < bands; j++) {
1367:                        double[] d = dd[j];
1368:                        size = d.length;
1369:
1370:                        for (int i = 0; i < size; i++) {
1371:                            double n = d[i];
1372:                            d[i] = n > Float.MAX_VALUE ? Float.MAX_VALUE
1373:                                    : (n < -Float.MAX_VALUE ? -Float.MAX_VALUE
1374:                                            : n);
1375:                        }
1376:                    }
1377:                    break;
1378:                }
1379:            }
1380:
1381:            /**
1382:             * Returns a region of the pixel data within a <code>Raster</code>
1383:             * in a packed <code>byte</code> array.  The returned data are
1384:             * retrieved from the <code>Raster</code>'s <code>DataBuffer</code>;
1385:             * no pixel-to-color translation is performed.
1386:             *
1387:             * <p> This method only returns a valid result when the pixels are
1388:             * single-band and single-bit.  All other types of data result in
1389:             * an exception.  The data are packed in such a format that eight
1390:             * pixels are packed into one byte, and the end of each scanline is
1391:             * padded with zeros to the end of the byte.
1392:             *
1393:             * <p> In general, this method is called when operations are to be
1394:             * performed on the bit data in a packed format directly, to save
1395:             * memory usage.  The static method <code>isPackedOperation</code>
1396:             * should be used to determine whether the destination and/or its sources
1397:             * are suitable for performing operations to a packed array.
1398:             *
1399:             * <p> The <code>Rectangle</code> specifies the region of interest
1400:             * within which the pixel data are to be retrieved.  It must be
1401:             * completely inside the <code>Raster</code>'s boundary, or
1402:             * this method will throw an exception.
1403:             *
1404:             * @param raster  The <code>Raster</code> that contains the pixel data.
1405:             * @param rect  The region of interest within the <code>Raster</code>
1406:             *        where the pixels are accessed.
1407:             * @param isDest  Indicates whether this <code>Raster</code> is a
1408:             *        destination <code>Raster</code>.  That is, its pixels have
1409:             *        not been computed.
1410:             * @param coerceZeroOffset If <code>true</code> the returned
1411:             *        <code>PackedImageData</code> will be forced to have a
1412:             *        <code>bitOffset</code> and <code>offset</code> of zero
1413:             *        and a <code>lineStride</code> of <code>(rect.width+7)/8</code>.
1414:             *        The <code>coercedZeroOffset</code> field of the returned
1415:             *        <code>PackedImageData</code> will be set to <code>true</code>.
1416:             * @return The <code>PackedImageData</code> with its data filled in.
1417:             *
1418:             * @throws IllegalArgumentException  If data described by the
1419:             *         <code>Raster</code>'s <code>SampleModel</code> are not
1420:             *         single-band and single-bit.
1421:             * @throws IllegalArgumentException  If <code>rect</code> is not
1422:             *         within the bounds of the specified <code>Raster</code>.
1423:             */
1424:            public PackedImageData getPackedPixels(Raster raster,
1425:                    Rectangle rect, boolean isDest, boolean coerceZeroOffset) {
1426:                if (!isPacked) {
1427:                    throw new IllegalArgumentException(JaiI18N
1428:                            .getString("PixelAccessor3"));
1429:                }
1430:
1431:                if (!raster.getBounds().contains(rect)) {
1432:                    throw new IllegalArgumentException(JaiI18N
1433:                            .getString("PixelAccessor0"));
1434:                }
1435:
1436:                byte[] data; // packed pixels
1437:                int lineStride, offset, bitOffset; // access information
1438:                boolean set; // true if need to and can set data
1439:
1440:                if (isMultiPixelPackedSM) {
1441:
1442:                    set = isDest;
1443:
1444:                    if (coerceZeroOffset) {
1445:
1446:                        data = ImageUtil.getPackedBinaryData(raster, rect);
1447:                        lineStride = (rect.width + 7) / 8;
1448:                        offset = bitOffset = 0;
1449:
1450:                    } else {
1451:
1452:                        MultiPixelPackedSampleModel sm = (MultiPixelPackedSampleModel) sampleModel;
1453:
1454:                        DataBuffer db = raster.getDataBuffer();
1455:                        int dbOffset = db.getOffset();
1456:
1457:                        int x = rect.x - raster.getSampleModelTranslateX();
1458:                        int y = rect.y - raster.getSampleModelTranslateY();
1459:
1460:                        int smLineStride = sm.getScanlineStride();
1461:                        int minOffset = sm.getOffset(x, y) + dbOffset;
1462:                        int maxOffset = sm.getOffset(x + rect.width - 1, y)
1463:                                + dbOffset;
1464:                        int numElements = maxOffset - minOffset + 1; // per line
1465:                        int smBitOffset = sm.getBitOffset(x);
1466:
1467:                        switch (bufferType) { // DataBuffer type
1468:                        case DataBuffer.TYPE_BYTE: // no need to copy
1469:                            data = ((DataBufferByte) db).getData();
1470:                            lineStride = smLineStride;
1471:                            offset = minOffset;
1472:                            bitOffset = smBitOffset;
1473:                            set = false; // no need to set for destination
1474:                            break;
1475:
1476:                        // Copy even if it's destination so they can easily
1477:                        // be set back.
1478:                        case DataBuffer.TYPE_USHORT:
1479:                            lineStride = numElements * 2; // 2 bytes for each ushort
1480:                            offset = smBitOffset / 8;
1481:                            bitOffset = smBitOffset % 8;
1482:                            data = new byte[lineStride * rect.height];
1483:
1484:                            short[] sd = ((DataBufferUShort) db).getData();
1485:                            for (int i = 0, h = 0; h < rect.height; h++) {
1486:                                for (int w = minOffset; w <= maxOffset; w++) {
1487:                                    short d = sd[w];
1488:                                    data[i++] = (byte) ((d >>> 8) & 0xff);
1489:                                    data[i++] = (byte) (d & 0xff);
1490:                                }
1491:                                minOffset += smLineStride;
1492:                                maxOffset += smLineStride;
1493:                            }
1494:                            break;
1495:
1496:                        case DataBuffer.TYPE_INT:
1497:                            lineStride = numElements * 4; // 4 bytes for each int
1498:                            offset = smBitOffset / 8;
1499:                            bitOffset = smBitOffset % 8;
1500:                            data = new byte[lineStride * rect.height];
1501:
1502:                            int[] id = ((DataBufferInt) db).getData();
1503:                            for (int i = 0, h = 0; h < rect.height; h++) {
1504:                                for (int w = minOffset; w <= maxOffset; w++) {
1505:                                    int d = id[w];
1506:                                    data[i++] = (byte) ((d >>> 24) & 0xff);
1507:                                    data[i++] = (byte) ((d >>> 16) & 0xff);
1508:                                    data[i++] = (byte) ((d >>> 8) & 0xff);
1509:                                    data[i++] = (byte) (d & 0xff);
1510:                                }
1511:                                minOffset += smLineStride;
1512:                                maxOffset += smLineStride;
1513:                            }
1514:                            break;
1515:
1516:                        default:
1517:                            throw new RuntimeException(); // should never get here
1518:                        }
1519:                    }
1520:
1521:                } else { // unknown SampleModel
1522:                    lineStride = (rect.width + 7) / 8;
1523:                    offset = 0;
1524:                    bitOffset = 0;
1525:                    set = isDest & (raster instanceof  WritableRaster);
1526:                    data = new byte[lineStride * rect.height];
1527:
1528:                    if (!isDest) { // copy one line at a time to
1529:                        int size = lineStride * 8; // avoid using too much memory
1530:                        int[] p = new int[size];
1531:                        for (int i = 0, h = 0; h < rect.height; h++) {
1532:                            p = raster.getPixels(rect.x, rect.y + h,
1533:                                    rect.width, 1, p);
1534:                            for (int w = 0; w < size; w += 8) {
1535:                                data[i++] = (byte) (p[w] << 7 | p[w + 1] << 6
1536:                                        | p[w + 2] << 5 | p[w + 3] << 4
1537:                                        | p[w + 4] << 3 | p[w + 5] << 2
1538:                                        | p[w + 6] << 1 | p[w + 7]);
1539:                            }
1540:                        }
1541:                    }
1542:                }
1543:
1544:                return new PackedImageData(raster, rect, data, lineStride,
1545:                        offset, bitOffset, coerceZeroOffset, set);
1546:            }
1547:
1548:            /**
1549:             * Sets a region of the pixel data within a <code>Raster</code>
1550:             * using a primitive array.  This method copies data only if
1551:             * the <code>set</code> flag in <code>PackedImageData</code> is
1552:             * <code>true</code>.
1553:             *
1554:             * <p> The <code>PackedImageData</code> should be obtained by
1555:             * calling the <code>getPackedPixels()</code> method.
1556:             *
1557:             * @param pid The </code>PackedImageData</code> object whose pixels
1558:             *            are to be written.
1559:             * @throws IllegalArgumentException  If the <code>pid</code> is
1560:             *         <code>null</code>.
1561:             */
1562:            public void setPackedPixels(PackedImageData pid) {
1563:
1564:                if (pid == null) {
1565:                    throw new IllegalArgumentException(JaiI18N
1566:                            .getString("Generic0"));
1567:                }
1568:
1569:                if (!pid.convertToDest) {
1570:                    return;
1571:                }
1572:
1573:                Raster raster = pid.raster;
1574:                Rectangle rect = pid.rect;
1575:                byte[] data = pid.data;
1576:
1577:                if (isMultiPixelPackedSM) {
1578:
1579:                    if (pid.coercedZeroOffset) {
1580:                        ImageUtil.setPackedBinaryData(data,
1581:                                (WritableRaster) raster, rect);
1582:                    } else {
1583:                        MultiPixelPackedSampleModel sm = (MultiPixelPackedSampleModel) sampleModel;
1584:
1585:                        DataBuffer db = raster.getDataBuffer();
1586:                        int dbOffset = db.getOffset();
1587:
1588:                        int x = rect.x - raster.getSampleModelTranslateX();
1589:                        int y = rect.y - raster.getSampleModelTranslateY();
1590:
1591:                        int lineStride = sm.getScanlineStride();
1592:                        int minOffset = sm.getOffset(x, y) + dbOffset;
1593:                        int maxOffset = sm.getOffset(x + rect.width - 1, y)
1594:                                + dbOffset;
1595:
1596:                        // Only need to set for buffer types of ushort and int.
1597:                        switch (bufferType) {
1598:                        case DataBuffer.TYPE_USHORT:
1599:                            short[] sd = ((DataBufferUShort) db).getData();
1600:                            for (int i = 0, h = 0; h < rect.height; h++) {
1601:                                for (int w = minOffset; w <= maxOffset; w++) {
1602:                                    sd[w] = (short) (data[i++] << 8 | data[i++]);
1603:                                }
1604:                                minOffset += lineStride;
1605:                                maxOffset += lineStride;
1606:                            }
1607:                            break;
1608:
1609:                        case DataBuffer.TYPE_INT:
1610:                            int[] id = ((DataBufferInt) db).getData();
1611:                            for (int i = 0, h = 0; h < rect.height; h++) {
1612:                                for (int w = minOffset; w <= maxOffset; w++) {
1613:                                    id[w] = data[i++] << 24 | data[i++] << 16
1614:                                            | data[i++] << 8 | data[i++];
1615:                                }
1616:                                minOffset += lineStride;
1617:                                maxOffset += lineStride;
1618:                            }
1619:                            break;
1620:                        }
1621:                    }
1622:
1623:                } else {
1624:                    /*
1625:                     * The getPackedData() method should set "set" to false if
1626:                     * the Raster is not writable.
1627:                     * Copy one line at a time to avoid using too much memory.
1628:                     */
1629:                    WritableRaster wr = (WritableRaster) raster;
1630:                    int size = pid.lineStride * 8;
1631:                    int[] p = new int[size];
1632:
1633:                    for (int i = 0, h = 0; h < rect.height; h++) {
1634:                        for (int w = 0; w < size; w += 8) {
1635:                            p[w] = (data[i] >>> 7) & 0x1;
1636:                            p[w + 1] = (data[i] >>> 6) & 0x1;
1637:                            p[w + 2] = (data[i] >>> 5) & 0x1;
1638:                            p[w + 3] = (data[i] >>> 4) & 0x1;
1639:                            p[w + 4] = (data[i] >>> 3) & 0x1;
1640:                            p[w + 5] = (data[i] >>> 2) & 0x1;
1641:                            p[w + 6] = (data[i] >>> 1) & 0x1;
1642:                            p[w + 7] = data[i] & 0x1;
1643:                            i++;
1644:                        }
1645:                        wr.setPixels(rect.x, rect.y + h, rect.width, 1, p);
1646:                    }
1647:                }
1648:            }
1649:
1650:            /**
1651:             * Returns an array of unnormalized color/alpha components in the
1652:             * <code>ColorSpace</code> defined in the image's
1653:             * <code>ColorModel</code>.  This method retrieves the pixel data
1654:             * within the specified rectangular region from the
1655:             * <code>Raster</code>, performs the pixel-to-color translation based
1656:             * on the image's <code>ColorModel</code>, and returns the components
1657:             * in the order specified by the <code>ColorSpace</code>.
1658:             *
1659:             * <p> In order for this method to return a valid result, the
1660:             * image must have a valid <code>ColorModel</code> that is compatible
1661:             * with the image's <code>SampleModel</code>.  Further, the
1662:             * <code>SampleModel</code> and <code>ColorModel</code> must have
1663:             * the same <code>transferType</code>.
1664:             *
1665:             * <p> The component data are stored in a primitive array of the
1666:             * type specified by the <code>type</code> argument.  It must be one
1667:             * of the valid data types defined in <code>DataBuffer</code> and
1668:             * large (in bit depth) enough to hold the color/alpha components,
1669:             * or an exception is thrown.  This means <code>type</code> should
1670:             * be greater than or equal to <code>componentType</code>.  To avoid
1671:             * extra array copy, it is best to use
1672:             * <code>DataBuffer.TYPE_INT</code> for this argument.
1673:             *
1674:             * <p> The <code>Rectangle</code> specifies the region of interest
1675:             * within which the pixel data are to be retrieved.  It must be
1676:             * completely inside the <code>Raster</code>'s boundary, or else
1677:             * this method throws an exception.
1678:             *
1679:             * @param raster  The <code>Raster</code> that contains the pixel data.
1680:             * @param rect  The region of interest within the <code>Raster</code>
1681:             *        where the pixels are accessed.
1682:             * @param type  The type of the primitive array used to return the
1683:             *        color/alpha components with.
1684:             * @return The <code>UnpackedImageData</code> with its data filled in.
1685:             *
1686:             * @throws IllegalArgumentException  If the image does not have a valid
1687:             *         <code>ColorModel</code> that is compatible with its
1688:             *         <code>SampleModel</code>.
1689:             * @throws IllegalArgumentException  If <code>type</code> is not a
1690:             *         valid data type defined in <code>DataBuffer</code>, or
1691:             *         is not large enough to hold the translated color/alpha
1692:             *         components.
1693:             * @throws IllegalArgumentException  If <code>rect</code> is not
1694:             *         contained by the bounds of the specified <code>Raster</code>.
1695:             */
1696:            public UnpackedImageData getComponents(Raster raster,
1697:                    Rectangle rect, int type) {
1698:                if (!hasCompatibleCM) {
1699:                    throw new IllegalArgumentException(JaiI18N
1700:                            .getString("PixelAccessor5"));
1701:                }
1702:
1703:                if (!raster.getBounds().contains(rect)) {
1704:                    throw new IllegalArgumentException(JaiI18N
1705:                            .getString("PixelAccessor0"));
1706:                }
1707:
1708:                if (type < DataBuffer.TYPE_BYTE
1709:                        || type > DataBuffer.TYPE_DOUBLE) { // unknown data type
1710:                    throw new IllegalArgumentException(JaiI18N
1711:                            .getString("PixelAccessor1"));
1712:                }
1713:
1714:                if (type < componentType
1715:                        || (componentType == DataBuffer.TYPE_USHORT && type == DataBuffer.TYPE_SHORT)) { // type not large enough
1716:                    throw new IllegalArgumentException(JaiI18N
1717:                            .getString("PixelAccessor4"));
1718:                }
1719:
1720:                // Get color/alpha components in an integer array.
1721:                int size = rect.width * rect.height * numComponents;
1722:                int[] ic = new int[size];
1723:                int width = rect.x + rect.width;
1724:                int height = rect.y + rect.height;
1725:
1726:                for (int i = 0, y = rect.y; y < height; y++) {
1727:                    for (int x = rect.x; x < width; x++) {
1728:                        Object p = raster.getDataElements(x, y, null);
1729:                        colorModel.getComponents(p, ic, i);
1730:                        i += numComponents;
1731:                    }
1732:                }
1733:
1734:                // Reformat components into the specified data type.
1735:                Object data = null;
1736:                switch (type) {
1737:                case DataBuffer.TYPE_BYTE:
1738:                    byte[] bc = new byte[size];
1739:                    for (int i = 0; i < size; i++) {
1740:                        bc[i] = (byte) (ic[i] & 0xff);
1741:                    }
1742:                    data = repeatBand(bc, numComponents);
1743:                    break;
1744:
1745:                case DataBuffer.TYPE_USHORT:
1746:                    short[] usc = new short[size];
1747:                    for (int i = 0; i < size; i++) {
1748:                        usc[i] = (short) (ic[i] & 0xffff);
1749:                    }
1750:                    data = repeatBand(usc, numComponents);
1751:                    break;
1752:
1753:                case DataBuffer.TYPE_SHORT:
1754:                    short[] sc = new short[size];
1755:                    for (int i = 0; i < size; i++) {
1756:                        sc[i] = (short) ic[i];
1757:                    }
1758:                    data = repeatBand(sc, numComponents);
1759:                    break;
1760:
1761:                case DataBuffer.TYPE_INT:
1762:                    data = repeatBand(ic, numComponents);
1763:                    break;
1764:
1765:                case DataBuffer.TYPE_FLOAT:
1766:                    float[] fc = new float[size];
1767:                    for (int i = 0; i < size; i++) {
1768:                        fc[i] = ic[i];
1769:                    }
1770:                    data = repeatBand(fc, numComponents);
1771:                    break;
1772:
1773:                case DataBuffer.TYPE_DOUBLE:
1774:                    double[] dc = new double[size];
1775:                    for (int i = 0; i < size; i++) {
1776:                        dc[i] = ic[i];
1777:                    }
1778:                    data = repeatBand(dc, numComponents);
1779:                    break;
1780:                }
1781:
1782:                return new UnpackedImageData(raster, rect, type, data,
1783:                        numComponents, numComponents * rect.width,
1784:                        getInterleavedOffsets(numComponents),
1785:                        raster instanceof  WritableRaster);
1786:            }
1787:
1788:            /**
1789:             * Given an array of unnormalized color/alpha components, this
1790:             * method performs color-to-pixel translation, and sets the
1791:             * translated pixel data back to the <code>Raster</code> within
1792:             * a specific region.  It is very important that the components
1793:             * array along with access information are obtained by calling
1794:             * the <code>getComponents()</code> method, or errors
1795:             * will occur.
1796:             *
1797:             * <p> In order for this method to return a valid result, the
1798:             * image must have a valid <code>ColorModel</code> that is compatible
1799:             * with the image's <code>SampleModel</code>.  Further, the
1800:             * <code>SampleModel</code> and <code>ColorModel</code> must have
1801:             * the same <code>transferType</code>.
1802:             *
1803:             * <p> This method sets data only if the <code>set</code> flag in
1804:             * <code>UnpackedImageData</code> is <code>true</code>.
1805:             *
1806:             * @param uid The <code>UnpackedImageData</code> whose data is to be set.
1807:             * @throws IllegalArgumentException  If the <code>uid</code> is
1808:             *         <code>null</code>.
1809:             */
1810:            public void setComponents(UnpackedImageData uid) {
1811:
1812:                if (uid == null) {
1813:                    throw new IllegalArgumentException(JaiI18N
1814:                            .getString("Generic0"));
1815:                }
1816:
1817:                if (!uid.convertToDest) {
1818:                    return;
1819:                }
1820:
1821:                WritableRaster raster = (WritableRaster) uid.raster;
1822:                Rectangle rect = uid.rect;
1823:                int type = uid.type;
1824:
1825:                int size = rect.width * rect.height * numComponents;
1826:                int[] ic = null;
1827:
1828:                switch (type) {
1829:                case DataBuffer.TYPE_BYTE:
1830:                    byte[] bc = uid.getByteData(0);
1831:                    ic = new int[size];
1832:                    for (int i = 0; i < size; i++) {
1833:                        ic[i] = bc[i] & 0xff;
1834:                    }
1835:                    break;
1836:
1837:                case DataBuffer.TYPE_USHORT:
1838:                    short[] usc = uid.getShortData(0);
1839:                    ic = new int[size];
1840:                    for (int i = 0; i < size; i++) {
1841:                        ic[i] = usc[i] & 0xffff;
1842:                    }
1843:                    break;
1844:
1845:                case DataBuffer.TYPE_SHORT:
1846:                    short[] sc = uid.getShortData(0);
1847:                    ic = new int[size];
1848:                    for (int i = 0; i < size; i++) {
1849:                        ic[i] = sc[i];
1850:                    }
1851:                    break;
1852:
1853:                case DataBuffer.TYPE_INT:
1854:                    ic = uid.getIntData(0);
1855:                    break;
1856:
1857:                case DataBuffer.TYPE_FLOAT:
1858:                    float[] fc = uid.getFloatData(0);
1859:                    ic = new int[size];
1860:                    for (int i = 0; i < size; i++) {
1861:                        ic[i] = (int) fc[i];
1862:                        ;
1863:                    }
1864:                    break;
1865:
1866:                case DataBuffer.TYPE_DOUBLE:
1867:                    double[] dc = uid.getDoubleData(0);
1868:                    ic = new int[size];
1869:                    for (int i = 0; i < size; i++) {
1870:                        ic[i] = (int) dc[i];
1871:                    }
1872:                    break;
1873:                }
1874:
1875:                int width = rect.x + rect.width;
1876:                int height = rect.y + rect.height;
1877:
1878:                for (int i = 0, y = rect.y; y < height; y++) {
1879:                    for (int x = rect.x; x < width; x++) {
1880:                        Object p = colorModel.getDataElements(ic, i, null);
1881:                        raster.setDataElements(x, y, p);
1882:                        i += numComponents;
1883:                    }
1884:                }
1885:            }
1886:
1887:            /**
1888:             * Returns an array of color/alpha components scaled from 0 to 255
1889:             * in the default sRGB <code>ColorSpace</code>.  This method
1890:             * retrieves the pixel data within the specified rectangular region
1891:             * from the <code>Raster</code>, performs the pixel-to-color translation
1892:             * based on the image's <code>ColorModel</code>, and returns the
1893:             * components in the order specified by the <code>ColorSpace</code>.
1894:             *
1895:             * <p> In order for this method to return a valid result, the
1896:             * image must have a valid <code>ColorModel</code> that is compatible
1897:             * with the image's <code>SampleModel</code>.  Further, the
1898:             * <code>SampleModel</code> and <code>ColorModel</code> must have
1899:             * the same <code>transferType</code>.
1900:             *
1901:             * <p> The component data are stored in a two-dimensional,
1902:             * band-interleaved, <code>byte</code> array, because the components
1903:             * are always scaled from 0 to 255.  Red is band 0, green is band 1,
1904:             * blue is band 2, and alpha is band 3.
1905:             *
1906:             * <p> The <code>Rectangle</code> specifies the region of interest
1907:             * within which the pixel data are to be retrieved.  It must be
1908:             * completely inside the <code>Raster</code>'s boundary, or
1909:             * this method will throw an exception.
1910:             *
1911:             * @param raster  The <code>Raster</code> that contains the pixel data.
1912:             * @param rect  The region of interest within the <code>Raster</code>
1913:             *        where the pixels are accessed.
1914:             * @return The <code>UnpackedImageData</code> with its data filled in.
1915:             *
1916:             * @throws IllegalArgumentException  If the image does not have a valid
1917:             *         <code>ColorModel</code> that is compatible with its
1918:             *         <code>SampleModel</code>.
1919:             * @throws IllegalArgumentException  If <code>rect</code> is not
1920:             *         contained by the bounds of the specified <code>Raster</code>.
1921:             */
1922:            public UnpackedImageData getComponentsRGB(Raster raster,
1923:                    Rectangle rect) {
1924:                if (!hasCompatibleCM) {
1925:                    throw new IllegalArgumentException(JaiI18N
1926:                            .getString("PixelAccessor5"));
1927:                }
1928:
1929:                if (!raster.getBounds().contains(rect)) {
1930:                    throw new IllegalArgumentException(JaiI18N
1931:                            .getString("PixelAccessor0"));
1932:                }
1933:
1934:                int size = rect.width * rect.height;
1935:
1936:                byte[][] data = new byte[4][size];
1937:                byte[] r = data[0]; // red
1938:                byte[] g = data[1]; // green
1939:                byte[] b = data[2]; // blue
1940:                byte[] a = data[3]; // alpha
1941:
1942:                // Get color/alpha components in an integer array.
1943:                int maxX = rect.x + rect.width;
1944:                int maxY = rect.y + rect.height;
1945:
1946:                if (isIndexCM) {
1947:                    // Cast the CM and get the size of the ICM tables.
1948:                    IndexColorModel icm = (IndexColorModel) colorModel;
1949:                    int mapSize = icm.getMapSize();
1950:
1951:                    // Load the ICM tables.
1952:                    byte[] reds = new byte[mapSize];
1953:                    icm.getReds(reds);
1954:                    byte[] greens = new byte[mapSize];
1955:                    icm.getGreens(greens);
1956:                    byte[] blues = new byte[mapSize];
1957:                    icm.getBlues(blues);
1958:                    byte[] alphas = null;
1959:                    if (icm.hasAlpha()) {
1960:                        alphas = new byte[mapSize];
1961:                        icm.getAlphas(alphas);
1962:                    }
1963:
1964:                    // Get the index values.
1965:                    int[] indices = raster.getPixels(rect.x, rect.y,
1966:                            rect.width, rect.height, (int[]) null);
1967:
1968:                    // Use the ICM tables to get the [A]RGB values.
1969:                    if (alphas == null) {
1970:                        // No alpha.
1971:                        for (int i = 0, y = rect.y; y < maxY; y++) {
1972:                            for (int x = rect.x; x < maxX; x++) {
1973:                                int index = indices[i];
1974:
1975:                                r[i] = reds[index];
1976:                                g[i] = greens[index];
1977:                                b[i] = blues[index];
1978:
1979:                                i++;
1980:                            }
1981:                        }
1982:                    } else {
1983:                        // Alpha.
1984:                        for (int i = 0, y = rect.y; y < maxY; y++) {
1985:                            for (int x = rect.x; x < maxX; x++) {
1986:                                int index = indices[i];
1987:
1988:                                r[i] = reds[index];
1989:                                g[i] = greens[index];
1990:                                b[i] = blues[index];
1991:                                a[i] = alphas[index];
1992:
1993:                                i++;
1994:                            }
1995:                        }
1996:                    }
1997:                } else {
1998:                    // XXX If ColorSpaceJAI is implemented use the
1999:                    // Raster-based methods here.
2000:                    // Not an IndexColorModel: use the "slow method".
2001:                    for (int i = 0, y = rect.y; y < maxY; y++) {
2002:                        for (int x = rect.x; x < maxX; x++) {
2003:                            Object p = raster.getDataElements(x, y, null);
2004:
2005:                            r[i] = (byte) colorModel.getRed(p);
2006:                            g[i] = (byte) colorModel.getGreen(p);
2007:                            b[i] = (byte) colorModel.getBlue(p);
2008:                            a[i] = (byte) colorModel.getAlpha(p);
2009:                            i++;
2010:                        }
2011:                    }
2012:                }
2013:
2014:                return new UnpackedImageData(raster, rect,
2015:                        DataBuffer.TYPE_BYTE, data, 1, rect.width, new int[4], // all entries automatically initialized to 0
2016:                        raster instanceof  WritableRaster);
2017:            }
2018:
2019:            /**
2020:             * Given an array of normalized (between 0 and 255) alpha/RGB color
2021:             * components, this method performs color-to-pixel translation, and
2022:             * sets the translated pixel data back to the <code>Raster</code>
2023:             * within a specific region.  It is very important that the components
2024:             * array along with access information are obtained by calling
2025:             * the <code>getComponentsRGB()</code> method, or errors
2026:             * will occur.
2027:             *
2028:             * <p> In order for this method to return a valid result, the
2029:             * image must have a valid <code>ColorModel</code> that is compatible
2030:             * with the image's <code>SampleModel</code>.  Furthermore, the
2031:             * <code>SampleModel</code> and <code>ColorModel</code> must have
2032:             * the same <code>transferType</code>.
2033:             *
2034:             * <p> This method sets data only if the <code>set</code> flag in
2035:             * <code>UnpackedImageData</code> is <code>true</code>.
2036:             *
2037:             * @param uid The <code>UnpackedImageData</code> to set.
2038:             * @throws IllegalArgumentException  If the <code>uid</code> is
2039:             *         <code>null</code>.
2040:             */
2041:            public void setComponentsRGB(UnpackedImageData uid) {
2042:
2043:                if (uid == null) {
2044:                    throw new IllegalArgumentException(JaiI18N
2045:                            .getString("Generic0"));
2046:                }
2047:
2048:                if (!uid.convertToDest) {
2049:                    return;
2050:                }
2051:
2052:                byte[][] data = uid.getByteData();
2053:                byte[] r = data[0]; // red
2054:                byte[] g = data[1]; // green
2055:                byte[] b = data[2]; // blue
2056:                byte[] a = data[3]; // alpha
2057:
2058:                WritableRaster raster = (WritableRaster) uid.raster;
2059:                Rectangle rect = uid.rect;
2060:
2061:                int maxX = rect.x + rect.width;
2062:                int maxY = rect.y + rect.height;
2063:
2064:                for (int i = 0, y = rect.y; y < maxY; y++) {
2065:                    for (int x = rect.x; x < maxX; x++) {
2066:                        int rgb = (a[i] << 24) | (b[i] << 16) | (g[i] << 8)
2067:                                | r[i];
2068:
2069:                        Object p = colorModel.getDataElements(rgb, null);
2070:                        raster.setDataElements(x, y, p);
2071:                        i++;
2072:                    }
2073:                }
2074:            }
2075:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.