Source Code Cross Referenced for ImageComponentRetained.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » 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 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: ImageComponentRetained.java,v $
0003:         *
0004:         * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.19 $
0028:         * $Date: 2008/02/28 20:17:23 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import java.nio.Buffer;
0035:        import java.util.*;
0036:        import java.awt.image.*;
0037:        import java.awt.color.ColorSpace;
0038:        import java.awt.geom.AffineTransform;
0039:        import java.awt.image.AffineTransformOp;
0040:        import java.awt.image.RenderedImage;
0041:        import java.nio.ByteBuffer;
0042:        import java.nio.ByteOrder;
0043:        import java.nio.IntBuffer;
0044:        import java.util.logging.Level;
0045:
0046:        /**
0047:         * Abstract class that is used to define 2D or 3D ImageComponent classes
0048:         * used in a Java 3D scene graph.
0049:         * This is used for texture images, background images and raster components
0050:         * of Shape3D nodes.
0051:         */
0052:
0053:        abstract class ImageComponentRetained extends NodeComponentRetained {
0054:
0055:            // change flag
0056:            static final int IMAGE_CHANGED = 0x01;
0057:            static final int SUBIMAGE_CHANGED = 0x02;
0058:
0059:            static final int TYPE_BYTE_BGR = 0x1;
0060:            static final int TYPE_BYTE_RGB = 0x2;
0061:            static final int TYPE_BYTE_ABGR = 0x4;
0062:            static final int TYPE_BYTE_RGBA = 0x8;
0063:            static final int TYPE_BYTE_LA = 0x10;
0064:            static final int TYPE_BYTE_GRAY = 0x20;
0065:            static final int TYPE_USHORT_GRAY = 0x40;
0066:            static final int TYPE_INT_BGR = 0x80;
0067:            static final int TYPE_INT_RGB = 0x100;
0068:            static final int TYPE_INT_ARGB = 0x200;
0069:
0070:            static final int IMAGE_SIZE_512X512 = 262144;
0071:
0072:            enum ImageFormatType {
0073:                TYPE_UNKNOWN, TYPE_BYTE_BGR, TYPE_BYTE_RGB, TYPE_BYTE_ABGR, TYPE_BYTE_RGBA, TYPE_BYTE_LA, TYPE_BYTE_GRAY, TYPE_USHORT_GRAY, TYPE_INT_BGR, TYPE_INT_RGB, TYPE_INT_ARGB
0074:            }
0075:
0076:            static final int IMAGE_DATA_TYPE_BYTE_ARRAY = 0x1000;
0077:            static final int IMAGE_DATA_TYPE_INT_ARRAY = 0x2000;
0078:            static final int IMAGE_DATA_TYPE_BYTE_BUFFER = 0x4000;
0079:            static final int IMAGE_DATA_TYPE_INT_BUFFER = 0x8000;
0080:
0081:            enum ImageDataType {
0082:                TYPE_NULL, TYPE_BYTE_ARRAY, TYPE_INT_ARRAY, TYPE_BYTE_BUFFER, TYPE_INT_BUFFER
0083:            }
0084:
0085:            private int apiFormat; // The format set by user.
0086:            int width; // Width of PixelArray
0087:            int height; // Height of PixelArray
0088:            int depth; // Depth of PixelArray
0089:            boolean byReference = false; // Is the imageComponent by reference
0090:            boolean yUp = false;
0091:            boolean imageTypeIsSupported;
0092:            boolean abgrSupported = true;
0093:            boolean npotSupported = true;
0094:            private int unitsPerPixel;
0095:            private int numberOfComponents;
0096:
0097:            // Note : This is unuse for NioImageBuffer.
0098:            // The image type of the input image. Using the constant in BufferedImage
0099:            private int imageType;
0100:
0101:            private ImageFormatType imageFormatType = ImageFormatType.TYPE_UNKNOWN;
0102:            ImageData imageData;
0103:            private ImageComponent.ImageClass imageClass = ImageComponent.ImageClass.BUFFERED_IMAGE;
0104:
0105:            // To support Non power of 2 (NPOT) image
0106:            // if enforceNonPowerOfTwoSupport is true (for examples Raster and Background)
0107:            // and imageData is a non power of 2 image
0108:            // and graphics driver doesn't support NPOT extension.
0109:            private ImageData imageDataPowerOfTwo;
0110:            private AffineTransformOp powerOfTwoATOp;
0111:            // The following flag means that if the image is non-power-of-two and the 
0112:            // card doesn't support NPOT texture, we will scale the image to a power 
0113:            // of two.
0114:            private boolean enforceNonPowerOfTwoSupport = false;
0115:            private boolean usedByOffScreenCanvas = false;
0116:
0117:            // This will store the referenced Images for reference case.
0118:            // private RenderedImage refImage[] = null;
0119:            private Object refImage[] = null;
0120:
0121:            // Issue 366: Lock for evaluateExtensions
0122:            Object evaluateExtLock = new Object();
0123:
0124:            // Lock used in the "by ref case"
0125:            GeometryLock geomLock = new GeometryLock();
0126:
0127:            int tilew = 0;
0128:            int tileh = 0;
0129:            int numXTiles = 0;
0130:            int numYTiles = 0;
0131:
0132:            // lists of Node Components that are referencing this ImageComponent
0133:            // object. This list is used to notify the referencing node components
0134:            // of any changes of this ImageComponent.
0135:            ArrayList userList = new ArrayList();
0136:
0137:            /**
0138:             * Retrieves the width of this image component object.
0139:             * @return the width of this image component object
0140:             */
0141:            int getWidth() {
0142:                return width;
0143:            }
0144:
0145:            /**
0146:             * Retrieves the height of this image component object.
0147:             * @return the height of this image component object
0148:             */
0149:            int getHeight() {
0150:                return height;
0151:            }
0152:
0153:            /**
0154:             * Retrieves the apiFormat of this image component object.
0155:             *
0156:             * @return the apiFormat of this image component object
0157:             */
0158:            int getFormat() {
0159:                return apiFormat;
0160:            }
0161:
0162:            void setFormat(int format) {
0163:                this .apiFormat = format;
0164:            }
0165:
0166:            void setByReference(boolean byReference) {
0167:                this .byReference = byReference;
0168:            }
0169:
0170:            boolean isByReference() {
0171:                return byReference;
0172:            }
0173:
0174:            void setYUp(boolean yUp) {
0175:                this .yUp = yUp;
0176:            }
0177:
0178:            boolean isYUp() {
0179:                return yUp;
0180:            }
0181:
0182:            int getUnitsPerPixel() {
0183:                return unitsPerPixel;
0184:            }
0185:
0186:            void setUnitsPerPixel(int ipp) {
0187:                unitsPerPixel = ipp;
0188:            }
0189:
0190:            ImageComponent.ImageClass getImageClass() {
0191:                return imageClass;
0192:            }
0193:
0194:            void setImageClass(RenderedImage image) {
0195:                if (image instanceof  BufferedImage) {
0196:                    imageClass = ImageComponent.ImageClass.BUFFERED_IMAGE;
0197:                } else {
0198:                    imageClass = ImageComponent.ImageClass.RENDERED_IMAGE;
0199:                }
0200:            }
0201:
0202:            void setImageClass(NioImageBuffer image) {
0203:                imageClass = ImageComponent.ImageClass.NIO_IMAGE_BUFFER;
0204:            }
0205:
0206:            void setEnforceNonPowerOfTwoSupport(boolean npot) {
0207:                this .enforceNonPowerOfTwoSupport = npot;
0208:            }
0209:
0210:            void setUsedByOffScreen(boolean used) {
0211:                usedByOffScreenCanvas = used;
0212:            }
0213:
0214:            boolean getUsedByOffScreen() {
0215:                return usedByOffScreenCanvas;
0216:            }
0217:
0218:            int getNumberOfComponents() {
0219:                return numberOfComponents;
0220:            }
0221:
0222:            void setNumberOfComponents(int numberOfComponents) {
0223:                this .numberOfComponents = numberOfComponents;
0224:            }
0225:
0226:            int getImageDataTypeIntValue() {
0227:                int idtValue = -1;
0228:                switch (imageData.imageDataType) {
0229:                case TYPE_BYTE_ARRAY:
0230:                    idtValue = IMAGE_DATA_TYPE_BYTE_ARRAY;
0231:                    break;
0232:                case TYPE_INT_ARRAY:
0233:                    idtValue = IMAGE_DATA_TYPE_INT_ARRAY;
0234:                    break;
0235:                case TYPE_BYTE_BUFFER:
0236:                    idtValue = IMAGE_DATA_TYPE_BYTE_BUFFER;
0237:                    break;
0238:                case TYPE_INT_BUFFER:
0239:                    idtValue = IMAGE_DATA_TYPE_INT_BUFFER;
0240:                    break;
0241:                default:
0242:                    assert false;
0243:                }
0244:                return idtValue;
0245:
0246:            }
0247:
0248:            int getImageFormatTypeIntValue(boolean powerOfTwoData) {
0249:                int iftValue = -1;
0250:                switch (imageFormatType) {
0251:                case TYPE_BYTE_BGR:
0252:                    iftValue = TYPE_BYTE_BGR;
0253:                    break;
0254:                case TYPE_BYTE_RGB:
0255:                    iftValue = TYPE_BYTE_RGB;
0256:                    break;
0257:                case TYPE_BYTE_ABGR:
0258:                    iftValue = TYPE_BYTE_ABGR;
0259:                    break;
0260:                case TYPE_BYTE_RGBA:
0261:                    if ((imageDataPowerOfTwo != null) && (powerOfTwoData)) {
0262:                        iftValue = TYPE_BYTE_ABGR;
0263:                    } else {
0264:                        iftValue = TYPE_BYTE_RGBA;
0265:                    }
0266:                    break;
0267:                case TYPE_BYTE_LA:
0268:                    iftValue = TYPE_BYTE_LA;
0269:                    break;
0270:                case TYPE_BYTE_GRAY:
0271:                    iftValue = TYPE_BYTE_GRAY;
0272:                    break;
0273:                case TYPE_USHORT_GRAY:
0274:                    iftValue = TYPE_USHORT_GRAY;
0275:                    break;
0276:                case TYPE_INT_BGR:
0277:                    iftValue = TYPE_INT_BGR;
0278:                    break;
0279:                case TYPE_INT_RGB:
0280:                    iftValue = TYPE_INT_RGB;
0281:                    break;
0282:                case TYPE_INT_ARGB:
0283:                    iftValue = TYPE_INT_ARGB;
0284:                    break;
0285:                default:
0286:                    throw new AssertionError();
0287:                }
0288:                return iftValue;
0289:            }
0290:
0291:            // Note: This method for RenderedImage, can't be used by NioImageBuffer.
0292:            int getImageType() {
0293:                return imageType;
0294:            }
0295:
0296:            void setImageFormatType(ImageFormatType ift) {
0297:                this .imageFormatType = ift;
0298:            }
0299:
0300:            ImageFormatType getImageFormatType() {
0301:                return this .imageFormatType;
0302:            }
0303:
0304:            void setRefImage(Object image, int index) {
0305:                this .refImage[index] = image;
0306:            }
0307:
0308:            Object getRefImage(int index) {
0309:                return this .refImage[index];
0310:            }
0311:
0312:            ImageData getImageData(boolean npotSupportNeeded) {
0313:                if (npotSupportNeeded) {
0314:                    assert enforceNonPowerOfTwoSupport;
0315:                    if (imageDataPowerOfTwo != null) {
0316:                        return imageDataPowerOfTwo;
0317:                    }
0318:                }
0319:                return imageData;
0320:            }
0321:
0322:            boolean useBilinearFilter() {
0323:                if (imageDataPowerOfTwo != null) {
0324:                    return true;
0325:                }
0326:
0327:                return false;
0328:            }
0329:
0330:            boolean isImageTypeSupported() {
0331:                return imageTypeIsSupported;
0332:            }
0333:
0334:            /**
0335:             * Check if ImageComponent parameters have valid values.
0336:             */
0337:            void processParams(int format, int width, int height, int depth) {
0338:                if (width < 1)
0339:                    throw new IllegalArgumentException(J3dI18N
0340:                            .getString("ImageComponentRetained0"));
0341:
0342:                if (height < 1)
0343:                    throw new IllegalArgumentException(J3dI18N
0344:                            .getString("ImageComponentRetained1"));
0345:
0346:                if (depth < 1)
0347:                    throw new IllegalArgumentException(J3dI18N
0348:                            .getString("ImageComponentRetained2"));
0349:
0350:                // If the format is 8bit per component, we may send it down
0351:                // to OpenGL directly if its by ref case
0352:                switch (format) {
0353:                case ImageComponent.FORMAT_RGB:// same as ImageComponent.FORMAT_RGB8
0354:                case ImageComponent.FORMAT_RGB4: // Need to be Deprecated
0355:                case ImageComponent.FORMAT_RGB5: // Need to be Deprecated
0356:                case ImageComponent.FORMAT_R3_G3_B2: // Need to be Deprecated
0357:                    numberOfComponents = 3;
0358:                    break;
0359:                case ImageComponent.FORMAT_RGBA:// same as ImageComponent.FORMAT_RGBA8
0360:                case ImageComponent.FORMAT_RGB5_A1: // Need to be Deprecated
0361:                case ImageComponent.FORMAT_RGBA4: // Need to be Deprecated
0362:                    numberOfComponents = 4;
0363:                    break;
0364:                case ImageComponent.FORMAT_LUM4_ALPHA4: // Need to be Deprecated
0365:                case ImageComponent.FORMAT_LUM8_ALPHA8:
0366:                    numberOfComponents = 2;
0367:                    break;
0368:                case ImageComponent.FORMAT_CHANNEL8:
0369:                    numberOfComponents = 1;
0370:                    break;
0371:                default:
0372:                    throw new IllegalArgumentException(J3dI18N
0373:                            .getString("ImageComponentRetained3"));
0374:                }
0375:
0376:                this .setFormat(format);
0377:                this .width = width;
0378:                this .height = height;
0379:                this .depth = depth;
0380:                refImage = new Object[depth];
0381:            }
0382:
0383:            int evaluateImageType(RenderedImage ri) {
0384:                int imageType = BufferedImage.TYPE_CUSTOM;
0385:
0386:                if (ri instanceof  BufferedImage) {
0387:                    imageType = ((BufferedImage) ri).getType();
0388:
0389:                    if (imageType != BufferedImage.TYPE_CUSTOM) {
0390:                        return imageType;
0391:                    }
0392:                } else {
0393:                    // Fix to Issue 412. Force copy for RenderedImage of type not equal to BufferedImage. 
0394:                    return imageType;
0395:                }
0396:
0397:                // System.err.println("This is a RenderedImage or BufferedImage with TYPE_CUSTOM. It imageType classification may not be correct.");
0398:                ColorModel cm = ri.getColorModel();
0399:                ColorSpace cs = cm.getColorSpace();
0400:                SampleModel sm = ri.getSampleModel();
0401:
0402:                int csType = cs.getType();
0403:                boolean isAlphaPre = cm.isAlphaPremultiplied();
0404:
0405:                if (csType == ColorSpace.TYPE_GRAY
0406:                        && cm instanceof  ComponentColorModel) {
0407:                    if (sm.getDataType() == DataBuffer.TYPE_BYTE) {
0408:                        imageType = BufferedImage.TYPE_BYTE_GRAY;
0409:                    } else if (sm.getDataType() == DataBuffer.TYPE_USHORT) {
0410:                        imageType = BufferedImage.TYPE_USHORT_GRAY;
0411:                    }
0412:                }
0413:
0414:                // RGB , only interested in BYTE ABGR and BGR for now
0415:                // all others will be copied to a buffered image
0416:                else if (csType == ColorSpace.TYPE_RGB) {
0417:                    int comparedBit = 0;
0418:                    int smDataType = sm.getDataType();
0419:                    if (smDataType == DataBuffer.TYPE_BYTE) {
0420:                        comparedBit = 8;
0421:                    } else if (smDataType == DataBuffer.TYPE_INT) {
0422:                        comparedBit = 32;
0423:                    }
0424:
0425:                    if (comparedBit != 0) {
0426:                        int numBands = sm.getNumBands();
0427:                        if (cm instanceof  ComponentColorModel
0428:                                && sm instanceof  PixelInterleavedSampleModel) {
0429:                            PixelInterleavedSampleModel csm = (PixelInterleavedSampleModel) sm;
0430:                            int[] offs = csm.getBandOffsets();
0431:                            ComponentColorModel ccm = (ComponentColorModel) cm;
0432:                            int[] nBits = ccm.getComponentSize();
0433:                            boolean isNBit = true;
0434:                            for (int i = 0; i < numBands; i++) {
0435:                                if (nBits[i] != comparedBit) {
0436:                                    isNBit = false;
0437:                                    break;
0438:                                }
0439:                            }
0440:
0441:                            // Handle TYPE_BYTE
0442:                            if (comparedBit == 8) {
0443:                                if (isNBit && offs[0] == numBands - 1
0444:                                        && offs[1] == numBands - 2
0445:                                        && offs[2] == numBands - 3) {
0446:                                    if (numBands == 3) {
0447:                                        imageType = BufferedImage.TYPE_3BYTE_BGR;
0448:                                    } else if (offs[3] == 0) {
0449:                                        imageType = (isAlphaPre ? BufferedImage.TYPE_4BYTE_ABGR_PRE
0450:                                                : BufferedImage.TYPE_4BYTE_ABGR);
0451:                                    }
0452:                                }
0453:                            }
0454:                            //Handle TYPE_INT
0455:                            else {
0456:                                if (isNBit) {
0457:                                    if (numBands == 3) {
0458:                                        if (offs[0] == numBands - 1
0459:                                                && offs[1] == numBands - 2
0460:                                                && offs[2] == numBands - 3) {
0461:                                            imageType = BufferedImage.TYPE_INT_BGR;
0462:                                        } else if (offs[0] == 0 && offs[1] == 1
0463:                                                && offs[2] == 2) {
0464:                                            imageType = BufferedImage.TYPE_INT_RGB;
0465:                                        }
0466:                                    } else if (offs[0] == 3 && offs[1] == 0
0467:                                            && offs[2] == 1 && offs[3] == 2) {
0468:                                        imageType = (isAlphaPre ? BufferedImage.TYPE_INT_ARGB_PRE
0469:                                                : BufferedImage.TYPE_INT_ARGB);
0470:                                    }
0471:                                }
0472:                            }
0473:                        }
0474:                    }
0475:                }
0476:
0477:                return imageType;
0478:            }
0479:
0480:            // Assume ri's imageType is BufferedImage.TYPE_CUSTOM
0481:            boolean is3ByteRGB(RenderedImage ri) {
0482:                boolean value = false;
0483:                int i;
0484:                ColorModel cm = ri.getColorModel();
0485:                ColorSpace cs = cm.getColorSpace();
0486:                SampleModel sm = ri.getSampleModel();
0487:                boolean isAlphaPre = cm.isAlphaPremultiplied();
0488:                int csType = cs.getType();
0489:                if (csType == ColorSpace.TYPE_RGB) {
0490:                    int numBands = sm.getNumBands();
0491:                    if ((numBands == 3)
0492:                            && (sm.getDataType() == DataBuffer.TYPE_BYTE)) {
0493:                        if (cm instanceof  ComponentColorModel
0494:                                && sm instanceof  PixelInterleavedSampleModel) {
0495:                            PixelInterleavedSampleModel csm = (PixelInterleavedSampleModel) sm;
0496:                            int[] offs = csm.getBandOffsets();
0497:                            ComponentColorModel ccm = (ComponentColorModel) cm;
0498:                            int[] nBits = ccm.getComponentSize();
0499:                            boolean is8Bit = true;
0500:                            for (i = 0; i < numBands; i++) {
0501:                                if (nBits[i] != 8) {
0502:                                    is8Bit = false;
0503:                                    break;
0504:                                }
0505:                            }
0506:                            if (is8Bit && offs[0] == 0 && offs[1] == 1
0507:                                    && offs[2] == 2) {
0508:                                value = true;
0509:                            }
0510:                        }
0511:                    }
0512:                }
0513:                return value;
0514:            }
0515:
0516:            // Assume ri's imageType is BufferedImage.TYPE_CUSTOM
0517:            boolean is4ByteRGBA(RenderedImage ri) {
0518:                boolean value = false;
0519:                int i;
0520:                ColorModel cm = ri.getColorModel();
0521:                ColorSpace cs = cm.getColorSpace();
0522:                SampleModel sm = ri.getSampleModel();
0523:                boolean isAlphaPre = cm.isAlphaPremultiplied();
0524:                int csType = cs.getType();
0525:                if (csType == ColorSpace.TYPE_RGB) {
0526:                    int numBands = sm.getNumBands();
0527:                    if ((numBands == 4)
0528:                            && (sm.getDataType() == DataBuffer.TYPE_BYTE)) {
0529:                        if (cm instanceof  ComponentColorModel
0530:                                && sm instanceof  PixelInterleavedSampleModel) {
0531:                            PixelInterleavedSampleModel csm = (PixelInterleavedSampleModel) sm;
0532:                            int[] offs = csm.getBandOffsets();
0533:                            ComponentColorModel ccm = (ComponentColorModel) cm;
0534:                            int[] nBits = ccm.getComponentSize();
0535:                            boolean is8Bit = true;
0536:                            for (i = 0; i < numBands; i++) {
0537:                                if (nBits[i] != 8) {
0538:                                    is8Bit = false;
0539:                                    break;
0540:                                }
0541:                            }
0542:                            if (is8Bit && offs[0] == 0 && offs[1] == 1
0543:                                    && offs[2] == 2 && offs[3] == 3
0544:                                    && !isAlphaPre) {
0545:                                value = true;
0546:                            }
0547:                        }
0548:                    }
0549:                }
0550:                return value;
0551:            }
0552:
0553:            // Note: This method for RenderedImage, can't be used by NioImageBuffer.
0554:            /* Check if sub-image type matches image type */
0555:            boolean isSubImageTypeEqual(RenderedImage ri) {
0556:                int subImageType = evaluateImageType(ri);
0557:
0558:                // This test is likely too loose, but the specification isn't clear either.
0559:                // Assuming TYPE_CUSTOM of sub-image == the TYPE_CUSTOM of existing image.
0560:                if (imageType == subImageType) {
0561:                    return true;
0562:                } else {
0563:                    return false;
0564:                }
0565:
0566:            }
0567:
0568:            // This method only support caller of offScreenBuffer and readRaster.
0569:            void createBlankImageData() {
0570:
0571:                assert (imageData == null);
0572:
0573:                switch (numberOfComponents) {
0574:                case 4:
0575:                    imageType = BufferedImage.TYPE_INT_ARGB;
0576:                    imageFormatType = ImageFormatType.TYPE_INT_ARGB;
0577:                    unitsPerPixel = 1;
0578:                    break;
0579:
0580:                case 3:
0581:                    imageType = BufferedImage.TYPE_INT_RGB;
0582:                    imageFormatType = ImageFormatType.TYPE_INT_RGB;
0583:                    unitsPerPixel = 1;
0584:                    break;
0585:                default:
0586:                    // Only valid for 3 and 4 channel case. ( Read back from framebuffer )
0587:                    assert false;
0588:                }
0589:
0590:                imageTypeIsSupported = true;
0591:                imageData = createRenderedImageDataObject(null);
0592:
0593:            }
0594:
0595:            // This method will set imageType, imageFormatType, and unitsPerPixel
0596:            // as it evaluates NioImageBuffer is supported. It will also reset
0597:            // abgrSupported.
0598:            boolean isImageTypeSupported(NioImageBuffer nioImgBuf) {
0599:
0600:                boolean isSupported = true;
0601:                NioImageBuffer.ImageType nioImageType = nioImgBuf
0602:                        .getImageType();
0603:
0604:                switch (numberOfComponents) {
0605:                case 4:
0606:                    switch (nioImageType) {
0607:                    case TYPE_4BYTE_ABGR:
0608:                        // TODO : This approach will lead to a very slow path
0609:                        // for unsupported case.
0610:                        if (abgrSupported) {
0611:                            imageFormatType = ImageFormatType.TYPE_BYTE_ABGR;
0612:                        } else {
0613:                            // Unsupported format on HW, switch to slow copy.
0614:                            imageFormatType = ImageFormatType.TYPE_BYTE_RGBA;
0615:                            isSupported = false;
0616:                        }
0617:                        unitsPerPixel = 4;
0618:                        break;
0619:                    case TYPE_4BYTE_RGBA:
0620:                        imageFormatType = ImageFormatType.TYPE_BYTE_RGBA;
0621:                        unitsPerPixel = 4;
0622:                        break;
0623:                    case TYPE_INT_ARGB:
0624:                        imageFormatType = ImageFormatType.TYPE_INT_ARGB;
0625:                        unitsPerPixel = 1;
0626:                        break;
0627:                    default:
0628:                        throw new IllegalArgumentException(J3dI18N
0629:                                .getString("ImageComponent5"));
0630:
0631:                    }
0632:                    break;
0633:                case 3:
0634:                    switch (nioImageType) {
0635:                    case TYPE_3BYTE_BGR:
0636:                        imageFormatType = ImageFormatType.TYPE_BYTE_BGR;
0637:                        unitsPerPixel = 3;
0638:                        break;
0639:                    case TYPE_3BYTE_RGB:
0640:                        imageFormatType = ImageFormatType.TYPE_BYTE_RGB;
0641:                        unitsPerPixel = 3;
0642:                        break;
0643:                    case TYPE_INT_BGR:
0644:                        imageFormatType = ImageFormatType.TYPE_INT_BGR;
0645:                        unitsPerPixel = 1;
0646:                        break;
0647:                    case TYPE_INT_RGB:
0648:                        imageFormatType = ImageFormatType.TYPE_INT_RGB;
0649:                        unitsPerPixel = 1;
0650:                        break;
0651:                    default:
0652:                        throw new IllegalArgumentException(J3dI18N
0653:                                .getString("ImageComponent5"));
0654:                    }
0655:                    break;
0656:
0657:                case 2:
0658:                    throw new IllegalArgumentException(J3dI18N
0659:                            .getString("ImageComponent5"));
0660:                case 1:
0661:                    if (nioImageType == NioImageBuffer.ImageType.TYPE_BYTE_GRAY) {
0662:                        imageFormatType = ImageFormatType.TYPE_BYTE_GRAY;
0663:                        unitsPerPixel = 1;
0664:                    } else {
0665:                        throw new IllegalArgumentException(J3dI18N
0666:                                .getString("ImageComponent5"));
0667:                    }
0668:                    break;
0669:
0670:                default:
0671:                    throw new AssertionError();
0672:                }
0673:
0674:                return isSupported;
0675:            }
0676:
0677:            // This method will set imageType, imageFormatType, and unitsPerPixel
0678:            // as it evaluates RenderedImage is supported. It will also reset
0679:            // abgrSupported.
0680:            boolean isImageTypeSupported(RenderedImage ri) {
0681:
0682:                boolean isSupported = true;
0683:                imageType = evaluateImageType(ri);
0684:
0685:                switch (numberOfComponents) {
0686:                case 4:
0687:                    if (imageType == BufferedImage.TYPE_4BYTE_ABGR) {
0688:
0689:                        // TODO : This approach will lead to a very slow path
0690:                        // for unsupported case.
0691:                        if (abgrSupported) {
0692:                            imageFormatType = ImageFormatType.TYPE_BYTE_ABGR;
0693:                        } else {
0694:                            // Unsupported format on HW, switch to slow copy.
0695:                            imageFormatType = ImageFormatType.TYPE_BYTE_RGBA;
0696:                            isSupported = false;
0697:                        }
0698:                        unitsPerPixel = 4;
0699:                    } else if (imageType == BufferedImage.TYPE_INT_ARGB) {
0700:                        imageFormatType = ImageFormatType.TYPE_INT_ARGB;
0701:                        unitsPerPixel = 1;
0702:                    } else if (is4ByteRGBA(ri)) {
0703:                        imageFormatType = ImageFormatType.TYPE_BYTE_RGBA;
0704:                        unitsPerPixel = 4;
0705:                    } else {
0706:                        // System.err.println("Image format is unsupported --- Case 4");
0707:                        // Convert unsupported format to TYPE_BYTE_RGBA.
0708:                        imageFormatType = ImageFormatType.TYPE_BYTE_RGBA;
0709:                        isSupported = false;
0710:                        unitsPerPixel = 4;
0711:                    }
0712:                    break;
0713:
0714:                case 3:
0715:                    if (imageType == BufferedImage.TYPE_3BYTE_BGR) {
0716:                        imageFormatType = ImageFormatType.TYPE_BYTE_BGR;
0717:                        unitsPerPixel = 3;
0718:                    } else if (imageType == BufferedImage.TYPE_INT_BGR) {
0719:                        imageFormatType = ImageFormatType.TYPE_INT_BGR;
0720:                        unitsPerPixel = 1;
0721:                    } else if (imageType == BufferedImage.TYPE_INT_RGB) {
0722:                        imageFormatType = ImageFormatType.TYPE_INT_RGB;
0723:                        unitsPerPixel = 1;
0724:                    } else if (is3ByteRGB(ri)) {
0725:                        imageFormatType = ImageFormatType.TYPE_BYTE_RGB;
0726:                        unitsPerPixel = 3;
0727:                    } else {
0728:                        // System.err.println("Image format is unsupported --- Case 3");
0729:                        // Convert unsupported format to TYPE_BYTE_RGB.
0730:                        imageFormatType = ImageFormatType.TYPE_BYTE_RGB;
0731:                        isSupported = false;
0732:                        unitsPerPixel = 3;
0733:                    }
0734:                    break;
0735:
0736:                case 2:
0737:                    // System.err.println("Image format is unsupported --- Case 2");
0738:                    // Convert unsupported format to TYPE_BYTE_LA.
0739:                    imageFormatType = ImageFormatType.TYPE_BYTE_LA;
0740:                    isSupported = false;
0741:                    unitsPerPixel = 2;
0742:                    break;
0743:
0744:                case 1:
0745:                    if (imageType == BufferedImage.TYPE_BYTE_GRAY) {
0746:                        imageFormatType = ImageFormatType.TYPE_BYTE_GRAY;
0747:                        unitsPerPixel = 1;
0748:                    } else {
0749:                        // System.err.println("Image format is unsupported --- Case 1");
0750:                        // Convert unsupported format to TYPE_BYTE_GRAY.
0751:                        imageFormatType = ImageFormatType.TYPE_BYTE_GRAY;
0752:                        isSupported = false;
0753:                        unitsPerPixel = 1;
0754:                    }
0755:                    break;
0756:
0757:                default:
0758:                    throw new AssertionError();
0759:                }
0760:
0761:                return isSupported;
0762:            }
0763:
0764:            /*
0765:             * This method assume that the following members have been initialized :
0766:             * width, height, depth, imageFormatType, and unitsPerPixel.
0767:             */
0768:            ImageData createNioImageBufferDataObject(
0769:                    NioImageBuffer nioImageBuffer) {
0770:
0771:                switch (imageFormatType) {
0772:                case TYPE_BYTE_GRAY:
0773:                case TYPE_BYTE_LA:
0774:                case TYPE_BYTE_RGB:
0775:                case TYPE_BYTE_BGR:
0776:                case TYPE_BYTE_RGBA:
0777:                case TYPE_BYTE_ABGR:
0778:                    if (nioImageBuffer != null) {
0779:                        return new ImageData(ImageDataType.TYPE_BYTE_BUFFER,
0780:                                width * height * depth * unitsPerPixel, width,
0781:                                height, nioImageBuffer);
0782:                    } else {
0783:                        // This is needed only if abgr is unsupported.
0784:                        return new ImageData(ImageDataType.TYPE_BYTE_BUFFER,
0785:                                width * height * depth * unitsPerPixel, width,
0786:                                height);
0787:                    }
0788:                case TYPE_INT_RGB:
0789:                case TYPE_INT_BGR:
0790:                case TYPE_INT_ARGB:
0791:                    return new ImageData(ImageDataType.TYPE_INT_BUFFER, width
0792:                            * height * depth * unitsPerPixel, width, height,
0793:                            nioImageBuffer);
0794:                default:
0795:                    throw new AssertionError();
0796:                }
0797:            }
0798:
0799:            /*
0800:             * This method assume that the following members have been initialized :
0801:             * depth, imageType, imageFormatType, and unitsPerPixel.
0802:             */
0803:            ImageData createRenderedImageDataObject(RenderedImage byRefImage,
0804:                    int dataWidth, int dataHeight) {
0805:                switch (imageFormatType) {
0806:                case TYPE_BYTE_GRAY:
0807:                case TYPE_BYTE_LA:
0808:                case TYPE_BYTE_RGB:
0809:                case TYPE_BYTE_BGR:
0810:                case TYPE_BYTE_RGBA:
0811:                case TYPE_BYTE_ABGR:
0812:                    if (byRefImage != null) {
0813:                        return new ImageData(ImageDataType.TYPE_BYTE_ARRAY,
0814:                                dataWidth * dataHeight * depth * unitsPerPixel,
0815:                                dataWidth, dataHeight, byRefImage);
0816:                    } else {
0817:                        return new ImageData(ImageDataType.TYPE_BYTE_ARRAY,
0818:                                dataWidth * dataHeight * depth * unitsPerPixel,
0819:                                dataWidth, dataHeight);
0820:                    }
0821:                case TYPE_INT_RGB:
0822:                case TYPE_INT_BGR:
0823:                case TYPE_INT_ARGB:
0824:                    if (byRefImage != null) {
0825:                        return new ImageData(ImageDataType.TYPE_INT_ARRAY,
0826:                                dataWidth * dataHeight * depth * unitsPerPixel,
0827:                                dataWidth, dataHeight, byRefImage);
0828:                    } else {
0829:                        return new ImageData(ImageDataType.TYPE_INT_ARRAY,
0830:                                dataWidth * dataHeight * depth * unitsPerPixel,
0831:                                dataWidth, dataHeight);
0832:                    }
0833:                default:
0834:                    throw new AssertionError();
0835:                }
0836:            }
0837:
0838:            private void updateImageDataPowerOfTwo(int depthIndex) {
0839:                assert enforceNonPowerOfTwoSupport;
0840:                BufferedImage bufImage = imageData
0841:                        .createBufferedImage(depthIndex);
0842:                BufferedImage scaledImg = powerOfTwoATOp.filter(bufImage, null);
0843:                copySupportedImageToImageData(scaledImg, 0, imageDataPowerOfTwo);
0844:            }
0845:
0846:            /*
0847:             * This method assume that the following members have been initialized :
0848:             *  width, height, depth, imageType, imageFormatType, and bytesPerPixel.
0849:             */
0850:            ImageData createRenderedImageDataObject(RenderedImage byRefImage) {
0851:
0852:                return createRenderedImageDataObject(byRefImage, width, height);
0853:
0854:            }
0855:
0856:            /**
0857:             * Copy specified region of image data from RenderedImage to
0858:             * ImageComponent's imageData object
0859:             */
0860:            void copySupportedImageToImageData(RenderedImage ri, int srcX,
0861:                    int srcY, int dstX, int dstY, int depthIndex,
0862:                    int copyWidth, int copyHeight, ImageData data) {
0863:
0864:                assert (data != null);
0865:
0866:                ColorModel cm = ri.getColorModel();
0867:
0868:                int xoff = ri.getTileGridXOffset(); // tile origin x offset
0869:                int yoff = ri.getTileGridYOffset(); // tile origin y offset
0870:                int minTileX = ri.getMinTileX(); // min tile x index
0871:                int minTileY = ri.getMinTileY(); // min tile y index
0872:                tilew = ri.getTileWidth(); // tile width in pixels
0873:                tileh = ri.getTileHeight(); // tile height in pixels
0874:
0875:                // determine the first tile of the image
0876:                float mt;
0877:
0878:                mt = (float) (srcX - xoff) / (float) tilew;
0879:                if (mt < 0) {
0880:                    minTileX = (int) (mt - 1);
0881:                } else {
0882:                    minTileX = (int) mt;
0883:                }
0884:
0885:                mt = (float) (srcY - yoff) / (float) tileh;
0886:                if (mt < 0) {
0887:                    minTileY = (int) (mt - 1);
0888:                } else {
0889:                    minTileY = (int) mt;
0890:                }
0891:
0892:                // determine the pixel offset of the upper-left corner of the
0893:                // first tile
0894:                int startXTile = minTileX * tilew + xoff;
0895:                int startYTile = minTileY * tileh + yoff;
0896:
0897:                // image dimension in the first tile
0898:                int curw = (startXTile + tilew - srcX);
0899:                int curh = (startYTile + tileh - srcY);
0900:
0901:                // check if the to-be-copied region is less than the tile image
0902:                // if so, update the to-be-copied dimension of this tile
0903:                if (curw > copyWidth) {
0904:                    curw = copyWidth;
0905:                }
0906:
0907:                if (curh > copyHeight) {
0908:                    curh = copyHeight;
0909:                }
0910:
0911:                // save the to-be-copied width of the left most tile
0912:                int startw = curw;
0913:
0914:                // temporary variable for dimension of the to-be-copied region
0915:                int tmpw = copyWidth;
0916:                int tmph = copyHeight;
0917:
0918:                // offset of the first pixel of the tile to be copied; offset is
0919:                // relative to the upper left corner of the title
0920:                int x = srcX - startXTile;
0921:                int y = srcY - startYTile;
0922:
0923:                // determine the number of tiles in each direction that the
0924:                // image spans
0925:                numXTiles = (copyWidth + x) / tilew;
0926:                numYTiles = (copyHeight + y) / tileh;
0927:
0928:                if (((float) (copyWidth + x) % (float) tilew) > 0) {
0929:                    numXTiles += 1;
0930:                }
0931:
0932:                if (((float) (copyHeight + y) % (float) tileh) > 0) {
0933:                    numYTiles += 1;
0934:                }
0935:
0936:                int offset;
0937:                int w, h, i, j, m, n;
0938:                int dstBegin;
0939:                Object pixel = null;
0940:                java.awt.image.Raster ras;
0941:                int lineUnits; // nbytes per line in dst image buffer
0942:                int sign; // -1 for going down
0943:                int dstLineUnits; // sign * lineUnits
0944:                int tileStart; // destination buffer offset
0945:                // at the next left most tile
0946:
0947:                byte[] dstByteBuffer = null;
0948:                int[] dstIntBuffer = null;
0949:
0950:                switch (data.getType()) {
0951:                case TYPE_BYTE_ARRAY:
0952:                    dstByteBuffer = data.getAsByteArray();
0953:                    break;
0954:                case TYPE_INT_ARRAY:
0955:                    dstIntBuffer = data.getAsIntArray();
0956:                    break;
0957:                default:
0958:                    assert false;
0959:                }
0960:
0961:                int dataWidth = data.dataWidth;
0962:                int dataHeight = data.dataHeight;
0963:
0964:                lineUnits = dataWidth * unitsPerPixel;
0965:                if (yUp) {
0966:                    // destination buffer offset
0967:                    tileStart = (depthIndex * dataWidth * dataHeight + dstY
0968:                            * dataWidth + dstX)
0969:                            * unitsPerPixel;
0970:                    sign = 1;
0971:                    dstLineUnits = lineUnits;
0972:                } else {
0973:                    // destination buffer offset
0974:                    tileStart = (depthIndex * dataWidth * dataHeight
0975:                            + (dataHeight - dstY - 1) * dataWidth + dstX)
0976:                            * unitsPerPixel;
0977:                    sign = -1;
0978:                    dstLineUnits = -lineUnits;
0979:                }
0980:
0981:                /*
0982:                 System.err.println("tileStart= " + tileStart + " dstLineUnits= " + dstLineUnits);
0983:                 System.err.println("startw= " + startw);
0984:                 */
0985:
0986:                // allocate memory for a pixel
0987:                ras = ri.getTile(minTileX, minTileY);
0988:                pixel = getDataElementBuffer(ras);
0989:
0990:                int srcOffset, dstOffset;
0991:                int tileLineUnits = tilew * unitsPerPixel;
0992:                int copyUnits;
0993:
0994:                for (n = minTileY; n < minTileY + numYTiles; n++) {
0995:
0996:                    dstBegin = tileStart; // destination buffer offset
0997:                    tmpw = copyWidth; // reset the width to be copied
0998:                    curw = startw; // reset the width to be copied of
0999:                    // the left most tile
1000:                    x = srcX - startXTile; // reset the starting x offset of
1001:                    // the left most tile
1002:
1003:                    for (m = minTileX; m < minTileX + numXTiles; m++) {
1004:
1005:                        // retrieve the raster for the next tile
1006:                        ras = ri.getTile(m, n);
1007:
1008:                        srcOffset = (y * tilew + x) * unitsPerPixel;
1009:                        dstOffset = dstBegin;
1010:
1011:                        copyUnits = curw * unitsPerPixel;
1012:
1013:                        //System.err.println("curh = "+curh+" curw = "+curw);
1014:                        //System.err.println("x = "+x+" y = "+y);
1015:
1016:                        switch (data.getType()) {
1017:                        case TYPE_BYTE_ARRAY:
1018:                            byte[] srcByteBuffer = ((DataBufferByte) ras
1019:                                    .getDataBuffer()).getData();
1020:                            for (h = 0; h < curh; h++) {
1021:                                System.arraycopy(srcByteBuffer, srcOffset,
1022:                                        dstByteBuffer, dstOffset, copyUnits);
1023:                                srcOffset += tileLineUnits;
1024:                                dstOffset += dstLineUnits;
1025:                            }
1026:                            break;
1027:                        case TYPE_INT_ARRAY:
1028:                            int[] srcIntBuffer = ((DataBufferInt) ras
1029:                                    .getDataBuffer()).getData();
1030:                            for (h = 0; h < curh; h++) {
1031:                                System.arraycopy(srcIntBuffer, srcOffset,
1032:                                        dstIntBuffer, dstOffset, copyUnits);
1033:                                srcOffset += tileLineUnits;
1034:                                dstOffset += dstLineUnits;
1035:                            }
1036:                            break;
1037:                        default:
1038:                            assert false;
1039:                        }
1040:
1041:                        // advance the destination buffer offset
1042:                        dstBegin += curw * unitsPerPixel;
1043:
1044:                        // move to the next tile in x direction
1045:                        x = 0;
1046:
1047:                        // determine the width of copy region of the next tile
1048:
1049:                        tmpw -= curw;
1050:                        if (tmpw < tilew) {
1051:                            curw = tmpw;
1052:                        } else {
1053:                            curw = tilew;
1054:                        }
1055:                    }
1056:
1057:                    // we are done copying an array of tiles in the x direction
1058:                    // advance the tileStart offset
1059:                    tileStart += dataWidth * unitsPerPixel * curh * sign;
1060:
1061:                    // move to the next set of tiles in y direction
1062:                    y = 0;
1063:
1064:                    // determine the height of copy region for the next set
1065:                    // of tiles
1066:                    tmph -= curh;
1067:                    if (tmph < tileh) {
1068:                        curh = tmph;
1069:                    } else {
1070:                        curh = tileh;
1071:                    }
1072:                }
1073:
1074:                if ((imageData == data) && (imageDataPowerOfTwo != null)) {
1075:                    updateImageDataPowerOfTwo(depthIndex);
1076:                }
1077:            }
1078:
1079:            // Quick line by line copy
1080:            void copyImageLineByLine(BufferedImage bi, int srcX, int srcY,
1081:                    int dstX, int dstY, int depthIndex, int copyWidth,
1082:                    int copyHeight, ImageData data) {
1083:
1084:                assert (data != null);
1085:
1086:                int h;
1087:                int rowBegin, // src begin row index
1088:                srcBegin, // src begin offset
1089:                dstBegin; // dst begin offset
1090:
1091:                int dataWidth = data.dataWidth;
1092:                int dataHeight = data.dataHeight;
1093:                int dstUnitsPerRow = dataWidth * unitsPerPixel; // bytes per row in dst image
1094:                rowBegin = srcY;
1095:
1096:                if (yUp) {
1097:                    dstBegin = (depthIndex * dataWidth * dataHeight + dstY
1098:                            * dataWidth + dstX)
1099:                            * unitsPerPixel;
1100:                } else {
1101:                    dstBegin = (depthIndex * dataWidth * dataHeight
1102:                            + (dataHeight - dstY - 1) * dataWidth + dstX)
1103:                            * unitsPerPixel;
1104:                    dstUnitsPerRow = -1 * dstUnitsPerRow;
1105:                }
1106:
1107:                int copyUnits = copyWidth * unitsPerPixel;
1108:                int srcWidth = bi.getWidth();
1109:                int srcUnitsPerRow = srcWidth * unitsPerPixel;
1110:                srcBegin = (rowBegin * srcWidth + srcX) * unitsPerPixel;
1111:
1112:                switch (data.getType()) {
1113:                case TYPE_BYTE_ARRAY:
1114:                    byte[] srcByteBuffer = ((DataBufferByte) bi.getRaster()
1115:                            .getDataBuffer()).getData();
1116:                    byte[] dstByteBuffer = data.getAsByteArray();
1117:                    for (h = 0; h < copyHeight; h++) {
1118:                        System.arraycopy(srcByteBuffer, srcBegin,
1119:                                dstByteBuffer, dstBegin, copyUnits);
1120:                        dstBegin += dstUnitsPerRow;
1121:                        srcBegin += srcUnitsPerRow;
1122:                    }
1123:                    break;
1124:
1125:                case TYPE_INT_ARRAY:
1126:                    int[] srcIntBuffer = ((DataBufferInt) bi.getRaster()
1127:                            .getDataBuffer()).getData();
1128:                    int[] dstIntBuffer = data.getAsIntArray();
1129:                    for (h = 0; h < copyHeight; h++) {
1130:                        System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer,
1131:                                dstBegin, copyUnits);
1132:                        dstBegin += dstUnitsPerRow;
1133:                        srcBegin += srcUnitsPerRow;
1134:                    }
1135:                    break;
1136:                default:
1137:                    assert false;
1138:                }
1139:
1140:                if ((imageData == data) && (imageDataPowerOfTwo != null)) {
1141:                    updateImageDataPowerOfTwo(depthIndex);
1142:                }
1143:            }
1144:
1145:            // Quick block copy for yUp image
1146:            void copyImageByBlock(BufferedImage bi, int depthIndex,
1147:                    ImageData data) {
1148:
1149:                assert ((data != null) && yUp);
1150:
1151:                int dataWidth = data.dataWidth;
1152:                int dataHeight = data.dataHeight;
1153:
1154:                int dstBegin; // dst begin offset
1155:                dstBegin = depthIndex * dataWidth * dataHeight * unitsPerPixel;
1156:
1157:                switch (imageData.getType()) {
1158:                case TYPE_BYTE_ARRAY:
1159:                    byte[] srcByteBuffer = ((DataBufferByte) bi.getRaster()
1160:                            .getDataBuffer()).getData();
1161:                    byte[] dstByteBuffer = data.getAsByteArray();
1162:                    System.arraycopy(srcByteBuffer, 0, dstByteBuffer, dstBegin,
1163:                            (dataWidth * dataHeight * unitsPerPixel));
1164:                    break;
1165:                case TYPE_INT_ARRAY:
1166:                    int[] srcIntBuffer = ((DataBufferInt) bi.getRaster()
1167:                            .getDataBuffer()).getData();
1168:                    int[] dstIntBuffer = data.getAsIntArray();
1169:                    System.arraycopy(srcIntBuffer, 0, dstIntBuffer, dstBegin,
1170:                            (dataWidth * dataHeight * unitsPerPixel));
1171:                    break;
1172:                default:
1173:                    assert false;
1174:                }
1175:
1176:                if ((imageData == data) && (imageDataPowerOfTwo != null)) {
1177:                    updateImageDataPowerOfTwo(depthIndex);
1178:                }
1179:
1180:            }
1181:
1182:            /**
1183:             * copy complete region of a RenderedImage to ImageComponent's imageData object.
1184:             */
1185:            void copySupportedImageToImageData(RenderedImage ri,
1186:                    int depthIndex, ImageData data) {
1187:
1188:                if (ri instanceof  BufferedImage) {
1189:                    if (yUp) {
1190:                        /*  Use quick block copy when  ( format is OK, Yup is true, and byRef is false). */
1191:                        // System.err.println("ImageComponentRetained.copySupportedImageToImageData() : (imageTypeSupported && !byReference && yUp) --- (2 BI)");
1192:                        copyImageByBlock((BufferedImage) ri, depthIndex, data);
1193:                    } else {
1194:                        /*  Use quick inverse line by line copy when (format is OK and Yup is false). */
1195:                        // System.err.println("ImageComponentRetained.copySupportedImageToImageData() : (imageTypeSupported && !yUp) --- (3 BI)");
1196:                        copyImageLineByLine((BufferedImage) ri, 0, 0, 0, 0,
1197:                                depthIndex, data.dataWidth, data.dataHeight,
1198:                                data);
1199:                    }
1200:                } else {
1201:                    // System.err.println("ImageComponentRetained.copySupportedImageToImageData() : (imageTypeSupported && !byReference ) --- (2 RI)");
1202:                    copySupportedImageToImageData(ri, ri.getMinX(), ri
1203:                            .getMinY(), 0, 0, depthIndex, data.dataWidth,
1204:                            data.dataHeight, data);
1205:
1206:                    /*
1207:                     * An alternative approach.
1208:                     *
1209:                    // Create a buffered image from renderImage
1210:                    ColorModel cm = ri.getColorModel();
1211:                    WritableRaster wRaster = ri.copyData(null);
1212:                    BufferedImage bi = new BufferedImage(cm,
1213:                                                        wRaster,
1214:                                                        cm.isAlphaPremultiplied()
1215:                                                        ,null);
1216:                     
1217:                    copySupportedImageToImageData((BufferedImage)ri, 0, 0, 0, 0, depthIndex, data.dataWidth, data.dataHeight, data);
1218:                     
1219:                     *
1220:                     *
1221:                     */
1222:                }
1223:            }
1224:
1225:            /*
1226:             * copy the complete unsupported NioImageBuffer into a supported BYTE_BUFFER format
1227:             */
1228:            void copyUnsupportedNioImageToImageData(NioImageBuffer nioImage,
1229:                    int srcX, int srcY, int dstX, int dstY, int copyWidth,
1230:                    int copyHeight, ImageData iData) {
1231:
1232:                if (MasterControl.isDevLoggable(Level.INFO)) {
1233:                    MasterControl
1234:                            .getDevLogger()
1235:                            .info(
1236:                                    "ImageComponent - Copying Unsupported NioImage, use a different image type");
1237:                }
1238:
1239:                assert (iData.getType() == ImageDataType.TYPE_BYTE_BUFFER);
1240:                assert (getImageFormatType() == ImageFormatType.TYPE_BYTE_RGBA);
1241:
1242:                int length = copyWidth * copyHeight;
1243:                ByteBuffer srcBuffer = (ByteBuffer) nioImage.getDataBuffer();
1244:                srcBuffer.rewind();
1245:                ByteBuffer dstBuffer = iData.getAsByteBuffer();
1246:                dstBuffer.rewind();
1247:
1248:                // Do copy and swap.
1249:                for (int i = 0; i < length; i += 4) {
1250:                    dstBuffer.put(i, srcBuffer.get(i + 3));
1251:                    dstBuffer.put(i + 1, srcBuffer.get(i + 2));
1252:                    dstBuffer.put(i + 2, srcBuffer.get(i + 1));
1253:                    dstBuffer.put(i + 3, srcBuffer.get(i));
1254:                }
1255:            }
1256:
1257:            /*
1258:             * copy the complete unsupported image into a supported BYTE_ARRAY format
1259:             */
1260:            void copyUnsupportedImageToImageData(RenderedImage ri,
1261:                    int depthIndex, ImageData data) {
1262:
1263:                assert (data.getType() == ImageDataType.TYPE_BYTE_ARRAY);
1264:
1265:                if (MasterControl.isDevLoggable(Level.INFO)) {
1266:                    MasterControl
1267:                            .getDevLogger()
1268:                            .info(
1269:                                    "ImageComponent - Copying Unsupported Image, use a different image type");
1270:                }
1271:
1272:                if (ri instanceof  BufferedImage) {
1273:                    copyUnsupportedImageToImageData((BufferedImage) ri, 0, 0,
1274:                            0, 0, depthIndex, data.dataWidth, data.dataHeight,
1275:                            data);
1276:                } else {
1277:                    copyUnsupportedImageToImageData(ri, ri.getMinX(), ri
1278:                            .getMinY(), 0, 0, depthIndex, data.dataWidth,
1279:                            data.dataHeight, data);
1280:                }
1281:            }
1282:
1283:            void copyUnsupportedImageToImageData(BufferedImage bi, int srcX,
1284:                    int srcY, int dstX, int dstY, int depthIndex,
1285:                    int copyWidth, int copyHeight, ImageData data) {
1286:
1287:                int w, h, i, j;
1288:                int rowBegin, // src begin row index
1289:                srcBegin, // src begin offset
1290:                dstBegin, // dst begin offset
1291:                rowInc, // row increment
1292:                // -1 --- ydown
1293:                //  1 --- yup
1294:                row;
1295:
1296:                rowBegin = srcY;
1297:                rowInc = 1;
1298:
1299:                assert (data != null);
1300:
1301:                int dataWidth = data.dataWidth;
1302:                int dataHeight = data.dataHeight;
1303:                int dstBytesPerRow = dataWidth * unitsPerPixel; // bytes per row in dst image
1304:
1305:                if (yUp) {
1306:                    dstBegin = (depthIndex * dataWidth * dataHeight + dstY
1307:                            * dataWidth + dstX)
1308:                            * unitsPerPixel;
1309:                } else {
1310:                    dstBegin = (depthIndex * dataWidth * dataHeight
1311:                            + (dataHeight - dstY - 1) * dataWidth + dstX)
1312:                            * unitsPerPixel;
1313:                    dstBytesPerRow = -1 * dstBytesPerRow;
1314:                }
1315:
1316:                WritableRaster ras = bi.getRaster();
1317:                ColorModel cm = bi.getColorModel();
1318:                Object pixel = getDataElementBuffer(ras);
1319:
1320:                byte[] dstBuffer = data.getAsByteArray();
1321:
1322:                switch (numberOfComponents) {
1323:                case 4: {
1324:                    for (row = rowBegin, h = 0; h < copyHeight; h++, row += rowInc) {
1325:                        j = dstBegin;
1326:                        for (w = srcX; w < (copyWidth + srcX); w++) {
1327:                            ras.getDataElements(w, row, pixel);
1328:                            dstBuffer[j++] = (byte) cm.getRed(pixel);
1329:                            dstBuffer[j++] = (byte) cm.getGreen(pixel);
1330:                            dstBuffer[j++] = (byte) cm.getBlue(pixel);
1331:                            dstBuffer[j++] = (byte) cm.getAlpha(pixel);
1332:                        }
1333:                        dstBegin += dstBytesPerRow;
1334:                    }
1335:                }
1336:                    break;
1337:
1338:                case 3: {
1339:                    for (row = rowBegin, h = 0; h < copyHeight; h++, row += rowInc) {
1340:                        j = dstBegin;
1341:                        for (w = srcX; w < (copyWidth + srcX); w++) {
1342:                            ras.getDataElements(w, row, pixel);
1343:                            dstBuffer[j++] = (byte) cm.getRed(pixel);
1344:                            dstBuffer[j++] = (byte) cm.getGreen(pixel);
1345:                            dstBuffer[j++] = (byte) cm.getBlue(pixel);
1346:                        }
1347:                        dstBegin += dstBytesPerRow;
1348:                    }
1349:                }
1350:                    break;
1351:
1352:                case 2: {
1353:                    for (row = rowBegin, h = 0; h < copyHeight; h++, row += rowInc) {
1354:                        j = dstBegin;
1355:                        for (w = srcX; w < (copyWidth + srcX); w++) {
1356:                            ras.getDataElements(w, row, pixel);
1357:                            dstBuffer[j++] = (byte) cm.getRed(pixel);
1358:                            dstBuffer[j++] = (byte) cm.getAlpha(pixel);
1359:                        }
1360:                        dstBegin += dstBytesPerRow;
1361:                    }
1362:                }
1363:                    break;
1364:
1365:                case 1: {
1366:                    for (row = rowBegin, h = 0; h < copyHeight; h++, row += rowInc) {
1367:                        j = dstBegin;
1368:                        for (w = srcX; w < (copyWidth + srcX); w++) {
1369:                            ras.getDataElements(w, row, pixel);
1370:                            dstBuffer[j++] = (byte) cm.getRed(pixel);
1371:                        }
1372:                        dstBegin += dstBytesPerRow;
1373:                    }
1374:                }
1375:                    break;
1376:                default:
1377:                    assert false;
1378:                }
1379:
1380:                if ((imageData == data) && (imageDataPowerOfTwo != null)) {
1381:                    updateImageDataPowerOfTwo(depthIndex);
1382:                }
1383:            }
1384:
1385:            void copyUnsupportedImageToImageData(RenderedImage ri, int srcX,
1386:                    int srcY, int dstX, int dstY, int depthIndex,
1387:                    int copyWidth, int copyHeight, ImageData data) {
1388:
1389:                int w, h, i, j, m, n;
1390:                int dstBegin;
1391:                Object pixel = null;
1392:                java.awt.image.Raster ras;
1393:                // dst image buffer
1394:                int sign; // -1 for going down
1395:                int dstLineBytes; // sign * lineBytes
1396:                int tileStart; // destination buffer offset
1397:                // at the next left most tile
1398:
1399:                int offset;
1400:
1401:                ColorModel cm = ri.getColorModel();
1402:
1403:                int xoff = ri.getTileGridXOffset(); // tile origin x offset
1404:                int yoff = ri.getTileGridYOffset(); // tile origin y offset
1405:                int minTileX = ri.getMinTileX(); // min tile x index
1406:                int minTileY = ri.getMinTileY(); // min tile y index
1407:                tilew = ri.getTileWidth(); // tile width in pixels
1408:                tileh = ri.getTileHeight(); // tile height in pixels
1409:
1410:                // determine the first tile of the image
1411:
1412:                float mt;
1413:
1414:                mt = (float) (srcX - xoff) / (float) tilew;
1415:                if (mt < 0) {
1416:                    minTileX = (int) (mt - 1);
1417:                } else {
1418:                    minTileX = (int) mt;
1419:                }
1420:
1421:                mt = (float) (srcY - yoff) / (float) tileh;
1422:                if (mt < 0) {
1423:                    minTileY = (int) (mt - 1);
1424:                } else {
1425:                    minTileY = (int) mt;
1426:                }
1427:
1428:                // determine the pixel offset of the upper-left corner of the
1429:                // first tile
1430:                int startXTile = minTileX * tilew + xoff;
1431:                int startYTile = minTileY * tileh + yoff;
1432:
1433:                // image dimension in the first tile
1434:                int curw = (startXTile + tilew - srcX);
1435:                int curh = (startYTile + tileh - srcY);
1436:
1437:                // check if the to-be-copied region is less than the tile image
1438:                // if so, update the to-be-copied dimension of this tile
1439:                if (curw > copyWidth) {
1440:                    curw = copyWidth;
1441:                }
1442:
1443:                if (curh > copyHeight) {
1444:                    curh = copyHeight;
1445:                }
1446:
1447:                // save the to-be-copied width of the left most tile
1448:                int startw = curw;
1449:
1450:                // temporary variable for dimension of the to-be-copied region
1451:                int tmpw = copyWidth;
1452:                int tmph = copyHeight;
1453:
1454:                // offset of the first pixel of the tile to be copied; offset is
1455:                // relative to the upper left corner of the title
1456:                int x = srcX - startXTile;
1457:                int y = srcY - startYTile;
1458:
1459:                // determine the number of tiles in each direction that the
1460:                // image spans
1461:
1462:                numXTiles = (copyWidth + x) / tilew;
1463:                numYTiles = (copyHeight + y) / tileh;
1464:
1465:                if (((float) (copyWidth + x) % (float) tilew) > 0) {
1466:                    numXTiles += 1;
1467:                }
1468:
1469:                if (((float) (copyHeight + y) % (float) tileh) > 0) {
1470:                    numYTiles += 1;
1471:                }
1472:
1473:                assert (data != null);
1474:                int dataWidth = data.dataWidth;
1475:                int dataHeight = data.dataHeight;
1476:                int lineBytes = dataWidth * unitsPerPixel; // nbytes per line in
1477:
1478:                if (yUp) {
1479:                    // destination buffer offset
1480:                    tileStart = (depthIndex * dataWidth * dataHeight + dstY
1481:                            * dataWidth + dstX)
1482:                            * unitsPerPixel;
1483:                    sign = 1;
1484:                    dstLineBytes = lineBytes;
1485:                } else {
1486:                    // destination buffer offset
1487:                    tileStart = (depthIndex * dataWidth * dataHeight
1488:                            + (dataHeight - dstY - 1) * dataWidth + dstX)
1489:                            * unitsPerPixel;
1490:                    sign = -1;
1491:                    dstLineBytes = -lineBytes;
1492:                }
1493:
1494:                /*
1495:                 System.err.println("tileStart= " + tileStart + " dstLineBytes= " + dstLineBytes);
1496:                 System.err.println("startw= " + startw);
1497:                 */
1498:
1499:                // allocate memory for a pixel
1500:                ras = ri.getTile(minTileX, minTileY);
1501:                pixel = getDataElementBuffer(ras);
1502:                byte[] dstBuffer = imageData.getAsByteArray();
1503:
1504:                switch (numberOfComponents) {
1505:                case 4: {
1506:                    //	    System.err.println("Case 1: byReference = "+byReference);
1507:                    for (n = minTileY; n < minTileY + numYTiles; n++) {
1508:
1509:                        dstBegin = tileStart; // destination buffer offset
1510:                        tmpw = copyWidth; // reset the width to be copied
1511:                        curw = startw; // reset the width to be copied of
1512:                        // the left most tile
1513:                        x = srcX - startXTile; // reset the starting x offset of
1514:                        // the left most tile
1515:
1516:                        for (m = minTileX; m < minTileX + numXTiles; m++) {
1517:
1518:                            // retrieve the raster for the next tile
1519:                            ras = ri.getTile(m, n);
1520:
1521:                            j = dstBegin;
1522:                            offset = 0;
1523:
1524:                            //System.err.println("curh = "+curh+" curw = "+curw);
1525:                            //System.err.println("x = "+x+" y = "+y);
1526:
1527:                            for (h = y; h < (y + curh); h++) {
1528:                                // System.err.println("j = "+j);
1529:                                for (w = x; w < (x + curw); w++) {
1530:                                    ras.getDataElements(w, h, pixel);
1531:                                    dstBuffer[j++] = (byte) cm.getRed(pixel);
1532:                                    dstBuffer[j++] = (byte) cm.getGreen(pixel);
1533:                                    dstBuffer[j++] = (byte) cm.getBlue(pixel);
1534:                                    dstBuffer[j++] = (byte) cm.getAlpha(pixel);
1535:                                }
1536:                                offset += dstLineBytes;
1537:                                j = dstBegin + offset;
1538:                            }
1539:
1540:                            // advance the destination buffer offset
1541:                            dstBegin += curw * unitsPerPixel;
1542:
1543:                            // move to the next tile in x direction
1544:                            x = 0;
1545:
1546:                            // determine the width of copy region of the next tile
1547:
1548:                            tmpw -= curw;
1549:                            if (tmpw < tilew) {
1550:                                curw = tmpw;
1551:                            } else {
1552:                                curw = tilew;
1553:                            }
1554:                        }
1555:
1556:                        // we are done copying an array of tiles in the x direction
1557:                        // advance the tileStart offset
1558:
1559:                        tileStart += dataWidth * unitsPerPixel * curh * sign;
1560:
1561:                        // move to the next set of tiles in y direction
1562:                        y = 0;
1563:
1564:                        // determine the height of copy region for the next set
1565:                        // of tiles
1566:                        tmph -= curh;
1567:                        if (tmph < tileh) {
1568:                            curh = tmph;
1569:                        } else {
1570:                            curh = tileh;
1571:                        }
1572:                    }
1573:                }
1574:                    break;
1575:                case 3: {
1576:                    for (n = minTileY; n < minTileY + numYTiles; n++) {
1577:
1578:                        dstBegin = tileStart; // destination buffer offset
1579:                        tmpw = copyWidth; // reset the width to be copied
1580:                        curw = startw; // reset the width to be copied of
1581:                        // the left most tile
1582:                        x = srcX - startXTile; // reset the starting x offset of
1583:                        // the left most tile
1584:
1585:                        for (m = minTileX; m < minTileX + numXTiles; m++) {
1586:
1587:                            // retrieve the raster for the next tile
1588:                            ras = ri.getTile(m, n);
1589:
1590:                            j = dstBegin;
1591:                            offset = 0;
1592:
1593:                            //System.err.println("curh = "+curh+" curw = "+curw);
1594:                            //System.err.println("x = "+x+" y = "+y);
1595:
1596:                            for (h = y; h < (y + curh); h++) {
1597:                                //			System.err.println("j = "+j);
1598:                                for (w = x; w < (x + curw); w++) {
1599:                                    ras.getDataElements(w, h, pixel);
1600:                                    dstBuffer[j++] = (byte) cm.getRed(pixel);
1601:                                    dstBuffer[j++] = (byte) cm.getGreen(pixel);
1602:                                    dstBuffer[j++] = (byte) cm.getBlue(pixel);
1603:                                }
1604:                                offset += dstLineBytes;
1605:                                j = dstBegin + offset;
1606:                            }
1607:
1608:                            // advance the destination buffer offset
1609:                            dstBegin += curw * unitsPerPixel;
1610:
1611:                            // move to the next tile in x direction
1612:                            x = 0;
1613:
1614:                            // determine the width of copy region of the next tile
1615:
1616:                            tmpw -= curw;
1617:                            if (tmpw < tilew) {
1618:                                curw = tmpw;
1619:                            } else {
1620:                                curw = tilew;
1621:                            }
1622:                        }
1623:
1624:                        // we are done copying an array of tiles in the x direction
1625:                        // advance the tileStart offset
1626:
1627:                        tileStart += dataWidth * unitsPerPixel * curh * sign;
1628:
1629:                        // move to the next set of tiles in y direction
1630:                        y = 0;
1631:
1632:                        // determine the height of copy region for the next set
1633:                        // of tiles
1634:                        tmph -= curh;
1635:                        if (tmph < tileh) {
1636:                            curh = tmph;
1637:                        } else {
1638:                            curh = tileh;
1639:                        }
1640:                    }
1641:                }
1642:                    break;
1643:                case 2: {
1644:                    for (n = minTileY; n < minTileY + numYTiles; n++) {
1645:
1646:                        dstBegin = tileStart; // destination buffer offset
1647:                        tmpw = copyWidth; // reset the width to be copied
1648:                        curw = startw; // reset the width to be copied of
1649:                        // the left most tile
1650:                        x = srcX - startXTile; // reset the starting x offset of
1651:                        // the left most tile
1652:
1653:                        for (m = minTileX; m < minTileX + numXTiles; m++) {
1654:
1655:                            // retrieve the raster for the next tile
1656:                            ras = ri.getTile(m, n);
1657:
1658:                            j = dstBegin;
1659:                            offset = 0;
1660:
1661:                            //System.err.println("curh = "+curh+" curw = "+curw);
1662:                            //System.err.println("x = "+x+" y = "+y);
1663:
1664:                            for (h = y; h < (y + curh); h++) {
1665:                                //			System.err.println("j = "+j);
1666:                                for (w = x; w < (x + curw); w++) {
1667:                                    ras.getDataElements(w, h, pixel);
1668:                                    dstBuffer[j++] = (byte) cm.getRed(pixel);
1669:                                    dstBuffer[j++] = (byte) cm.getAlpha(pixel);
1670:                                }
1671:                                offset += dstLineBytes;
1672:                                j = dstBegin + offset;
1673:                            }
1674:
1675:                            // advance the destination buffer offset
1676:                            dstBegin += curw * unitsPerPixel;
1677:
1678:                            // move to the next tile in x direction
1679:                            x = 0;
1680:
1681:                            // determine the width of copy region of the next tile
1682:
1683:                            tmpw -= curw;
1684:                            if (tmpw < tilew) {
1685:                                curw = tmpw;
1686:                            } else {
1687:                                curw = tilew;
1688:                            }
1689:                        }
1690:
1691:                        // we are done copying an array of tiles in the x direction
1692:                        // advance the tileStart offset
1693:
1694:                        tileStart += dataWidth * unitsPerPixel * curh * sign;
1695:
1696:                        // move to the next set of tiles in y direction
1697:                        y = 0;
1698:
1699:                        // determine the height of copy region for the next set
1700:                        // of tiles
1701:                        tmph -= curh;
1702:                        if (tmph < tileh) {
1703:                            curh = tmph;
1704:                        } else {
1705:                            curh = tileh;
1706:                        }
1707:                    }
1708:                }
1709:                    break;
1710:                case 1: {
1711:                    for (n = minTileY; n < minTileY + numYTiles; n++) {
1712:
1713:                        dstBegin = tileStart; // destination buffer offset
1714:                        tmpw = copyWidth; // reset the width to be copied
1715:                        curw = startw; // reset the width to be copied of
1716:                        // the left most tile
1717:                        x = srcX - startXTile; // reset the starting x offset of
1718:                        // the left most tile
1719:
1720:                        for (m = minTileX; m < minTileX + numXTiles; m++) {
1721:
1722:                            // retrieve the raster for the next tile
1723:                            ras = ri.getTile(m, n);
1724:
1725:                            j = dstBegin;
1726:                            offset = 0;
1727:
1728:                            //System.err.println("curh = "+curh+" curw = "+curw);
1729:                            //System.err.println("x = "+x+" y = "+y);
1730:
1731:                            for (h = y; h < (y + curh); h++) {
1732:                                //			System.err.println("j = "+j);
1733:                                for (w = x; w < (x + curw); w++) {
1734:                                    ras.getDataElements(w, h, pixel);
1735:                                    dstBuffer[j++] = (byte) cm.getRed(pixel);
1736:                                }
1737:                                offset += dstLineBytes;
1738:                                j = dstBegin + offset;
1739:                            }
1740:
1741:                            // advance the destination buffer offset
1742:                            dstBegin += curw * unitsPerPixel;
1743:
1744:                            // move to the next tile in x direction
1745:                            x = 0;
1746:
1747:                            // determine the width of copy region of the next tile
1748:
1749:                            tmpw -= curw;
1750:                            if (tmpw < tilew) {
1751:                                curw = tmpw;
1752:                            } else {
1753:                                curw = tilew;
1754:                            }
1755:                        }
1756:
1757:                        // we are done copying an array of tiles in the x direction
1758:                        // advance the tileStart offset
1759:                        tileStart += dataWidth * unitsPerPixel * curh * sign;
1760:
1761:                        // move to the next set of tiles in y direction
1762:                        y = 0;
1763:
1764:                        // determine the height of copy region for the next set
1765:                        // of tiles
1766:                        tmph -= curh;
1767:                        if (tmph < tileh) {
1768:                            curh = tmph;
1769:                        } else {
1770:                            curh = tileh;
1771:                        }
1772:                    }
1773:                }
1774:                    break;
1775:
1776:                default:
1777:                    assert false;
1778:                }
1779:
1780:                if ((imageData == data) && (imageDataPowerOfTwo != null)) {
1781:                    updateImageDataPowerOfTwo(depthIndex);
1782:                }
1783:            }
1784:
1785:            void evaluateExtensions(Canvas3D canvas) {
1786:                // Issue 366: need to synchronize since it could be called concurrently
1787:                // from multiple renderers (and maybe the renderer(s) and renderbin)
1788:                synchronized (evaluateExtLock) {
1789:                    // For performance reason the ordering of the following 2 statements is intentional.
1790:                    // So that we only need to do format conversion for imageData only
1791:                    evaluateExtABGR(canvas.extensionsSupported);
1792:                    evaluateExtNonPowerOfTwo(canvas.textureExtendedFeatures);
1793:                }
1794:
1795:            }
1796:
1797:            void evaluateExtABGR(int ext) {
1798:
1799:                // If abgrSupported is false, a copy has been created so
1800:                // we don't have to check again.
1801:                if (!abgrSupported) {
1802:                    return;
1803:                }
1804:
1805:                if (getImageFormatType() != ImageFormatType.TYPE_BYTE_ABGR) {
1806:                    return;
1807:                }
1808:
1809:                if ((ext & Canvas3D.EXT_ABGR) != 0) {
1810:                    return;
1811:                }
1812:
1813:                // ABGR is unsupported, set flag to false.
1814:                abgrSupported = false;
1815:                convertImageDataFromABGRToRGBA();
1816:
1817:            }
1818:
1819:            private int getClosestPowerOf2(int value) {
1820:
1821:                if (value < 1)
1822:                    return value;
1823:
1824:                int powerValue = 1;
1825:                for (;;) {
1826:                    powerValue *= 2;
1827:                    if (value < powerValue) {
1828:                        // Found max bound of power, determine which is closest
1829:                        int minBound = powerValue / 2;
1830:                        if ((powerValue - value) > (value - minBound))
1831:                            return minBound;
1832:                        else
1833:                            return powerValue;
1834:                    }
1835:                }
1836:            }
1837:
1838:            private int getCeilPowerOf2(int value) {
1839:
1840:                if (value < 1)
1841:                    return value;
1842:
1843:                int powerValue = 1;
1844:                for (;;) {
1845:                    powerValue *= 2;
1846:                    if (value <= powerValue) {
1847:                        // Found max bound of power
1848:                        return powerValue;
1849:                    }
1850:                }
1851:            }
1852:
1853:            void evaluateExtNonPowerOfTwo(int ext) {
1854:                // Only need to enforce for Raster or Background.
1855:                if (!enforceNonPowerOfTwoSupport) {
1856:                    return;
1857:                }
1858:
1859:                // If npotSupported is false, a copy power of two image has been created
1860:                // so we don't have to check again.
1861:                if (!npotSupported) {
1862:                    return;
1863:                }
1864:
1865:                if (imageData == null && !isByReference()) {
1866:                    return;
1867:                }
1868:
1869:                if ((ext & Canvas3D.TEXTURE_NON_POWER_OF_TWO) != 0) {
1870:                    return;
1871:                }
1872:
1873:                // NPOT is unsupported, set flag to false.
1874:                npotSupported = false;
1875:
1876:                int npotWidth;
1877:                int npotHeight;
1878:                // Always scale up if image size is smaller 512*512.
1879:                if ((width * height) < IMAGE_SIZE_512X512) {
1880:                    npotWidth = getCeilPowerOf2(width);
1881:                    npotHeight = getCeilPowerOf2(height);
1882:                } else {
1883:                    npotWidth = getClosestPowerOf2(width);
1884:                    npotHeight = getClosestPowerOf2(height);
1885:                }
1886:
1887:                // System.err.println("width " + width + " height " + height + " npotWidth " + npotWidth + " npotHeight " + npotHeight);
1888:
1889:                float xScale = (float) npotWidth / (float) width;
1890:                float yScale = (float) npotHeight / (float) height;
1891:
1892:                // scale if scales aren't 1.0
1893:                if (!(xScale == 1.0f && yScale == 1.0f)) {
1894:
1895:                    if (imageData == null) {
1896:                        // This is a byRef, support format and is a RenderedImage case.
1897:                        // See ImageComponent2DRetained.set(RenderedImage image)
1898:                        RenderedImage ri = (RenderedImage) getRefImage(0);
1899:
1900:                        assert !(ri instanceof  BufferedImage);
1901:
1902:                        // Create a buffered image from renderImage
1903:                        ColorModel cm = ri.getColorModel();
1904:                        WritableRaster wRaster = ri.copyData(null);
1905:                        ri = new BufferedImage(cm, wRaster, cm
1906:                                .isAlphaPremultiplied(), null);
1907:
1908:                        // Create image data object with buffer for image. */
1909:                        imageData = createRenderedImageDataObject(null);
1910:                        copySupportedImageToImageData(ri, 0, imageData);
1911:
1912:                    }
1913:
1914:                    assert imageData != null;
1915:
1916:                    // Create a supported BufferedImage type.
1917:                    BufferedImage bi = imageData.createBufferedImage(0);
1918:
1919:                    int imageType = bi.getType();
1920:                    BufferedImage scaledImg = new BufferedImage(npotWidth,
1921:                            npotHeight, imageType);
1922:
1923:                    AffineTransform at = AffineTransform.getScaleInstance(
1924:                            xScale, yScale);
1925:
1926:                    powerOfTwoATOp = new AffineTransformOp(at,
1927:                            AffineTransformOp.TYPE_BILINEAR);
1928:
1929:                    powerOfTwoATOp.filter(bi, scaledImg);
1930:
1931:                    // System.err.println("bi " + bi.getColorModel());
1932:                    // System.err.println("scaledImg " + scaledImg.getColorModel());
1933:
1934:                    imageDataPowerOfTwo = createRenderedImageDataObject(null,
1935:                            npotWidth, npotHeight);
1936:                    // Since bi is created from imageData, it's imageType is supported.
1937:                    copySupportedImageToImageData(scaledImg, 0,
1938:                            imageDataPowerOfTwo);
1939:
1940:                } else {
1941:                    imageDataPowerOfTwo = null;
1942:                }
1943:            }
1944:
1945:            void convertImageDataFromABGRToRGBA() {
1946:
1947:                // Unsupported format on HW, switch to slow copy.
1948:                imageFormatType = ImageFormatType.TYPE_BYTE_RGBA;
1949:                imageTypeIsSupported = false;
1950:
1951:                // Only need to convert imageData
1952:                imageData.convertFromABGRToRGBA();
1953:
1954:            }
1955:
1956:            /**
1957:             * Copy supported ImageType from ImageData to the user defined bufferedImage
1958:             */
1959:            void copyToRefImage(int depth) {
1960:                int h;
1961:                int rowBegin, // src begin row index
1962:                srcBegin, // src begin offset
1963:                dstBegin; // dst begin offset
1964:
1965:                // refImage has to be a BufferedImage for off screen and read raster
1966:                assert refImage[depth] != null;
1967:                assert (refImage[depth] instanceof  BufferedImage);
1968:
1969:                BufferedImage bi = (BufferedImage) refImage[depth];
1970:                int dstUnitsPerRow = width * unitsPerPixel; // bytes per row in dst image
1971:                rowBegin = 0;
1972:
1973:                if (yUp) {
1974:                    dstBegin = (depth * width * height) * unitsPerPixel;
1975:                } else {
1976:                    dstBegin = (depth * width * height + (height - 1) * width)
1977:                            * unitsPerPixel;
1978:                    dstUnitsPerRow = -1 * dstUnitsPerRow;
1979:                }
1980:
1981:                int scanline = width * unitsPerPixel;
1982:                srcBegin = (rowBegin * width) * unitsPerPixel;
1983:
1984:                switch (imageData.getType()) {
1985:                case TYPE_BYTE_ARRAY:
1986:                    byte[] dstByteBuffer = ((DataBufferByte) bi.getRaster()
1987:                            .getDataBuffer()).getData();
1988:                    byte[] srcByteBuffer = imageData.getAsByteArray();
1989:                    for (h = 0; h < height; h++) {
1990:                        System.arraycopy(srcByteBuffer, srcBegin,
1991:                                dstByteBuffer, dstBegin, scanline);
1992:                        dstBegin += dstUnitsPerRow;
1993:                        srcBegin += scanline;
1994:                    }
1995:                    break;
1996:
1997:                case TYPE_INT_ARRAY:
1998:                    int[] dstIntBuffer = ((DataBufferInt) bi.getRaster()
1999:                            .getDataBuffer()).getData();
2000:                    int[] srcIntBuffer = imageData.getAsIntArray();
2001:                    for (h = 0; h < height; h++) {
2002:                        System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer,
2003:                                dstBegin, scanline);
2004:                        dstBegin += dstUnitsPerRow;
2005:                        srcBegin += scanline;
2006:                    }
2007:                    break;
2008:                default:
2009:                    assert false;
2010:                }
2011:
2012:            }
2013:
2014:            /**
2015:             * Copy image to the user defined bufferedImage ( 3 or 4 components only )
2016:             */
2017:            void copyToRefImageWithFormatConversion(int depth) {
2018:                int w, h, i, j;
2019:                int dstBegin, dstInc, dstIndex, dstIndexInc;
2020:                // refImage has to be a BufferedImage for off screen and read raster
2021:                assert refImage[depth] != null;
2022:                assert (refImage[depth] instanceof  BufferedImage);
2023:
2024:                BufferedImage bi = (BufferedImage) refImage[depth];
2025:                int biType = bi.getType();
2026:                byte[] buf = imageData.getAsByteArray();
2027:
2028:                // convert from Ydown to Yup for texture
2029:                if (!yUp) {
2030:                    dstInc = -1 * width;
2031:                    dstBegin = (height - 1) * width;
2032:                    dstIndex = height - 1;
2033:                    dstIndexInc = -1;
2034:                } else {
2035:                    dstInc = width;
2036:                    dstBegin = 0;
2037:                    dstIndex = 0;
2038:                    dstIndexInc = 1;
2039:                }
2040:
2041:                switch (biType) {
2042:                case BufferedImage.TYPE_INT_ARGB:
2043:                    int[] intData = ((DataBufferInt) bi.getRaster()
2044:                            .getDataBuffer()).getData();
2045:                    // Multiply by 4 to get the byte incr and start point
2046:                    j = 0;
2047:                    switch (imageFormatType) {
2048:                    case TYPE_BYTE_RGBA:
2049:                        for (h = 0; h < height; h++, dstBegin += dstInc) {
2050:                            i = dstBegin;
2051:                            for (w = 0; w < width; w++, j += 4, i++) {
2052:                                intData[i] = (((buf[j + 3] & 0xff) << 24) | // a
2053:                                        ((buf[j] & 0xff) << 16) | // r
2054:                                        ((buf[j + 1] & 0xff) << 8) | // g
2055:                                (buf[j + 2] & 0xff)); // b
2056:                            }
2057:                        }
2058:                        break;
2059:                    case TYPE_BYTE_RGB:
2060:                        for (h = 0; h < height; h++, dstBegin += dstInc) {
2061:                            i = dstBegin;
2062:                            for (w = 0; w < width; w++, j += 3, i++) {
2063:                                intData[i] = (0xff000000 | // a
2064:                                        ((buf[j] & 0xff) << 16) | // r
2065:                                        ((buf[j + 1] & 0xff) << 8) | // g
2066:                                (buf[j + 2] & 0xff)); // b
2067:                            }
2068:                        }
2069:                        break;
2070:                    default:
2071:                        assert false;
2072:                    }
2073:                    break;
2074:
2075:                case BufferedImage.TYPE_INT_RGB:
2076:                    intData = ((DataBufferInt) bi.getRaster().getDataBuffer())
2077:                            .getData();
2078:                    // Multiply by 4 to get the byte incr and start point
2079:                    j = 0;
2080:                    for (h = 0; h < height; h++, dstBegin += dstInc) {
2081:                        i = dstBegin;
2082:                        for (w = 0; w < width; w++, j += 4, i++) {
2083:                            intData[i] = (0xff000000 | // a
2084:                                    ((buf[j] & 0xff) << 16) | // r
2085:                                    ((buf[j + 1] & 0xff) << 8) | // g
2086:                            (buf[j + 2] & 0xff)); // b
2087:                        }
2088:                    }
2089:                    break;
2090:
2091:                case BufferedImage.TYPE_4BYTE_ABGR:
2092:                    byte[] byteData = ((DataBufferByte) bi.getRaster()
2093:                            .getDataBuffer()).getData();
2094:                    // Multiply by 4 to get the byte incr and start point
2095:                    j = 0;
2096:
2097:                    //Issue 381: dstBegin contains pixel count, but we are looping over byte count. In case of YDown, it contains a count that is decremented and if we do not multiply, we have an AIOOB thrown at 25% of the copy.
2098:                    dstBegin <<= 2;
2099:
2100:                    switch (imageFormatType) {
2101:                    case TYPE_BYTE_RGBA:
2102:                        for (h = 0; h < height; h++, dstBegin += (dstInc << 2)) {
2103:                            i = dstBegin;
2104:                            for (w = 0; w < width; w++, j += 4) {
2105:                                byteData[i++] = buf[j + 3]; // a
2106:                                byteData[i++] = buf[j + 2]; // b
2107:                                byteData[i++] = buf[j + 1];// g
2108:                                byteData[i++] = buf[j]; // r
2109:                            }
2110:                        }
2111:                        break;
2112:                    case TYPE_BYTE_RGB:
2113:                        for (h = 0; h < height; h++, dstBegin += (dstInc << 2)) {
2114:                            i = dstBegin;
2115:                            for (w = 0; w < width; w++, j += 3) {
2116:                                byteData[i++] = (byte) 0xff; // a
2117:                                byteData[i++] = buf[j + 2]; // b
2118:                                byteData[i++] = buf[j + 1];// g
2119:                                byteData[i++] = buf[j]; // r
2120:                            }
2121:                        }
2122:                        break;
2123:                    default:
2124:                        assert false;
2125:                    }
2126:                    break;
2127:
2128:                case BufferedImage.TYPE_INT_BGR:
2129:                    intData = ((DataBufferInt) bi.getRaster().getDataBuffer())
2130:                            .getData();
2131:                    // Multiply by 4 to get the byte incr and start point
2132:                    j = 0;
2133:
2134:                    for (h = 0; h < height; h++, dstBegin += dstInc) {
2135:                        i = dstBegin;
2136:                        for (w = 0; w < width; w++, j += 4, i++) {
2137:                            intData[i] = (0xff000000 | // a
2138:                                    ((buf[j] & 0xff)) | // r
2139:                                    ((buf[j + 1] & 0xff) << 8) | // g
2140:                            (buf[j + 2] & 0xff) << 16); // b
2141:                        }
2142:                    }
2143:                    break;
2144:                default:
2145:                    assert false;
2146:                }
2147:
2148:            }
2149:
2150:            // Add a user to the userList
2151:            synchronized void addUser(NodeComponentRetained node) {
2152:                userList.add(node);
2153:            }
2154:
2155:            // Add a user to the  userList
2156:            synchronized void removeUser(NodeComponentRetained node) {
2157:                int i = userList.indexOf(node);
2158:                if (i >= 0) {
2159:                    userList.remove(i);
2160:                }
2161:            }
2162:
2163:            /*
2164:             *
2165:             * @exception IllegalSharingException if this image is
2166:             * being used by a Canvas3D as an off-screen buffer.
2167:             */
2168:            void setLive(boolean inBackgroundGroup, int refCount) {
2169:                // Do illegalSharing check.
2170:                if (getUsedByOffScreen()) {
2171:                    throw new IllegalSharingException(J3dI18N
2172:                            .getString("ImageComponent3"));
2173:                }
2174:                super .setLive(inBackgroundGroup, refCount);
2175:            }
2176:
2177:            /**
2178:             * ImageComponent object doesn't really have mirror object.
2179:             * But it's using the updateMirrorObject interface to propagate
2180:             * the changes to the users
2181:             */
2182:            synchronized void updateMirrorObject(int component, Object value) {
2183:
2184:                //System.err.println("ImageComponent.updateMirrorObject");
2185:
2186:                Object user;
2187:
2188:                if (((component & IMAGE_CHANGED) != 0)
2189:                        || ((component & SUBIMAGE_CHANGED) != 0)) {
2190:                    synchronized (userList) {
2191:                        for (int i = userList.size() - 1; i >= 0; i--) {
2192:                            user = userList.get(i);
2193:                            if (user != null) {
2194:                                if (user instanceof  TextureRetained) {
2195:                                    ((TextureRetained) user)
2196:                                            .notifyImageComponentImageChanged(
2197:                                                    this ,
2198:                                                    (ImageComponentUpdateInfo) value);
2199:                                } else if (user instanceof  RasterRetained) {
2200:                                    ((RasterRetained) user)
2201:                                            .notifyImageComponentImageChanged(
2202:                                                    this ,
2203:                                                    (ImageComponentUpdateInfo) value);
2204:                                } else if (user instanceof  BackgroundRetained) {
2205:                                    ((BackgroundRetained) user)
2206:                                            .notifyImageComponentImageChanged(
2207:                                                    this ,
2208:                                                    (ImageComponentUpdateInfo) value);
2209:                                }
2210:                            }
2211:                        }
2212:                    }
2213:                }
2214:            }
2215:
2216:            final void sendMessage(int attrMask, Object attr) {
2217:
2218:                J3dMessage createMessage = new J3dMessage();
2219:                createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES
2220:                        | J3dThread.UPDATE_RENDER;
2221:                createMessage.type = J3dMessage.IMAGE_COMPONENT_CHANGED;
2222:                createMessage.universe = null;
2223:                createMessage.args[0] = this ;
2224:                createMessage.args[1] = new Integer(attrMask);
2225:                createMessage.args[2] = attr;
2226:                createMessage.args[3] = new Integer(changedFrequent);
2227:                VirtualUniverse.mc.processMessage(createMessage);
2228:            }
2229:
2230:            void handleFrequencyChange(int bit) {
2231:                if (bit == ImageComponent.ALLOW_IMAGE_WRITE) {
2232:                    setFrequencyChangeMask(ImageComponent.ALLOW_IMAGE_WRITE,
2233:                            0x1);
2234:                }
2235:            }
2236:
2237:            static Object getDataElementBuffer(java.awt.image.Raster ras) {
2238:                int nc = ras.getNumDataElements();
2239:
2240:                switch (ras.getTransferType()) {
2241:                case DataBuffer.TYPE_INT:
2242:                    return new int[nc];
2243:                case DataBuffer.TYPE_BYTE:
2244:                    return new byte[nc];
2245:                case DataBuffer.TYPE_USHORT:
2246:                case DataBuffer.TYPE_SHORT:
2247:                    return new short[nc];
2248:                case DataBuffer.TYPE_FLOAT:
2249:                    return new float[nc];
2250:                case DataBuffer.TYPE_DOUBLE:
2251:                    return new double[nc];
2252:                }
2253:                // Should not happen
2254:                return null;
2255:            }
2256:
2257:            /**
2258:             * Wrapper class for image data.
2259:             * Currently supports byte array and int array.
2260:             * Will eventually support NIO ByteBuffer and IntBuffer.
2261:             */
2262:            class ImageData {
2263:
2264:                private Object data = null;
2265:                private ImageDataType imageDataType = ImageDataType.TYPE_NULL;
2266:                private int length = 0;
2267:                private boolean dataIsByRef = false;
2268:                private int dataWidth, dataHeight;
2269:
2270:                /**
2271:                 * Constructs a new ImageData buffer of the specified type with the
2272:                 * specified length.
2273:                 */
2274:                ImageData(ImageDataType imageDataType, int length,
2275:                        int dataWidth, int dataHeight) {
2276:                    this .imageDataType = imageDataType;
2277:                    this .length = length;
2278:                    this .dataWidth = dataWidth;
2279:                    this .dataHeight = dataHeight;
2280:                    this .dataIsByRef = false;
2281:
2282:                    switch (imageDataType) {
2283:                    case TYPE_BYTE_ARRAY:
2284:                        data = new byte[length];
2285:                        break;
2286:                    case TYPE_INT_ARRAY:
2287:                        data = new int[length];
2288:                        break;
2289:                    case TYPE_BYTE_BUFFER:
2290:                        ByteOrder order = ByteOrder.nativeOrder();
2291:                        data = ByteBuffer.allocateDirect(length).order(order);
2292:                        break;
2293:                    case TYPE_INT_BUFFER:
2294:                    default:
2295:                        throw new AssertionError();
2296:                    }
2297:                }
2298:
2299:                /**
2300:                 * Constructs a new ImageData buffer of the specified type with the
2301:                 * specified length and the specified byRefImage as data.
2302:                 */
2303:                ImageData(ImageDataType imageDataType, int length,
2304:                        int dataWidth, int dataHeight, Object byRefImage) {
2305:                    BufferedImage bi;
2306:                    NioImageBuffer nio;
2307:
2308:                    this .imageDataType = imageDataType;
2309:                    this .length = length;
2310:                    this .dataWidth = dataWidth;
2311:                    this .dataHeight = dataHeight;
2312:                    this .dataIsByRef = true;
2313:
2314:                    switch (imageDataType) {
2315:                    case TYPE_BYTE_ARRAY:
2316:                        bi = (BufferedImage) byRefImage;
2317:                        data = ((DataBufferByte) bi.getRaster().getDataBuffer())
2318:                                .getData();
2319:                        break;
2320:                    case TYPE_INT_ARRAY:
2321:                        bi = (BufferedImage) byRefImage;
2322:                        data = ((DataBufferInt) bi.getRaster().getDataBuffer())
2323:                                .getData();
2324:                        break;
2325:                    case TYPE_BYTE_BUFFER:
2326:                    case TYPE_INT_BUFFER:
2327:                        nio = (NioImageBuffer) byRefImage;
2328:                        data = nio.getDataBuffer();
2329:                        break;
2330:                    default:
2331:                        throw new AssertionError();
2332:                    }
2333:                }
2334:
2335:                /**
2336:                 * Constructs a new ImageData buffer from the specified
2337:                 * object. This object stores a reference to the input image data.
2338:                 */
2339:                ImageData(Object data, boolean isByRef) {
2340:                    this .data = data;
2341:                    dataIsByRef = isByRef;
2342:                    dataWidth = ((ImageData) data).dataWidth;
2343:                    dataHeight = ((ImageData) data).dataHeight;
2344:
2345:                    if (data == null) {
2346:                        imageDataType = ImageDataType.TYPE_NULL;
2347:                        length = 0;
2348:                    } else if (data instanceof  byte[]) {
2349:                        imageDataType = ImageDataType.TYPE_BYTE_ARRAY;
2350:                        length = ((byte[]) data).length;
2351:                    } else if (data instanceof  int[]) {
2352:                        imageDataType = ImageDataType.TYPE_INT_ARRAY;
2353:                        length = ((int[]) data).length;
2354:                    } else if (data instanceof  ByteBuffer) {
2355:                        imageDataType = ImageDataType.TYPE_BYTE_BUFFER;
2356:                        length = ((ByteBuffer) data).limit();
2357:                    } else if (data instanceof  IntBuffer) {
2358:                        imageDataType = ImageDataType.TYPE_INT_BUFFER;
2359:                        length = ((IntBuffer) data).limit();
2360:                    } else {
2361:                        assert false;
2362:                    }
2363:                }
2364:
2365:                /**
2366:                 * Returns the type of this DataBuffer.
2367:                 */
2368:                ImageDataType getType() {
2369:                    return imageDataType;
2370:                }
2371:
2372:                /**
2373:                 * Returns the number of elements in this DataBuffer.
2374:                 */
2375:                int length() {
2376:                    return length;
2377:                }
2378:
2379:                /**
2380:                 * Returns the width of this DataBuffer.
2381:                 */
2382:                int getWidth() {
2383:                    return dataWidth;
2384:                }
2385:
2386:                /**
2387:                 * Returns the height of this DataBuffer.
2388:                 */
2389:                int getHeight() {
2390:                    return dataHeight;
2391:                }
2392:
2393:                /**
2394:                 * Returns this DataBuffer as an Object.
2395:                 */
2396:                Object get() {
2397:                    return data;
2398:                }
2399:
2400:                /**
2401:                 * Returns is this data is byRef. No internal data is made.
2402:                 */
2403:                boolean isDataByRef() {
2404:                    return dataIsByRef;
2405:                }
2406:
2407:                /**
2408:                 * Returns this DataBuffer as a byte array.
2409:                 */
2410:                byte[] getAsByteArray() {
2411:                    return (byte[]) data;
2412:                }
2413:
2414:                /**
2415:                 * Returns this DataBuffer as an int array.
2416:                 */
2417:                int[] getAsIntArray() {
2418:                    return (int[]) data;
2419:                }
2420:
2421:                /**
2422:                 * Returns this DataBuffer as an nio ByteBuffer.
2423:                 */
2424:                ByteBuffer getAsByteBuffer() {
2425:                    return (ByteBuffer) data;
2426:                }
2427:
2428:                /**
2429:                 * Returns this DataBuffer as an nio IntBuffer.
2430:                 */
2431:                IntBuffer getAsIntBuffer() {
2432:                    return (IntBuffer) data;
2433:                }
2434:
2435:                // Handle TYPE_BYTE_LA only
2436:                void copyByLineAndExpand(BufferedImage bi, int depthIndex) {
2437:                    int h;
2438:                    int srcBegin, // src begin offset
2439:                    dstBegin; // dst begin offset
2440:
2441:                    assert (imageData.getType() == ImageDataType.TYPE_BYTE_ARRAY);
2442:                    assert (imageFormatType == ImageFormatType.TYPE_BYTE_LA);
2443:
2444:                    int unitsPerRow = width * unitsPerPixel; // bytes per row
2445:                    int scanline = unitsPerRow;
2446:                    if (yUp) {
2447:                        srcBegin = (depthIndex * width * height)
2448:                                * unitsPerPixel;
2449:                    } else {
2450:                        srcBegin = (depthIndex * width * height + (height - 1)
2451:                                * width)
2452:                                * unitsPerPixel;
2453:                        unitsPerRow = -1 * unitsPerRow;
2454:                    }
2455:
2456:                    dstBegin = 0;
2457:                    // ABGR is 4 bytes per pixel
2458:                    int dstUnitsPerRow = width * 4;
2459:
2460:                    byte[] dstByteBuffer = ((DataBufferByte) bi.getRaster()
2461:                            .getDataBuffer()).getData();
2462:                    byte[] srcByteBuffer = imageData.getAsByteArray();
2463:                    for (h = 0; h < height; h++) {
2464:                        for (int v = 0, w = 0; w < scanline; w += unitsPerPixel, v += 4) {
2465:                            dstByteBuffer[dstBegin + v] = srcByteBuffer[srcBegin
2466:                                    + w + 1]; // Alpha
2467:                            dstByteBuffer[dstBegin + v + 1] = 0;
2468:                            dstByteBuffer[dstBegin + v + 2] = 0;
2469:                            dstByteBuffer[dstBegin + v + 3] = srcByteBuffer[srcBegin
2470:                                    + w]; // Red
2471:                        }
2472:
2473:                        dstBegin += dstUnitsPerRow;
2474:                        srcBegin += unitsPerRow;
2475:                    }
2476:
2477:                }
2478:
2479:                // Quick line by line copy
2480:                void copyByLine(BufferedImage bi, int depthIndex,
2481:                        boolean swapNeeded) {
2482:
2483:                    int h;
2484:                    int srcBegin, // src begin offset
2485:                    dstBegin; // dst begin offset
2486:
2487:                    int unitsPerRow = width * unitsPerPixel; // bytes per row
2488:                    int copyUnits = unitsPerRow;
2489:                    if (yUp) {
2490:                        srcBegin = (depthIndex * width * height)
2491:                                * unitsPerPixel;
2492:                    } else {
2493:                        srcBegin = (depthIndex * width * height + (height - 1)
2494:                                * width)
2495:                                * unitsPerPixel;
2496:                        unitsPerRow = -1 * unitsPerRow;
2497:                    }
2498:
2499:                    dstBegin = 0;
2500:
2501:                    switch (imageData.getType()) {
2502:                    case TYPE_BYTE_ARRAY:
2503:                        byte[] dstByteBuffer = ((DataBufferByte) bi.getRaster()
2504:                                .getDataBuffer()).getData();
2505:                        byte[] srcByteBuffer = imageData.getAsByteArray();
2506:                        for (h = 0; h < height; h++) {
2507:                            if (!swapNeeded) {
2508:                                System.arraycopy(srcByteBuffer, srcBegin,
2509:                                        dstByteBuffer, dstBegin, copyUnits);
2510:                            } else {
2511:                                if (imageFormatType == ImageFormatType.TYPE_BYTE_RGB) {
2512:                                    assert (unitsPerPixel == 3);
2513:                                    for (int w = 0; w < copyUnits; w += unitsPerPixel) {
2514:                                        dstByteBuffer[dstBegin + w] = srcByteBuffer[srcBegin
2515:                                                + w + 2];
2516:                                        dstByteBuffer[dstBegin + w + 1] = srcByteBuffer[srcBegin
2517:                                                + w + 1];
2518:                                        dstByteBuffer[dstBegin + w + 2] = srcByteBuffer[srcBegin
2519:                                                + w];
2520:                                    }
2521:                                } else if (imageFormatType == ImageFormatType.TYPE_BYTE_RGBA) {
2522:                                    assert (unitsPerPixel == 4);
2523:                                    for (int w = 0; w < copyUnits; w += unitsPerPixel) {
2524:                                        dstByteBuffer[dstBegin + w] = srcByteBuffer[srcBegin
2525:                                                + w + 3];
2526:                                        dstByteBuffer[dstBegin + w + 1] = srcByteBuffer[srcBegin
2527:                                                + w + 2];
2528:                                        dstByteBuffer[dstBegin + w + 2] = srcByteBuffer[srcBegin
2529:                                                + w + 1];
2530:                                        dstByteBuffer[dstBegin + w + 3] = srcByteBuffer[srcBegin
2531:                                                + w];
2532:                                    }
2533:                                } else {
2534:                                    assert false;
2535:                                }
2536:                            }
2537:                            dstBegin += copyUnits;
2538:                            srcBegin += unitsPerRow;
2539:                        }
2540:                        break;
2541:
2542:                    // INT case doesn't required to handle swapNeeded
2543:                    case TYPE_INT_ARRAY:
2544:                        assert (!swapNeeded);
2545:                        int[] dstIntBuffer = ((DataBufferInt) bi.getRaster()
2546:                                .getDataBuffer()).getData();
2547:                        int[] srcIntBuffer = imageData.getAsIntArray();
2548:                        for (h = 0; h < height; h++) {
2549:                            System.arraycopy(srcIntBuffer, srcBegin,
2550:                                    dstIntBuffer, dstBegin, copyUnits);
2551:                            dstBegin += copyUnits;
2552:                            srcBegin += unitsPerRow;
2553:                        }
2554:                        break;
2555:                    default:
2556:                        assert false;
2557:                    }
2558:                }
2559:
2560:                void copyByBlock(BufferedImage bi, int depthIndex) {
2561:                    // src begin offset
2562:                    int srcBegin = depthIndex * width * height * unitsPerPixel;
2563:
2564:                    switch (imageData.getType()) {
2565:                    case TYPE_BYTE_ARRAY:
2566:                        byte[] dstByteBuffer = ((DataBufferByte) bi.getRaster()
2567:                                .getDataBuffer()).getData();
2568:                        byte[] srcByteBuffer = imageData.getAsByteArray();
2569:                        System.arraycopy(srcByteBuffer, srcBegin,
2570:                                dstByteBuffer, 0,
2571:                                (height * width * unitsPerPixel));
2572:                        break;
2573:                    case TYPE_INT_ARRAY:
2574:                        int[] dstIntBuffer = ((DataBufferInt) bi.getRaster()
2575:                                .getDataBuffer()).getData();
2576:                        int[] srcIntBuffer = imageData.getAsIntArray();
2577:                        System.arraycopy(srcIntBuffer, srcBegin, dstIntBuffer,
2578:                                0, (height * width * unitsPerPixel));
2579:                        break;
2580:                    default:
2581:                        assert false;
2582:                    }
2583:                }
2584:
2585:                // Need to check for imageData is null. if it is null return null.
2586:                BufferedImage createBufferedImage(int depthIndex) {
2587:                    if (data != null) {
2588:                        int bufferType = BufferedImage.TYPE_CUSTOM;
2589:                        boolean swapNeeded = false;
2590:
2591:                        switch (imageFormatType) {
2592:                        case TYPE_BYTE_BGR:
2593:                            bufferType = BufferedImage.TYPE_3BYTE_BGR;
2594:                            break;
2595:                        case TYPE_BYTE_RGB:
2596:                            bufferType = BufferedImage.TYPE_3BYTE_BGR;
2597:                            swapNeeded = true;
2598:                            break;
2599:                        case TYPE_BYTE_ABGR:
2600:                            bufferType = BufferedImage.TYPE_4BYTE_ABGR;
2601:                            break;
2602:                        case TYPE_BYTE_RGBA:
2603:                            bufferType = BufferedImage.TYPE_4BYTE_ABGR;
2604:                            swapNeeded = true;
2605:                            break;
2606:                        // This is a special case. Need to handle separately.
2607:                        case TYPE_BYTE_LA:
2608:                            bufferType = BufferedImage.TYPE_4BYTE_ABGR;
2609:                            break;
2610:                        case TYPE_BYTE_GRAY:
2611:                            bufferType = BufferedImage.TYPE_BYTE_GRAY;
2612:                            break;
2613:                        case TYPE_INT_BGR:
2614:                            bufferType = BufferedImage.TYPE_INT_BGR;
2615:                            break;
2616:                        case TYPE_INT_RGB:
2617:                            bufferType = BufferedImage.TYPE_INT_RGB;
2618:                            break;
2619:                        case TYPE_INT_ARGB:
2620:                            bufferType = BufferedImage.TYPE_INT_ARGB;
2621:                            break;
2622:                        // Unsupported case, so shouldn't be here.
2623:                        case TYPE_USHORT_GRAY:
2624:                            bufferType = BufferedImage.TYPE_USHORT_GRAY;
2625:                        default:
2626:                            assert false;
2627:
2628:                        }
2629:
2630:                        BufferedImage bi = new BufferedImage(width, height,
2631:                                bufferType);
2632:                        if ((!swapNeeded)
2633:                                && (imageFormatType != ImageFormatType.TYPE_BYTE_LA)) {
2634:                            if (yUp) {
2635:                                copyByBlock(bi, depthIndex);
2636:                            } else {
2637:                                copyByLine(bi, depthIndex, false);
2638:                            }
2639:                        } else if (swapNeeded) {
2640:                            copyByLine(bi, depthIndex, swapNeeded);
2641:                        } else if (imageFormatType == ImageFormatType.TYPE_BYTE_LA) {
2642:                            copyByLineAndExpand(bi, depthIndex);
2643:                        } else {
2644:                            assert false;
2645:                        }
2646:
2647:                        return bi;
2648:
2649:                    }
2650:                    return null;
2651:                }
2652:
2653:                void convertFromABGRToRGBA() {
2654:                    int i;
2655:
2656:                    if (imageDataType == ImageComponentRetained.ImageDataType.TYPE_BYTE_ARRAY) {
2657:                        // Note : Highly inefficient for depth > 0 case.
2658:                        // This method doesn't take into account of depth, it is assuming that
2659:                        // depth == 0, which is true for ImageComponent2D.
2660:                        byte[] srcBuffer, dstBuffer;
2661:                        srcBuffer = getAsByteArray();
2662:
2663:                        if (dataIsByRef) {
2664:                            dstBuffer = new byte[length];
2665:                            // Do copy and swap.
2666:                            for (i = 0; i < length; i += 4) {
2667:                                dstBuffer[i] = srcBuffer[i + 3];
2668:                                dstBuffer[i + 1] = srcBuffer[i + 2];
2669:                                dstBuffer[i + 2] = srcBuffer[i + 1];
2670:                                dstBuffer[i + 3] = srcBuffer[i];
2671:                            }
2672:                            data = dstBuffer;
2673:                            dataIsByRef = false;
2674:
2675:                        } else {
2676:                            byte a, b;
2677:                            // Do swap in place.
2678:                            for (i = 0; i < length; i += 4) {
2679:                                a = srcBuffer[i];
2680:                                b = srcBuffer[i + 1];
2681:                                srcBuffer[i] = srcBuffer[i + 3];
2682:                                srcBuffer[i + 1] = srcBuffer[i + 2];
2683:                                srcBuffer[i + 2] = b;
2684:                                srcBuffer[i + 3] = a;
2685:                            }
2686:                        }
2687:                    } else if (imageDataType == ImageComponentRetained.ImageDataType.TYPE_BYTE_BUFFER) {
2688:
2689:                        assert dataIsByRef;
2690:                        ByteBuffer srcBuffer, dstBuffer;
2691:
2692:                        srcBuffer = getAsByteBuffer();
2693:                        srcBuffer.rewind();
2694:
2695:                        ByteOrder order = ByteOrder.nativeOrder();
2696:                        dstBuffer = ByteBuffer.allocateDirect(length).order(
2697:                                order);
2698:                        dstBuffer.rewind();
2699:
2700:                        // Do copy and swap.
2701:                        for (i = 0; i < length; i += 4) {
2702:                            dstBuffer.put(i, srcBuffer.get(i + 3));
2703:                            dstBuffer.put(i + 1, srcBuffer.get(i + 2));
2704:                            dstBuffer.put(i + 2, srcBuffer.get(i + 1));
2705:                            dstBuffer.put(i + 3, srcBuffer.get(i));
2706:                        }
2707:
2708:                        dataIsByRef = false;
2709:
2710:                    }
2711:                }
2712:            }
2713:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.