Source Code Cross Referenced for ColorSpaceJAI.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » javax » media » jai » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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


0001:        /*
0002:         * $RCSfile: ColorSpaceJAI.java,v $
0003:         *
0004:         * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * Use is subject to license terms.
0007:         *
0008:         * $Revision: 1.1 $
0009:         * $Date: 2005/02/11 04:57:06 $
0010:         * $State: Exp $
0011:         */
0012:        package javax.media.jai;
0013:
0014:        import java.awt.Point;
0015:        import java.awt.color.ColorSpace;
0016:        import java.awt.color.ICC_ColorSpace;
0017:        import java.awt.image.Raster;
0018:        import java.awt.image.WritableRaster;
0019:        import java.awt.image.DataBuffer;
0020:        import java.awt.image.DataBufferByte;
0021:        import java.awt.image.DataBufferShort;
0022:        import java.awt.image.DataBufferInt;
0023:        import java.awt.image.SampleModel;
0024:
0025:        /**
0026:         * An abstract subclass of <code>ColorSpace</code> which adds methods to
0027:         * transform colors represented as pixels in a <code>Raster</code> between
0028:         * a specific color space and either sRGB or a well-defined C.I.E. X,Y,Z
0029:         * color space.  As mentioned in the documentation of {@link ColorSpace},
0030:         * sRGB is a proposed standard default RGB color space for the Internet.
0031:         *
0032:         * <p>This class is particularly applicable for use with color
0033:         * spaces which are mathematically defined and for which no I.C.C. profile
0034:         * is readily available.  (Note however that color conversions specified
0035:         * by a simple matrix transformation might best be effected using the
0036:         * "BandCombine" operation.)  The JAI "ColorConvert" operation recognizes when
0037:         * an instance of <code>ColorSpaceJAI</code> is present and uses the
0038:         * <code>Raster</code>-based conversion methods to improve performance.
0039:         * This is possible because without the <code>ColorSpaceJAI</code> definition,
0040:         * a <code>ColorSpace</code> which was not an {@link ICC_ColorSpace}
0041:         * would permit color conversion only by means of pixel-by-pixel invocations
0042:         * of <code>toCIEXYZ(float[])</code> and <code>fromCIEXYZ(float[])</code> (or,
0043:         * equivalently <code>toRGB(float[])</code> and
0044:         * <code>fromRGB(float[])</code>).</p>
0045:         *
0046:         * @see java.awt.color.ColorSpace
0047:         * @see java.awt.color.ICC_ColorSpace
0048:         * @see javax.media.jai.operator.ColorConvertDescriptor
0049:         * @see javax.media.jai.operator.BandCombineDescriptor
0050:         *
0051:         * @since JAI 1.1
0052:         */
0053:        public abstract class ColorSpaceJAI extends ColorSpace {
0054:            /** Cache the maximum value for XYZ color space. */
0055:            private static final double maxXYZ = 1 + 32767.0 / 32768.0;
0056:
0057:            /** Cache the power value for XYZ to RGB */
0058:            private static final double power1 = 1.0 / 2.4;
0059:
0060:            /** The map from byte RGB to the step before matrix operation. */
0061:            private static double[] LUT = new double[256];
0062:
0063:            static {
0064:                for (int i = 0; i < 256; i++) {
0065:                    double v = i / 255.0;
0066:                    if (v < 0.040449936)
0067:                        LUT[i] = v / 12.92;
0068:                    else
0069:                        LUT[i] = Math.pow((v + 0.055) / 1.055, 2.4);
0070:                }
0071:            }
0072:
0073:            /**
0074:             * Whether conversion to/from this <code>ColorSpaceJAI</code>
0075:             * is more efficient using the sRGB methods.
0076:             */
0077:            private boolean isRGBPreferredIntermediary;
0078:
0079:            /**
0080:             * Transforms the pixel data in the source <code>Raster</code> from
0081:             * CIEXYZ to sRGB.  It is assumed that the input XYZ values are
0082:             * represented relative to the CIE D50 white point of the
0083:             * <code>ColorSpace.CS_CIEXYZ</code> color space.  Integral data will
0084:             * be normalized according to the number of bits specified for the
0085:             * respective component; floating point data should be between 0.0 and
0086:             * 1.0&nbsp;+&nbsp;(32767.0&nbsp;/&nbsp;32768.0).  All integral data
0087:             * are assumed to be unsigned; signed data should be shifted by the
0088:             * caller before invoking this method.
0089:             *
0090:             * <p> The exact sequence of transformations applied is as follows:</p>
0091:             * <p><ol>
0092:             * <li>If the source data are integral, convert the digital codes to
0093:             * CIE XYZ values in the range <code>[0.0,&nbsp;F<sub>max</sub>]</code>
0094:             * as:
0095:             * <pre>
0096:             * F<sub>d50</sub> = F<sub>max</sub> * I<sub>src</sub> / 2<sup>M<sub>src</sub></sup>
0097:             * </pre>
0098:             *
0099:             * where
0100:             *
0101:             * <pre>
0102:             * I<sub>src</sub> is the digital code of a source color component
0103:             * M<sub>src</sub> is the number of significant bits per source color
0104:             * component
0105:             * F<sub>max</sub> is 1.0&nbsp;+&nbsp;(32767.0&nbsp;/&nbsp;32768.0)
0106:             * F<sub>d50</sub> is the corresponding CIE XYZ value relative to CIE D50
0107:             * </pre>
0108:             *
0109:             * If the source data are floating point no scaling is performed and it
0110:             * is assumed that the data are already clipped to the range
0111:             * <code>[0.0,&nbsp;1.0&nbsp;+&nbsp;(32767.0&nbsp;/&nbsp;32768.0)]</code>.</li>
0112:             * <p><li>Perform chromatic adaptation from the CIE D50 white point to the
0113:             * CIE D65 white point as described in {@link ICC_ColorSpace#fromCIEXYZ}:
0114:             * <pre>
0115:             * X<sub>d65</sub> = X<sub>d50</sub> * (X<sub>wd65</sub> / X<sub>wd50</sub>)
0116:             * Y<sub>d65</sub> = Y<sub>d50</sub> * (Y<sub>wd65</sub> / Y<sub>wd50</sub>)
0117:             * Z<sub>d65</sub> = Z<sub>d50</sub> * (Z<sub>wd65</sub> / Z<sub>wd50</sub>)
0118:             * </pre>
0119:             *
0120:             * where
0121:             *
0122:             * <pre>
0123:             * X<sub>d50</sub>, Y<sub>d50</sub>, Z<sub>d50</sub> are the XYZ values relative to CIE D50
0124:             * X<sub>wd65</sub>, Y<sub>wd65</sub>, Z<sub>wd65</sub> are the CIE D65 white point values
0125:             * X<sub>wd50</sub>, Y<sub>wd50</sub>, Z<sub>wd50</sub> are the CIE D50 white point values
0126:             * X<sub>d65</sub>, Y<sub>d65</sub>, Z<sub>d65</sub> are the XYZ values relative to CIE D65
0127:             * </pre>
0128:             *
0129:             * Substituting the actual CIE D50 and D65 white point values in the
0130:             * above gives:
0131:             *
0132:             * <pre>
0133:             * X<sub>d65</sub> = X<sub>d50</sub> * (0.3127/0.3457)
0134:             * Y<sub>d65</sub> = Y<sub>d50</sub> * (0.3291/0.3585)
0135:             * Z<sub>d65</sub> = Z<sub>d50</sub> * (0.3582/0.2958)
0136:             * </pre></li></p>
0137:             * <li>Calculate sRGB tristimulus values as:
0138:             * <pre>
0139:             * [ R<sub>sRGB</sub> ]   [  3.2406 -1.5372 -0.4986 ] [ X<sub>d65</sub> ]
0140:             * [ G<sub>sRGB</sub> ] = [ -0.9689  1.8758  0.0415 ] [ Y<sub>d65</sub> ]
0141:             * [ B<sub>sRGB</sub> ]   [  0.0557 -0.2040  1.0570 ] [ Z<sub>d65</sub> ]
0142:             * </pre></li>
0143:             * <p><li>
0144:             * Clip sRGB tristimulus values to the range <code>[0.0,&nbsp;1.0]</code>.
0145:             * </li></p>
0146:             * <li>Transform sRGB tristimulus values to non-linear sR'G'B' values as:
0147:             * <pre>
0148:             * C'<sub>sRGB</sub> = 12.92*C<sub>sRGB</sub> if C<sub>sRGB</sub> <= 0.0031308
0149:             * C'<sub>sRGB</sub> = 1.055*C<sub>sRGB</sub><sup>(1.0/2.4)</sup> - 0.055 if C<sub>sRGB</sub> > 0.0031308
0150:             * </pre>
0151:             *
0152:             * where
0153:             *
0154:             * <pre>
0155:             * C<sub>sRGB</sub> is a sRGB tristimulus value
0156:             * C'<sub>sRGB</sub> is the corresponding non-linear sR'G'B' value
0157:             * </pre></li>
0158:             * <li>If the destination data are integral, convert the non-linear
0159:             * sR'G'B' values to digital codes as:
0160:             * <pre>
0161:             * I<sub>dest</sub> = round(C'<sub>sRGB</sub> * 2<sup>M<sub>dest</sub></sup>)
0162:             * </pre>
0163:             *
0164:             * where
0165:             *
0166:             * <pre>
0167:             * C'<sub>sRGB</sub> is the a non-linear sR'G'B' value
0168:             * M<sub>dest</sub> is the number of significant bits per destination color
0169:             * component
0170:             * I<sub>dest</sub> is the digital code of a destination color component
0171:             * </pre>
0172:             * If the destination data are floating point neither scaling nor rounding
0173:             * is performed.
0174:             * </li>
0175:             * </ol></p>
0176:             *
0177:             * <p>If the destination <code>WritableRaster</code> is <code>null</code>,
0178:             * a new <code>WritableRaster</code> will be created.  The
0179:             * <code>Raster</code>s are treated as having no alpha channel, i.e.,
0180:             * all bands are color bands.</p>
0181:             *
0182:             * <p> This method is provided for the convenience of extenders defining
0183:             * a color space for which the conversion is defined with respect to
0184:             * CIEXYZ.</p>
0185:             *
0186:             * <p><i> It should be noted that there is no official specification
0187:             * of sRGB with respect to digital codes of depths other than 8 bits.
0188:             * The present implementation for other bit depths is provided as an
0189:             * extrapolation of the 8-bit sRGB standard and its use should be
0190:             * recognized as such.  The extrapolation is implemented by replacing
0191:             * the white digital count (<code>WDC</code>) and black digital count
0192:             * (<code>KDC</code>) in the 8-bit sRGB specification with values
0193:             * corresponding to the extrema of the data type in question when
0194:             * treated as unsigned.  For all data types <code>KDC</code> is zero
0195:             * and <code>WDC</code> is specified by the component size
0196:             * parameters.</i></p>
0197:             *
0198:             * @param src the source <code>Raster</code> to be converted.
0199:             * @param srcComponentSize array that specifies the number of significant
0200:             *      bits per source color component; ignored for floating point data.
0201:             *      If <code>null</code> defaults to the value returned by
0202:             *      <code>src.getSampleModel().getSampleSize()</code>.
0203:             * @param dest the destination <code>WritableRaster</code>,
0204:             *        or <code>null</code>.
0205:             * @param destComponentSize array that specifies the number of significant
0206:             *       bits per destination color component; ignored for floating point
0207:             *       data.  If <code>null</code>, defaults to the value returned by
0208:             *       <code>dest.getSampleModel().getSampleSize()</code>, or the sample
0209:             *	     size of the newly created destination WritableRaster if dest is
0210:             *	     null.
0211:             * @return <code>dest</code> color converted from <code>src</code>
0212:             *         or a new, <code>WritableRaster</code> containing the converted
0213:             *         pixels if <code>dest</code> is <code>null</code>.
0214:             * @exception IllegalArgumentException if <code>src</code> is
0215:             *            <code>null</code>, the number of source or destination
0216:             *            bands is not 3, or either component size array
0217:             *            is non-null and has length not equal to 3.
0218:             */
0219:            public static WritableRaster CIEXYZToRGB(Raster src,
0220:                    int[] srcComponentSize, WritableRaster dest,
0221:                    int[] destComponentSize) {
0222:
0223:                // Validate the parameters
0224:                checkParameters(src, srcComponentSize, dest, destComponentSize);
0225:
0226:                SampleModel srcSampleModel = src.getSampleModel();
0227:
0228:                /*if the parameter srcComponentSize is null, use the sample size
0229:                 * of the source raster.
0230:                 */
0231:                if (srcComponentSize == null)
0232:                    srcComponentSize = srcSampleModel.getSampleSize();
0233:
0234:                // if the destination raster is null, create a new WritableRaster
0235:                if (dest == null) {
0236:                    Point origin = new Point(src.getMinX(), src.getMinY());
0237:                    dest = RasterFactory.createWritableRaster(srcSampleModel,
0238:                            origin);
0239:                }
0240:
0241:                /* if the parameter dstComponentSize is null, use the sample size
0242:                 * of the source raster.
0243:                 */
0244:                SampleModel dstSampleModel = dest.getSampleModel();
0245:                if (destComponentSize == null)
0246:                    destComponentSize = dstSampleModel.getSampleSize();
0247:
0248:                PixelAccessor srcAcc = new PixelAccessor(srcSampleModel, null);
0249:                UnpackedImageData srcUid = srcAcc.getPixels(src, src
0250:                        .getBounds(), srcSampleModel.getDataType(), false);
0251:
0252:                switch (srcSampleModel.getDataType()) {
0253:
0254:                case DataBuffer.TYPE_BYTE:
0255:                    CIEXYZToRGBByte(srcUid, srcComponentSize, dest,
0256:                            destComponentSize);
0257:                    break;
0258:                case DataBuffer.TYPE_USHORT:
0259:                case DataBuffer.TYPE_SHORT:
0260:                    CIEXYZToRGBShort(srcUid, srcComponentSize, dest,
0261:                            destComponentSize);
0262:                    break;
0263:                case DataBuffer.TYPE_INT:
0264:                    CIEXYZToRGBInt(srcUid, srcComponentSize, dest,
0265:                            destComponentSize);
0266:                    break;
0267:                case DataBuffer.TYPE_FLOAT:
0268:                    CIEXYZToRGBFloat(srcUid, srcComponentSize, dest,
0269:                            destComponentSize);
0270:                    break;
0271:                case DataBuffer.TYPE_DOUBLE:
0272:                    CIEXYZToRGBDouble(srcUid, srcComponentSize, dest,
0273:                            destComponentSize);
0274:                    break;
0275:                }
0276:
0277:                return dest;
0278:            }
0279:
0280:            /**
0281:             * Verify that the parameters are compatible with the limitations
0282:             * of the static methods {@link #CIEXYZToRGB} and {@link #RGBToCIEXYZ}.
0283:             * If any of the parameters are not compatible with the requirements
0284:             * of these methods, throw an <code>IllegalArgumentException</code>
0285:             *
0286:             * @throws IllegalArgumentException if <code>src</code> is
0287:             *         <code>null</code>.
0288:             * @throws IllegalArgumentException if <code>src.getNumBands()</code>
0289:             *         does not return the value 3.
0290:             * @throws IllegalArgumentException if <code>dst</code> is
0291:             *         non-<code>null</code> and <code>dst.getNumBands()</code>
0292:             *         does not return the value 3.
0293:             * @throws IllegalArgumentException if <code>srcComponentSize</code> is
0294:             *         non-<code>null</code> but its length is not 3.
0295:             * @throws IllegalArgumentException if <code>destComponentSize</code> is
0296:             *         non-<code>null</code> but its length is not 3.
0297:             */
0298:            protected static void checkParameters(Raster src,
0299:                    int[] srcComponentSize, WritableRaster dest,
0300:                    int[] destComponentSize) {
0301:
0302:                if (src == null)
0303:                    throw new IllegalArgumentException(JaiI18N
0304:                            .getString("ColorSpaceJAI0"));
0305:                if (src.getNumBands() != 3)
0306:                    throw new IllegalArgumentException(JaiI18N
0307:                            .getString("ColorSpaceJAI1"));
0308:                if (dest != null && dest.getNumBands() != 3)
0309:                    throw new IllegalArgumentException(JaiI18N
0310:                            .getString("ColorSpaceJAI2"));
0311:                if (srcComponentSize != null && srcComponentSize.length != 3)
0312:                    throw new IllegalArgumentException(JaiI18N
0313:                            .getString("ColorSpaceJAI3"));
0314:                if (destComponentSize != null && destComponentSize.length != 3)
0315:                    throw new IllegalArgumentException(JaiI18N
0316:                            .getString("ColorSpaceJAI4"));
0317:            }
0318:
0319:            /**
0320:             * After conversion, the range of a signed short is
0321:             * <code>[0,&nbsp;Short.MAX_Value-Short.MIN_VALUE]</code> and that
0322:             * of an integer is <code>[0,&nbsp;0xFFFFFFFFL]</code>.  To avoid
0323:             * clamping, convert the value to a signed integer with the same
0324:             * binary bits.  If the <code>dataType</code> parameter is either
0325:             * <code>DataBuffer.TYPE_SHORT</code> or <code>DataBuffer.TYPE_INT</code>
0326:             * then the array is modified in place; otherwise the method has no
0327:             * effect.
0328:             *
0329:             * @param buf Array of post-conversion digital codes.
0330:             * @param dataType The data type: one of the constants <code>TYPE_*</code>
0331:             *        defined in {@link DataBuffer}.
0332:             */
0333:            static void convertToSigned(double[] buf, int dataType) {
0334:                if (dataType == DataBuffer.TYPE_SHORT) {
0335:                    for (int i = 0; i < buf.length; i++) {
0336:                        short temp = (short) (((int) buf[i]) & 0xFFFF);
0337:                        buf[i] = temp;
0338:                    }
0339:                } else if (dataType == DataBuffer.TYPE_INT) {
0340:                    for (int i = 0; i < buf.length; i++) {
0341:                        int temp = (int) (((long) buf[i]) & 0xFFFFFFFFl);
0342:                        buf[i] = temp;
0343:                    }
0344:                }
0345:            }
0346:
0347:            static void XYZ2RGB(float[] XYZ, float[] RGB) {
0348:                RGB[0] = 2.9311227F * XYZ[0] - 1.4111496F * XYZ[1] - 0.6038046F
0349:                        * XYZ[2];
0350:                RGB[1] = -0.87637005F * XYZ[0] + 1.7219844F * XYZ[1]
0351:                        + 0.0502565F * XYZ[2];
0352:                RGB[2] = 0.05038065F * XYZ[0] - 0.187272F * XYZ[1] + 1.280027F
0353:                        * XYZ[2];
0354:
0355:                for (int i = 0; i < 3; i++) {
0356:                    float v = RGB[i];
0357:
0358:                    if (v < 0.0F)
0359:                        v = 0.0F;
0360:
0361:                    if (v < 0.0031308F)
0362:                        RGB[i] = 12.92F * v;
0363:                    else {
0364:                        if (v > 1.0F)
0365:                            v = 1.0F;
0366:
0367:                        RGB[i] = (float) (1.055 * Math.pow(v, power1) - 0.055);
0368:                    }
0369:                }
0370:            }
0371:
0372:            private static void roundValues(double[] data) {
0373:                for (int i = 0; i < data.length; i++)
0374:                    data[i] = (long) (data[i] + 0.5);
0375:            }
0376:
0377:            // Convert a byte raster from CIEXYZ to RGB color space
0378:            static void CIEXYZToRGBByte(UnpackedImageData src,
0379:                    int[] srcComponentSize, WritableRaster dest,
0380:                    int[] destComponentSize) {
0381:                byte[] xBuf = src.getByteData(0);
0382:                byte[] yBuf = src.getByteData(1);
0383:                byte[] zBuf = src.getByteData(2);
0384:
0385:                // maps the integral XYZ into floating-point
0386:                float normx = (float) (maxXYZ / ((1L << srcComponentSize[0]) - 1));
0387:                float normy = (float) (maxXYZ / ((1L << srcComponentSize[1]) - 1));
0388:                float normz = (float) (maxXYZ / ((1L << srcComponentSize[2]) - 1));
0389:
0390:                // the upper bounds for the red, green and blue bands
0391:                double upperr = 1.0, upperg = 1.0, upperb = 1.0;
0392:
0393:                int dstType = dest.getSampleModel().getDataType();
0394:
0395:                // for the integer type, re-calculate the bounds
0396:                if (dstType < DataBuffer.TYPE_FLOAT) {
0397:                    upperr = (1L << destComponentSize[0]) - 1;
0398:                    upperg = (1L << destComponentSize[1]) - 1;
0399:                    upperb = (1L << destComponentSize[2]) - 1;
0400:                }
0401:
0402:                int height = dest.getHeight();
0403:                int width = dest.getWidth();
0404:
0405:                double[] dstPixels = new double[3 * height * width];
0406:
0407:                int xStart = src.bandOffsets[0];
0408:                int yStart = src.bandOffsets[1];
0409:                int zStart = src.bandOffsets[2];
0410:                int srcPixelStride = src.pixelStride;
0411:                int srcLineStride = src.lineStride;
0412:
0413:                float[] XYZ = new float[3];
0414:                float[] RGB = new float[3];
0415:
0416:                int dIndex = 0;
0417:                for (int j = 0; j < height; j++, xStart += srcLineStride, yStart += srcLineStride, zStart += srcLineStride) {
0418:                    for (int i = 0, xIndex = xStart, yIndex = yStart, zIndex = zStart; i < width; i++, xIndex += srcPixelStride, yIndex += srcPixelStride, zIndex += srcPixelStride) {
0419:                        XYZ[0] = (xBuf[xIndex] & 0xFF) * normx;
0420:                        XYZ[1] = (yBuf[yIndex] & 0xFF) * normy;
0421:                        XYZ[2] = (zBuf[zIndex] & 0xFF) * normz;
0422:
0423:                        XYZ2RGB(XYZ, RGB);
0424:
0425:                        dstPixels[dIndex++] = upperr * RGB[0];
0426:                        dstPixels[dIndex++] = upperg * RGB[1];
0427:                        dstPixels[dIndex++] = upperb * RGB[2];
0428:                    }
0429:                }
0430:
0431:                // Because of 4738524: setPixels should round the provided double 
0432:                // value instead of casting
0433:                // If it is fixed, then this piece of code can be removed.
0434:                if (dstType < DataBuffer.TYPE_FLOAT)
0435:                    roundValues(dstPixels);
0436:
0437:                convertToSigned(dstPixels, dstType);
0438:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
0439:                        dstPixels);
0440:            }
0441:
0442:            // convert a short type raster from CIEXYZ to RGB
0443:            private static void CIEXYZToRGBShort(UnpackedImageData src,
0444:                    int[] srcComponentSize, WritableRaster dest,
0445:                    int[] destComponentSize) {
0446:                short[] xBuf = src.getShortData(0);
0447:                short[] yBuf = src.getShortData(1);
0448:                short[] zBuf = src.getShortData(2);
0449:
0450:                // maps the integral XYZ into floating-point
0451:                float normx = (float) (maxXYZ / ((1L << srcComponentSize[0]) - 1));
0452:                float normy = (float) (maxXYZ / ((1L << srcComponentSize[1]) - 1));
0453:                float normz = (float) (maxXYZ / ((1L << srcComponentSize[2]) - 1));
0454:
0455:                // the upper bounds for the red, green and blue bands
0456:                double upperr = 1.0, upperg = 1.0, upperb = 1.0;
0457:
0458:                int dstType = dest.getSampleModel().getDataType();
0459:
0460:                // for the integer type, re-calculate the norm and bands
0461:                if (dstType < DataBuffer.TYPE_FLOAT) {
0462:                    upperr = (1L << destComponentSize[0]) - 1;
0463:                    upperg = (1L << destComponentSize[1]) - 1;
0464:                    upperb = (1L << destComponentSize[2]) - 1;
0465:                }
0466:
0467:                int height = dest.getHeight();
0468:                int width = dest.getWidth();
0469:
0470:                double[] dstPixels = new double[3 * height * width];
0471:
0472:                int xStart = src.bandOffsets[0];
0473:                int yStart = src.bandOffsets[1];
0474:                int zStart = src.bandOffsets[2];
0475:                int srcPixelStride = src.pixelStride;
0476:                int srcLineStride = src.lineStride;
0477:
0478:                float[] XYZ = new float[3];
0479:                float[] RGB = new float[3];
0480:
0481:                int dIndex = 0;
0482:                for (int j = 0; j < height; j++, xStart += srcLineStride, yStart += srcLineStride, zStart += srcLineStride) {
0483:                    for (int i = 0, xIndex = xStart, yIndex = yStart, zIndex = zStart; i < width; i++, xIndex += srcPixelStride, yIndex += srcPixelStride, zIndex += srcPixelStride) {
0484:                        XYZ[0] = (xBuf[xIndex] & 0xFFFF) * normx;
0485:                        XYZ[1] = (yBuf[yIndex] & 0xFFFF) * normy;
0486:                        XYZ[2] = (zBuf[zIndex] & 0xFFFF) * normz;
0487:
0488:                        XYZ2RGB(XYZ, RGB);
0489:
0490:                        dstPixels[dIndex++] = upperr * RGB[0];
0491:                        dstPixels[dIndex++] = upperg * RGB[1];
0492:                        dstPixels[dIndex++] = upperb * RGB[2];
0493:                    }
0494:                }
0495:
0496:                // Because of 4738524: setPixels should round the provided double 
0497:                // value instead of casting
0498:                // If it is fixed, then this piece of code can be removed.
0499:                if (dstType < DataBuffer.TYPE_FLOAT)
0500:                    roundValues(dstPixels);
0501:
0502:                convertToSigned(dstPixels, dstType);
0503:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
0504:                        dstPixels);
0505:            }
0506:
0507:            // convert an int type raster from CIEXYZ to RGB
0508:            private static void CIEXYZToRGBInt(UnpackedImageData src,
0509:                    int[] srcComponentSize, WritableRaster dest,
0510:                    int[] destComponentSize) {
0511:                int[] xBuf = src.getIntData(0);
0512:                int[] yBuf = src.getIntData(1);
0513:                int[] zBuf = src.getIntData(2);
0514:
0515:                // maps the integral XYZ into floating-point
0516:                float normx = (float) (maxXYZ / ((1L << srcComponentSize[0]) - 1));
0517:                float normy = (float) (maxXYZ / ((1L << srcComponentSize[1]) - 1));
0518:                float normz = (float) (maxXYZ / ((1L << srcComponentSize[2]) - 1));
0519:
0520:                // the upper bound for each band
0521:                double upperr = 1.0, upperg = 1.0, upperb = 1.0;
0522:
0523:                int dstType = dest.getSampleModel().getDataType();
0524:
0525:                // for the integer type, re-calculate the bounds
0526:                if (dstType < DataBuffer.TYPE_FLOAT) {
0527:                    upperr = (1L << destComponentSize[0]) - 1;
0528:                    upperg = (1L << destComponentSize[1]) - 1;
0529:                    upperb = (1L << destComponentSize[2]) - 1;
0530:                }
0531:
0532:                int height = dest.getHeight();
0533:                int width = dest.getWidth();
0534:
0535:                double[] dstPixels = new double[3 * height * width];
0536:
0537:                int xStart = src.bandOffsets[0];
0538:                int yStart = src.bandOffsets[1];
0539:                int zStart = src.bandOffsets[2];
0540:                int srcPixelStride = src.pixelStride;
0541:                int srcLineStride = src.lineStride;
0542:
0543:                float[] XYZ = new float[3];
0544:                float[] RGB = new float[3];
0545:
0546:                int dIndex = 0;
0547:                for (int j = 0; j < height; j++, xStart += srcLineStride, yStart += srcLineStride, zStart += srcLineStride) {
0548:                    for (int i = 0, xIndex = xStart, yIndex = yStart, zIndex = zStart; i < width; i++, xIndex += srcPixelStride, yIndex += srcPixelStride, zIndex += srcPixelStride) {
0549:                        XYZ[0] = (xBuf[xIndex] & 0xFFFFFFFFl) * normx;
0550:                        XYZ[1] = (yBuf[yIndex] & 0xFFFFFFFFl) * normy;
0551:                        XYZ[2] = (zBuf[zIndex] & 0xFFFFFFFFl) * normz;
0552:
0553:                        XYZ2RGB(XYZ, RGB);
0554:
0555:                        dstPixels[dIndex++] = upperr * RGB[0];
0556:                        dstPixels[dIndex++] = upperg * RGB[1];
0557:                        dstPixels[dIndex++] = upperb * RGB[2];
0558:                    }
0559:                }
0560:
0561:                // Because of 4738524: setPixels should round the provided double 
0562:                // value instead of casting
0563:                // If it is fixed, then this piece of code can be removed.
0564:                if (dstType < DataBuffer.TYPE_FLOAT)
0565:                    roundValues(dstPixels);
0566:
0567:                convertToSigned(dstPixels, dstType);
0568:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
0569:                        dstPixels);
0570:            }
0571:
0572:            // convert a float type ratser from CIEXYZ to RGB
0573:            private static void CIEXYZToRGBFloat(UnpackedImageData src,
0574:                    int[] srcComponentSize, WritableRaster dest,
0575:                    int[] destComponentSize) {
0576:                float[] xBuf = src.getFloatData(0);
0577:                float[] yBuf = src.getFloatData(1);
0578:                float[] zBuf = src.getFloatData(2);
0579:
0580:                // the upper bounds for the 3 bands
0581:                double upperr = 1.0, upperg = 1.0, upperb = 1.0;
0582:
0583:                int dstType = dest.getSampleModel().getDataType();
0584:
0585:                // for the integer type, re-calculate the bounds
0586:                if (dstType < DataBuffer.TYPE_FLOAT) {
0587:                    upperr = (1L << destComponentSize[0]) - 1;
0588:                    upperg = (1L << destComponentSize[1]) - 1;
0589:                    upperb = (1L << destComponentSize[2]) - 1;
0590:                }
0591:
0592:                int height = dest.getHeight();
0593:                int width = dest.getWidth();
0594:
0595:                double[] dstPixels = new double[3 * height * width];
0596:
0597:                int xStart = src.bandOffsets[0];
0598:                int yStart = src.bandOffsets[1];
0599:                int zStart = src.bandOffsets[2];
0600:                int srcPixelStride = src.pixelStride;
0601:                int srcLineStride = src.lineStride;
0602:
0603:                float[] XYZ = new float[3];
0604:                float[] RGB = new float[3];
0605:
0606:                int dIndex = 0;
0607:                for (int j = 0; j < height; j++, xStart += srcLineStride, yStart += srcLineStride, zStart += srcLineStride) {
0608:                    for (int i = 0, xIndex = xStart, yIndex = yStart, zIndex = zStart; i < width; i++, xIndex += srcPixelStride, yIndex += srcPixelStride, zIndex += srcPixelStride) {
0609:                        XYZ[0] = xBuf[xIndex];
0610:                        XYZ[1] = yBuf[yIndex];
0611:                        XYZ[2] = zBuf[zIndex];
0612:
0613:                        XYZ2RGB(XYZ, RGB);
0614:
0615:                        dstPixels[dIndex++] = upperr * RGB[0];
0616:                        dstPixels[dIndex++] = upperg * RGB[1];
0617:                        dstPixels[dIndex++] = upperb * RGB[2];
0618:                    }
0619:                }
0620:
0621:                // Because of 4738524: setPixels should round the provided double 
0622:                // value instead of casting
0623:                // If it is fixed, then this piece of code can be removed.
0624:                if (dstType < DataBuffer.TYPE_FLOAT)
0625:                    roundValues(dstPixels);
0626:
0627:                convertToSigned(dstPixels, dstType);
0628:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
0629:                        dstPixels);
0630:            }
0631:
0632:            // convert a double type ratser form CIEXYZ to RGB color space
0633:            private static void CIEXYZToRGBDouble(UnpackedImageData src,
0634:                    int[] srcComponentSize, WritableRaster dest,
0635:                    int[] destComponentSize) {
0636:                double[] xBuf = src.getDoubleData(0);
0637:                double[] yBuf = src.getDoubleData(1);
0638:                double[] zBuf = src.getDoubleData(2);
0639:
0640:                // the upper bound of each band
0641:                double upperr = 1.0, upperg = 1.0, upperb = 1.0;
0642:
0643:                int dstType = dest.getSampleModel().getDataType();
0644:
0645:                // for the integer type, re-calculate the bounds
0646:                if (dstType < DataBuffer.TYPE_FLOAT) {
0647:                    upperr = (1L << destComponentSize[0]) - 1;
0648:                    upperg = (1L << destComponentSize[1]) - 1;
0649:                    upperb = (1L << destComponentSize[2]) - 1;
0650:                }
0651:
0652:                int height = dest.getHeight();
0653:                int width = dest.getWidth();
0654:
0655:                double[] dstPixels = new double[3 * height * width];
0656:
0657:                int xStart = src.bandOffsets[0];
0658:                int yStart = src.bandOffsets[1];
0659:                int zStart = src.bandOffsets[2];
0660:                int srcPixelStride = src.pixelStride;
0661:                int srcLineStride = src.lineStride;
0662:
0663:                float[] XYZ = new float[3];
0664:                float[] RGB = new float[3];
0665:
0666:                int dIndex = 0;
0667:                for (int j = 0; j < height; j++, xStart += srcLineStride, yStart += srcLineStride, zStart += srcLineStride) {
0668:                    for (int i = 0, xIndex = xStart, yIndex = yStart, zIndex = zStart; i < width; i++, xIndex += srcPixelStride, yIndex += srcPixelStride, zIndex += srcPixelStride) {
0669:                        XYZ[0] = (float) xBuf[xIndex];
0670:                        XYZ[1] = (float) yBuf[yIndex];
0671:                        XYZ[2] = (float) zBuf[zIndex];
0672:
0673:                        XYZ2RGB(XYZ, RGB);
0674:
0675:                        dstPixels[dIndex++] = upperr * RGB[0];
0676:                        dstPixels[dIndex++] = upperg * RGB[1];
0677:                        dstPixels[dIndex++] = upperb * RGB[2];
0678:                    }
0679:                }
0680:
0681:                // Because of 4738524: setPixels should round the provided double 
0682:                // value instead of casting
0683:                // If it is fixed, then this piece of code can be removed.
0684:                if (dstType < DataBuffer.TYPE_FLOAT)
0685:                    roundValues(dstPixels);
0686:
0687:                convertToSigned(dstPixels, dstType);
0688:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
0689:                        dstPixels);
0690:            }
0691:
0692:            /**
0693:             * Transforms the pixel data in the source <code>Raster</code> from
0694:             * sRGB to CIEXYZ.  The output XYZ values are represented relative to
0695:             * the CIE D50 white point of the <code>ColorSpace.CS_CIEXYZ</code>
0696:             * color space.  Integral data will be normalized according to the
0697:             * number of bits specified for the respective component; floating
0698:             * point data should be between 0.0 and 1.0.  All integral data are
0699:             * assumed to be unsigned; signed data should be shifted by the caller
0700:             * before invoking this method.
0701:             *
0702:             * <p> The exact sequence of transformations applied is as follows:</p>
0703:             * <p><ol>
0704:             * <li>If the source data are integral, convert the digital codes to
0705:             * non-linear sRGB values in the range <code>[0.0,&nbsp;1.0]</code> as:
0706:             * <pre>
0707:             * C'<sub>sRGB</sub> = I<sub>src</sub> / 2<sup>M<sub>src</sub></sup>
0708:             * </pre>
0709:             *
0710:             * where
0711:             *
0712:             * <pre>
0713:             * I<sub>src</sub> is the digital code of a source color component
0714:             * M<sub>src</sub> is the number of significant bits per source color
0715:             * component
0716:             * C'<sub>sRGB</sub> is the corresponding sR'G'B' value
0717:             * </pre>
0718:             *
0719:             * If the source data are floating point no scaling is performed and it
0720:             * is assumed that the data are already clipped to the range
0721:             * <code>[0.0,&nbsp;1.0]</code>.</li>
0722:             * <p><li>Transform non-linear sR'G'B' values to sRGB tristimulus values
0723:             * as:
0724:             * <pre>
0725:             * C<sub>sRGB</sub> = C'<sub>sRGB</sub>/12.92 if C'<sub>sRGB</sub> <= 0.04045
0726:             * C<sub>sRGB</sub> = [(C'<sub>sRGB</sub> + 0.055)/1.055]<sup>2.4</sup> if C'<sub>sRGB</sub> > 0.04045
0727:             * </pre>
0728:             *
0729:             * where
0730:             *
0731:             * <pre>
0732:             * C'<sub>sRGB</sub> is a non-linear sR'G'B' value
0733:             * C<sub>sRGB</sub> is the corresponding sRGB tristimulus value
0734:             * </pre></li></p>
0735:             * <li>Calculate CIE XYZ D65-relative values as:
0736:             * <pre>
0737:             * [ X<sub>d65</sub> ]   [ 0.4124 0.3576 0.1805 ] [ R<sub>sRGB</sub> ]
0738:             * [ Y<sub>d65</sub> ] = [ 0.2126 0.7152 0.0722 ] [ G<sub>sRGB</sub> ]
0739:             * [ Z<sub>d65</sub> ]   [ 0.0193 0.1192 0.9505 ] [ B<sub>sRGB</sub> ]
0740:             * </pre></li>
0741:             * <li>Perform chromatic adaptation from the CIE D65 white point to the
0742:             * CIE D50 white point as described in {@link ICC_ColorSpace#toCIEXYZ}:
0743:             * <pre>
0744:             * X<sub>d50</sub> = X<sub>d65</sub> * (X<sub>wd50</sub> / X<sub>wd65</sub>)
0745:             * Y<sub>d50</sub> = Y<sub>d65</sub> * (Y<sub>wd50</sub> / Y<sub>wd65</sub>)
0746:             * Z<sub>d50</sub> = Z<sub>d65</sub> * (Z<sub>wd50</sub> / Z<sub>wd65</sub>)
0747:             * </pre>
0748:             *
0749:             * where
0750:             *
0751:             * <pre>
0752:             * X<sub>d65</sub>, Y<sub>d65</sub>, Z<sub>d65</sub> are the XYZ values relative to CIE D65
0753:             * X<sub>wd50</sub>, Y<sub>wd50</sub>, Z<sub>wd50</sub> are the CIE D50 white point values
0754:             * X<sub>wd65</sub>, Y<sub>wd65</sub>, Z<sub>wd65</sub> are the CIE D65 white point values
0755:             * X<sub>d50</sub>, Y<sub>d50</sub>, Z<sub>d50</sub> are the XYZ values relative to CIE D50
0756:             * </pre>
0757:             *
0758:             * Substituting the actual CIE D50 and D65 white point values in the
0759:             * above gives:
0760:             *
0761:             * <pre>
0762:             * X<sub>d50</sub> = X<sub>d65</sub> * (0.3457/0.3127)
0763:             * Y<sub>d50</sub> = Y<sub>d65</sub> * (0.3585/0.3291)
0764:             * Z<sub>d50</sub> = Z<sub>d65</sub> * (0.2958/0.3582)
0765:             * </pre></li>
0766:             * <li>If the destination data are integral, convert the CIE XYZ
0767:             * values to digital codes as:
0768:             * <pre>
0769:             * I<sub>dest</sub> = round(F<sub>d50</sub> * 2<sup>M<sub>dest</sub></sup> / F<sub>max</sub>)
0770:             * </pre>
0771:             *
0772:             * where
0773:             *
0774:             * <pre>
0775:             * F<sub>d50</sub> is a CIE XYZ value relative to CIE D50
0776:             * M<sub>dest</sub> is the number of significant bits per destination color
0777:             * component
0778:             * F<sub>max</sub> is 1.0&nbsp;+&nbsp;(32767.0&nbsp;/&nbsp;32768.0)
0779:             * I<sub>dest</sub> is the digital code of a destination color component
0780:             * </pre>
0781:             * If the destination data are floating point neither scaling nor rounding
0782:             * is performed.
0783:             * </li>
0784:             * </ol></p>
0785:             *
0786:             * <p> If the destination <code>WritableRaster</code> is <code>null</code>,
0787:             * a new <code>WritableRaster</code> will be created.  The
0788:             * <code>Raster</code>s are treated as having no alpha channel, i.e.,
0789:             * all bands are color bands.
0790:             *
0791:             * <p> This method is provided for the convenience of extenders defining
0792:             * a color space for which the conversion is defined with respect to
0793:             * sRGB.
0794:             *
0795:             * <p><i> It should be noted that there is no official specification
0796:             * of sRGB with respect to digital codes of depths other than 8 bits.
0797:             * The present implementation for other bit depths is provided as an
0798:             * extrapolation of the 8-bit sRGB standard and its use should be
0799:             * recognized as such.  The extrapolation is implemented by replacing
0800:             * the white digital count (<code>WDC</code>) and black digital count
0801:             * (<code>KDC</code>) in the 8-bit sRGB specification with values
0802:             * corresponding to the extrema of the data type in question when
0803:             * treated as unsigned.  For all data types <code>KDC</code> is zero
0804:             * and <code>WDC</code> is specified by the component size
0805:             * parameters.</i></p>
0806:             *
0807:             * @param src the source <code>Raster</code> to be converted.
0808:             * @param srcComponentSize array that specifies the number of significant
0809:             *      bits per source color component; ignored for floating point data.
0810:             *      If <code>null</code> defaults to the value returned by
0811:             *      <code>src.getSampleModel().getSampleSize()</code>.
0812:             * @param dest the destination <code>WritableRaster</code>,
0813:             *        or <code>null</code>.
0814:             * @param destComponentSize array that specifies the number of significant
0815:             *       bits per destination color component; ignored for floating point
0816:             *       data.  If <code>null</code>, defaults to the value returned by
0817:             *       <code>dest.getSampleModel().getSampleSize()</code>, or the sample
0818:             *       size of the newly created destination WritableRaster if dest is
0819:             *	     null.
0820:             * @return <code>dest</code> color converted from <code>src</code>
0821:             *         or a new, <code>WritableRaster</code> containing the converted
0822:             *         pixels if <code>dest</code> is <code>null</code>.
0823:             * @exception IllegalArgumentException if <code>src</code> is
0824:             *            <code>null</code>, the number of source or destination
0825:             *            bands is not 3, or either component size array
0826:             *            is non-null and has length not equal to 3.
0827:             */
0828:            public static WritableRaster RGBToCIEXYZ(Raster src,
0829:                    int[] srcComponentSize, WritableRaster dest,
0830:                    int[] destComponentSize) {
0831:
0832:                checkParameters(src, srcComponentSize, dest, destComponentSize);
0833:
0834:                SampleModel srcSampleModel = src.getSampleModel();
0835:
0836:                // if the srcComponentSize is not provided, use the sample sizes
0837:                // from the source's sample model
0838:                if (srcComponentSize == null)
0839:                    srcComponentSize = srcSampleModel.getSampleSize();
0840:
0841:                // if the destination raster is not provided, create a new one
0842:                if (dest == null) {
0843:                    Point origin = new Point(src.getMinX(), src.getMinY());
0844:                    dest = RasterFactory.createWritableRaster(srcSampleModel,
0845:                            origin);
0846:                }
0847:
0848:                SampleModel dstSampleModel = dest.getSampleModel();
0849:
0850:                //if the destComponentSize is not provided, use the sample sizes
0851:                //from the destination's sample model
0852:                if (destComponentSize == null)
0853:                    destComponentSize = dstSampleModel.getSampleSize();
0854:
0855:                PixelAccessor srcAcc = new PixelAccessor(srcSampleModel, null);
0856:                UnpackedImageData srcUid = srcAcc.getPixels(src, src
0857:                        .getBounds(), srcSampleModel.getDataType(), false);
0858:
0859:                switch (srcSampleModel.getDataType()) {
0860:
0861:                case DataBuffer.TYPE_BYTE:
0862:                    RGBToCIEXYZByte(srcUid, srcComponentSize, dest,
0863:                            destComponentSize);
0864:                    break;
0865:                case DataBuffer.TYPE_USHORT:
0866:                case DataBuffer.TYPE_SHORT:
0867:                    RGBToCIEXYZShort(srcUid, srcComponentSize, dest,
0868:                            destComponentSize);
0869:                    break;
0870:                case DataBuffer.TYPE_INT:
0871:                    RGBToCIEXYZInt(srcUid, srcComponentSize, dest,
0872:                            destComponentSize);
0873:                    break;
0874:                case DataBuffer.TYPE_FLOAT:
0875:                    RGBToCIEXYZFloat(srcUid, srcComponentSize, dest,
0876:                            destComponentSize);
0877:                    break;
0878:                case DataBuffer.TYPE_DOUBLE:
0879:                    RGBToCIEXYZDouble(srcUid, srcComponentSize, dest,
0880:                            destComponentSize);
0881:                    break;
0882:                }
0883:
0884:                return dest;
0885:            }
0886:
0887:            static void RGB2XYZ(float[] RGB, float[] XYZ) {
0888:                for (int i = 0; i < 3; i++) {
0889:                    if (RGB[i] < 0.040449936F)
0890:                        RGB[i] /= 12.92F;
0891:                    else
0892:                        RGB[i] = (float) (Math.pow((RGB[i] + 0.055) / 1.055,
0893:                                2.4));
0894:                }
0895:
0896:                XYZ[0] = 0.45593763F * RGB[0] + 0.39533819F * RGB[1]
0897:                        + 0.19954964F * RGB[2];
0898:                XYZ[1] = 0.23157515F * RGB[0] + 0.77905262F * RGB[1]
0899:                        + 0.07864978F * RGB[2];
0900:                XYZ[2] = 0.01593493F * RGB[0] + 0.09841772F * RGB[1]
0901:                        + 0.78488615F * RGB[2];
0902:            }
0903:
0904:            // convert a byte ratser from RGB to CIEXYZ
0905:            private static void RGBToCIEXYZByte(UnpackedImageData src,
0906:                    int[] srcComponentSize, WritableRaster dest,
0907:                    int[] destComponentSize) {
0908:                byte[] rBuf = src.getByteData(0);
0909:                byte[] gBuf = src.getByteData(1);
0910:                byte[] bBuf = src.getByteData(2);
0911:
0912:                // used to left-shift the value to fill in all the 8-bits
0913:                int normr = 8 - srcComponentSize[0];
0914:                int normg = 8 - srcComponentSize[1];
0915:                int normb = 8 - srcComponentSize[2];
0916:
0917:                // the norms used to map the color value to the desired range
0918:                double normx = 1.0, normy = normx, normz = normx;
0919:
0920:                int dstType = dest.getSampleModel().getDataType();
0921:                boolean isInt = (dstType < DataBuffer.TYPE_FLOAT);
0922:
0923:                // for the integer type, redefine the norms and upper bounds
0924:                // because rgb={1.0, 1.0, 1.0} is xyz={0.950456, 1.0, 1.088754},
0925:                // so for normx, normz, they are specially treated
0926:                if (isInt) {
0927:                    normx = ((1L << destComponentSize[0]) - 1) / maxXYZ;
0928:                    normy = ((1L << destComponentSize[1]) - 1) / maxXYZ;
0929:                    normz = ((1L << destComponentSize[2]) - 1) / maxXYZ;
0930:                }
0931:
0932:                int height = dest.getHeight();
0933:                int width = dest.getWidth();
0934:
0935:                double[] dstPixels = new double[3 * height * width];
0936:
0937:                int rStart = src.bandOffsets[0];
0938:                int gStart = src.bandOffsets[1];
0939:                int bStart = src.bandOffsets[2];
0940:                int srcPixelStride = src.pixelStride;
0941:                int srcLineStride = src.lineStride;
0942:
0943:                int dIndex = 0;
0944:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
0945:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
0946:                        double R = LUT[(rBuf[rIndex] & 0xFF) << normr];
0947:                        double G = LUT[(gBuf[gIndex] & 0xFF) << normg];
0948:                        double B = LUT[(bBuf[bIndex] & 0xFF) << normb];
0949:
0950:                        if (isInt) {
0951:                            double X, Y, Z;
0952:                            dstPixels[dIndex++] = (0.45593763 * R + 0.39533819
0953:                                    * G + 0.19954964 * B)
0954:                                    * normx;
0955:                            dstPixels[dIndex++] = (0.23157515 * R + 0.77905262
0956:                                    * G + 0.07864978 * B)
0957:                                    * normy;
0958:                            dstPixels[dIndex++] = (0.01593493 * R + 0.09841772
0959:                                    * G + 0.78488615 * B)
0960:                                    * normz;
0961:                        } else {
0962:                            dstPixels[dIndex++] = 0.45593763 * R + 0.39533819
0963:                                    * G + 0.19954964 * B;
0964:                            dstPixels[dIndex++] = 0.23157515 * R + 0.77905262
0965:                                    * G + 0.07864978 * B;
0966:                            dstPixels[dIndex++] = 0.01593493 * R + 0.09841772
0967:                                    * G + 0.78488615 * B;
0968:                        }
0969:                    }
0970:                }
0971:
0972:                // Because of 4738524: setPixels should round the provided double 
0973:                // value instead of casting
0974:                // If it is fixed, then this piece of code can be removed.
0975:                if (dstType < DataBuffer.TYPE_FLOAT)
0976:                    roundValues(dstPixels);
0977:
0978:                convertToSigned(dstPixels, dstType);
0979:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
0980:                        dstPixels);
0981:            }
0982:
0983:            // convert a short ratser from RGB to CIEXYZ
0984:            private static void RGBToCIEXYZShort(UnpackedImageData src,
0985:                    int[] srcComponentSize, WritableRaster dest,
0986:                    int[] destComponentSize) {
0987:                short[] rBuf = src.getShortData(0);
0988:                short[] gBuf = src.getShortData(1);
0989:                short[] bBuf = src.getShortData(2);
0990:
0991:                // used to left-shift the input value to fill all the bits
0992:                float normr = (1 << srcComponentSize[0]) - 1;
0993:                float normg = (1 << srcComponentSize[1]) - 1;
0994:                float normb = (1 << srcComponentSize[2]) - 1;
0995:
0996:                // used to map the output to the desired range
0997:                double normx = 1.0, normy = 1.0, normz = 1.0;
0998:
0999:                int dstType = dest.getSampleModel().getDataType();
1000:                boolean isInt = (dstType < DataBuffer.TYPE_FLOAT);
1001:
1002:                // define the norms and upper bounds for the integer types
1003:                // see the comments in RGBToCIEXYZByte
1004:                if (isInt) {
1005:                    normx = ((1L << destComponentSize[0]) - 1) / maxXYZ;
1006:                    normy = ((1L << destComponentSize[1]) - 1) / maxXYZ;
1007:                    normz = ((1L << destComponentSize[2]) - 1) / maxXYZ;
1008:                }
1009:
1010:                int height = dest.getHeight();
1011:                int width = dest.getWidth();
1012:
1013:                double[] dstPixels = new double[3 * height * width];
1014:
1015:                int rStart = src.bandOffsets[0];
1016:                int gStart = src.bandOffsets[1];
1017:                int bStart = src.bandOffsets[2];
1018:                int srcPixelStride = src.pixelStride;
1019:                int srcLineStride = src.lineStride;
1020:
1021:                float[] XYZ = new float[3];
1022:                float[] RGB = new float[3];
1023:
1024:                int dIndex = 0;
1025:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
1026:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
1027:                        RGB[0] = (rBuf[rIndex] & 0xFFFF) / normr;
1028:                        RGB[1] = (gBuf[gIndex] & 0xFFFF) / normg;
1029:                        RGB[2] = (bBuf[bIndex] & 0xFFFF) / normb;
1030:
1031:                        RGB2XYZ(RGB, XYZ);
1032:
1033:                        if (isInt) {
1034:                            dstPixels[dIndex++] = XYZ[0] * normx;
1035:                            dstPixels[dIndex++] = XYZ[1] * normy;
1036:                            dstPixels[dIndex++] = XYZ[2] * normz;
1037:                        } else {
1038:                            dstPixels[dIndex++] = XYZ[0];
1039:                            dstPixels[dIndex++] = XYZ[1];
1040:                            dstPixels[dIndex++] = XYZ[2];
1041:                        }
1042:                    }
1043:                }
1044:
1045:                // Because of 4738524: setPixels should round the provided double 
1046:                // value instead of casting
1047:                // If it is fixed, then this piece of code can be removed.
1048:                if (dstType < DataBuffer.TYPE_FLOAT)
1049:                    roundValues(dstPixels);
1050:
1051:                convertToSigned(dstPixels, dstType);
1052:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1053:                        dstPixels);
1054:            }
1055:
1056:            // convert a int type ratser from RGB to CIEXYZ
1057:            private static void RGBToCIEXYZInt(UnpackedImageData src,
1058:                    int[] srcComponentSize, WritableRaster dest,
1059:                    int[] destComponentSize) {
1060:                int[] rBuf = src.getIntData(0);
1061:                int[] gBuf = src.getIntData(1);
1062:                int[] bBuf = src.getIntData(2);
1063:
1064:                // used to left-shift the input to fill all the bits
1065:                float normr = (1L << srcComponentSize[0]) - 1;
1066:                float normg = (1L << srcComponentSize[1]) - 1;
1067:                float normb = (1L << srcComponentSize[2]) - 1;
1068:
1069:                // norms to map the output to the desired range
1070:                double normx = 1.0, normy = 1.0, normz = 1.0;
1071:
1072:                int dstType = dest.getSampleModel().getDataType();
1073:                boolean isInt = (dstType < DataBuffer.TYPE_FLOAT);
1074:
1075:                // define the norm and upper bounds for the integer output types
1076:                // see also the comments in RGBToCIEXYZByte
1077:                if (isInt) {
1078:                    normx = ((1L << destComponentSize[0]) - 1) / maxXYZ;
1079:                    normy = ((1L << destComponentSize[1]) - 1) / maxXYZ;
1080:                    normz = ((1L << destComponentSize[2]) - 1) / maxXYZ;
1081:                }
1082:
1083:                int height = dest.getHeight();
1084:                int width = dest.getWidth();
1085:
1086:                double[] dstPixels = new double[3 * height * width];
1087:
1088:                int rStart = src.bandOffsets[0];
1089:                int gStart = src.bandOffsets[1];
1090:                int bStart = src.bandOffsets[2];
1091:                int srcPixelStride = src.pixelStride;
1092:                int srcLineStride = src.lineStride;
1093:
1094:                float[] XYZ = new float[3];
1095:                float[] RGB = new float[3];
1096:
1097:                int dIndex = 0;
1098:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
1099:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
1100:                        RGB[0] = (rBuf[rIndex] & 0xFFFFFFFFl) / normr;
1101:                        RGB[1] = (gBuf[gIndex] & 0xFFFFFFFFl) / normg;
1102:                        RGB[2] = (bBuf[bIndex] & 0xFFFFFFFFl) / normb;
1103:
1104:                        RGB2XYZ(RGB, XYZ);
1105:
1106:                        if (isInt) {
1107:                            dstPixels[dIndex++] = XYZ[0] * normx;
1108:                            dstPixels[dIndex++] = XYZ[1] * normx;
1109:                            dstPixels[dIndex++] = XYZ[2] * normx;
1110:                        } else {
1111:                            dstPixels[dIndex++] = XYZ[0];
1112:                            dstPixels[dIndex++] = XYZ[1];
1113:                            dstPixels[dIndex++] = XYZ[2];
1114:                        }
1115:                    }
1116:                }
1117:
1118:                // Because of 4738524: setPixels should round the provided double 
1119:                // value instead of casting
1120:                // If it is fixed, then this piece of code can be removed.
1121:                if (dstType < DataBuffer.TYPE_FLOAT)
1122:                    roundValues(dstPixels);
1123:
1124:                convertToSigned(dstPixels, dstType);
1125:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1126:                        dstPixels);
1127:            }
1128:
1129:            // convert a float type ratser from RGB to CIEXYZ color space
1130:            private static void RGBToCIEXYZFloat(UnpackedImageData src,
1131:                    int[] srcComponentSize, WritableRaster dest,
1132:                    int[] destComponentSize) {
1133:                float[] rBuf = src.getFloatData(0);
1134:                float[] gBuf = src.getFloatData(1);
1135:                float[] bBuf = src.getFloatData(2);
1136:
1137:                // norms to map the output value to the desired range
1138:                double normx = 1.0, normy = 1.0, normz = 1.0;
1139:
1140:                int dstType = dest.getSampleModel().getDataType();
1141:                boolean isInt = (dstType < DataBuffer.TYPE_FLOAT);
1142:
1143:                // define the norms and upper bounds for the integer types
1144:                if (isInt) {
1145:                    normx = ((1L << destComponentSize[0]) - 1) / maxXYZ;
1146:                    normy = ((1L << destComponentSize[1]) - 1) / maxXYZ;
1147:                    normz = ((1L << destComponentSize[2]) - 1) / maxXYZ;
1148:                }
1149:
1150:                int height = dest.getHeight();
1151:                int width = dest.getWidth();
1152:
1153:                double[] dstPixels = new double[3 * height * width];
1154:
1155:                int rStart = src.bandOffsets[0];
1156:                int gStart = src.bandOffsets[1];
1157:                int bStart = src.bandOffsets[2];
1158:                int srcPixelStride = src.pixelStride;
1159:                int srcLineStride = src.lineStride;
1160:
1161:                float[] XYZ = new float[3];
1162:                float[] RGB = new float[3];
1163:
1164:                int dIndex = 0;
1165:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
1166:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
1167:                        RGB[0] = rBuf[rIndex];
1168:                        RGB[1] = gBuf[gIndex];
1169:                        RGB[2] = bBuf[bIndex];
1170:
1171:                        RGB2XYZ(RGB, XYZ);
1172:
1173:                        if (isInt) {
1174:                            dstPixels[dIndex++] = XYZ[0] * normx;
1175:                            dstPixels[dIndex++] = XYZ[1] * normx;
1176:                            dstPixels[dIndex++] = XYZ[2] * normx;
1177:                        } else {
1178:                            dstPixels[dIndex++] = XYZ[0];
1179:                            dstPixels[dIndex++] = XYZ[1];
1180:                            dstPixels[dIndex++] = XYZ[2];
1181:                        }
1182:                    }
1183:                }
1184:
1185:                // Because of 4738524: setPixels should round the provided double 
1186:                // value instead of casting
1187:                // If it is fixed, then this piece of code can be removed.
1188:                if (dstType < DataBuffer.TYPE_FLOAT)
1189:                    roundValues(dstPixels);
1190:
1191:                convertToSigned(dstPixels, dstType);
1192:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1193:                        dstPixels);
1194:            }
1195:
1196:            // convert a double type raster from RGB to CIEXYZ
1197:            private static void RGBToCIEXYZDouble(UnpackedImageData src,
1198:                    int[] srcComponentSize, WritableRaster dest,
1199:                    int[] destComponentSize) {
1200:                double[] rBuf = src.getDoubleData(0);
1201:                double[] gBuf = src.getDoubleData(1);
1202:                double[] bBuf = src.getDoubleData(2);
1203:
1204:                // norms to map the output to the desired range
1205:                double normx = 1.0, normy = 1.0, normz = 1.0;
1206:
1207:                int dstType = dest.getSampleModel().getDataType();
1208:                boolean isInt = (dstType < DataBuffer.TYPE_FLOAT);
1209:
1210:                if (isInt) {
1211:                    normx = ((1L << destComponentSize[0]) - 1) / maxXYZ;
1212:                    normy = ((1L << destComponentSize[1]) - 1) / maxXYZ;
1213:                    normz = ((1L << destComponentSize[2]) - 1) / maxXYZ;
1214:                }
1215:
1216:                int height = dest.getHeight();
1217:                int width = dest.getWidth();
1218:
1219:                double[] dstPixels = new double[3 * height * width];
1220:
1221:                int rStart = src.bandOffsets[0];
1222:                int gStart = src.bandOffsets[1];
1223:                int bStart = src.bandOffsets[2];
1224:                int srcPixelStride = src.pixelStride;
1225:                int srcLineStride = src.lineStride;
1226:
1227:                float[] XYZ = new float[3];
1228:                float[] RGB = new float[3];
1229:
1230:                int dIndex = 0;
1231:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
1232:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
1233:                        RGB[0] = (float) rBuf[rIndex];
1234:                        RGB[1] = (float) gBuf[gIndex];
1235:                        RGB[2] = (float) bBuf[bIndex];
1236:
1237:                        RGB2XYZ(RGB, XYZ);
1238:
1239:                        if (isInt) {
1240:                            dstPixels[dIndex++] = XYZ[0] * normx;
1241:                            dstPixels[dIndex++] = XYZ[1] * normx;
1242:                            dstPixels[dIndex++] = XYZ[2] * normx;
1243:                        } else {
1244:                            dstPixels[dIndex++] = XYZ[0];
1245:                            dstPixels[dIndex++] = XYZ[1];
1246:                            dstPixels[dIndex++] = XYZ[2];
1247:                        }
1248:                    }
1249:                }
1250:
1251:                // Because of 4738524: setPixels should round the provided double 
1252:                // value instead of casting
1253:                // If it is fixed, then this piece of code can be removed.
1254:                if (dstType < DataBuffer.TYPE_FLOAT)
1255:                    roundValues(dstPixels);
1256:
1257:                convertToSigned(dstPixels, dstType);
1258:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1259:                        dstPixels);
1260:            }
1261:
1262:            /**
1263:             * Constructs a <code>ColorSpaceJAI</code> object given the color space
1264:             * type, the number of components, and an indicator of the preferred
1265:             * intermediary or connection color space.
1266:             *
1267:             * @param type The color space type (<code>ColorSpace.TYPE_*</code>).
1268:             * @param numComponents The number of color components.
1269:             * @param isRGBPreferredIntermediary Whether sRGB (<code>true</code>)
1270:             * or CIEXYZ (<code>false</code>) is the preferred connection
1271:             * color space.
1272:             *
1273:             * @exception IllegalArgumentException if <code>numComponents</code>
1274:             *            is non-positive.
1275:             */
1276:            protected ColorSpaceJAI(int type, int numComponents,
1277:                    boolean isRGBPreferredIntermediary) {
1278:                super (type, numComponents);
1279:                this .isRGBPreferredIntermediary = isRGBPreferredIntermediary;
1280:            }
1281:
1282:            /**
1283:             * Whether sRGB is the preferred intermediary color space when converting
1284:             * to another color space which is neither sRGB nor CIEXYZ.  This
1285:             * serves to indicate the more efficient conversion pathway.
1286:             *
1287:             * @return <code>true</code> if sRGB is preferred, or <code>false</code>
1288:             * if CIEXYZ is preferred.
1289:             */
1290:            public boolean isRGBPreferredIntermediary() {
1291:                return this .isRGBPreferredIntermediary;
1292:            }
1293:
1294:            /**
1295:             * Transforms the pixel data in the source <code>Raster</code> from
1296:             * CIEXYZ values with respect to the CIE D50 white point to the color
1297:             * space represented by this class.  If the destination
1298:             * <code>WritableRaster</code> is <code>null</code>, a new
1299:             * <code>WritableRaster</code> will be created.  The
1300:             * <code>Raster</code>s are treated as having no alpha channel, i.e.,
1301:             * all bands are color bands.
1302:             *
1303:             * <p> If required by the underlying transformation, integral data will
1304:             * be normalized according to the number of bits of the respective
1305:             * component; floating point data should be between 0.0 and
1306:             * 1.0&nbsp;+&nbsp;(32767.0&nbsp;/&nbsp;32768.0).
1307:             * All integral data are assumed to be unsigned; signed data should be
1308:             * shifted by the caller before invoking this method.
1309:             *
1310:             * @param src the source <code>Raster</code> to be converted.
1311:             * @param srcComponentSize array that specifies the number of significant
1312:             *      bits per source color component; ignored for floating point data.
1313:             *      If <code>null</code> defaults to the value returned by
1314:             *      <code>src.getSampleModel().getSampleSize()</code>.
1315:             * @param dest the destination <code>WritableRaster</code>,
1316:             *        or <code>null</code>.
1317:             * @param destComponentSize array that specifies the number of significant
1318:             *       bits per destination color component; ignored for floating point
1319:             *       data.  If <code>null</code>, defaults to the value returned by
1320:             *       <code>dest.getSampleModel().getSampleSize()</code>, or the sample
1321:             *       size of the newly created destination WritableRaster if dest is
1322:             *       null.
1323:             * @return <code>dest</code> color converted from <code>src</code>
1324:             *         or a new, <code>WritableRaster</code> containing the converted
1325:             *         pixels if <code>dest</code> is <code>null</code>.
1326:             * @exception IllegalArgumentException if <code>src</code> is
1327:             *            <code>null</code>, the number of source or destination
1328:             *            bands does not equal the number of components of the
1329:             *            respective color space, or either component size array
1330:             *            is non-null and has length not equal to the number of
1331:             *            bands in the respective <code>Raster</code>.
1332:             *
1333:             */
1334:            public abstract WritableRaster fromCIEXYZ(Raster src,
1335:                    int[] srcComponentSize, WritableRaster dest,
1336:                    int[] destComponentSize);
1337:
1338:            /**
1339:             * Transforms the pixel data in the source <code>Raster</code> from
1340:             * sRGB to the color space represented by this class.
1341:             * If the destination <code>WritableRaster</code> is <code>null</code>,
1342:             * a new <code>WritableRaster</code> will be created.  The
1343:             * <code>Raster</code>s are treated as having no alpha channel, i.e.,
1344:             * all bands are color bands.
1345:             *
1346:             * <p> If required by the underlying transformation, integral data will
1347:             * be normalized according to the number of bits of the respective
1348:             * component; floating point data should be between 0.0 and 1.0.
1349:             * All integral data are assumed to be unsigned; signed data should be
1350:             * shifted by the caller before invoking this method.
1351:             *
1352:             * @param src the source <code>Raster</code> to be converted.
1353:             * @param srcComponentSize array that specifies the number of significant
1354:             *      bits per source color component; ignored for floating point data.
1355:             *      If <code>null</code> defaults to the value returned by
1356:             *      <code>src.getSampleModel().getSampleSize()</code>.
1357:             * @param dest the destination <code>WritableRaster</code>,
1358:             *        or <code>null</code>.
1359:             * @param destComponentSize array that specifies the number of significant
1360:             *       bits per destination color component; ignored for floating point
1361:             *       data.  If <code>null</code>, defaults to the value returned by
1362:             *       <code>dest.getSampleModel().getSampleSize()</code>, or the sample
1363:             *       size of the newly created destination WritableRaster if dest is
1364:             *       null.
1365:             * @return <code>dest</code> color converted from <code>src</code>
1366:             *         or a new, <code>WritableRaster</code> containing the converted
1367:             *         pixels if <code>dest</code> is <code>null</code>.
1368:             * @exception IllegalArgumentException if <code>src</code> is
1369:             *            <code>null</code>, the number of source or destination
1370:             *            bands does not equal the number of components of the
1371:             *            respective color space, or either component size array
1372:             *            is non-null and has length not equal to the number of
1373:             *            bands in the respective <code>Raster</code>.
1374:             *
1375:             */
1376:            public abstract WritableRaster fromRGB(Raster src,
1377:                    int[] srcComponentSize, WritableRaster dest,
1378:                    int[] destComponentSize);
1379:
1380:            /**
1381:             * Transforms the pixel data in the source <code>Raster</code> from
1382:             * the color space represented by this class to CIEXYZ values with
1383:             * respect to the CIE D50 white point.  If the destination
1384:             * <code>WritableRaster</code> is <code>null</code>, a new
1385:             * <code>WritableRaster</code> will be created.  The
1386:             * <code>Raster</code>s are treated as having no alpha channel, i.e.,
1387:             * all bands are color bands.
1388:             *
1389:             * <p> If required by the underlying transformation, integral data will
1390:             * be normalized according to the number of bits of the respective
1391:             * component; floating point data should be between 0.0 and 1.0.
1392:             * All integral data are assumed to be unsigned; signed data should be
1393:             * shifted by the caller before invoking this method.
1394:             *
1395:             * @param src the source <code>Raster</code> to be converted.
1396:             * @param srcComponentSize array that specifies the number of significant
1397:             *      bits per source color component; ignored for floating point data.
1398:             *      If <code>null</code> defaults to the value returned by
1399:             *      <code>src.getSampleModel().getSampleSize()</code>.
1400:             * @param dest the destination <code>WritableRaster</code>,
1401:             *        or <code>null</code>.
1402:             * @param destComponentSize array that specifies the number of significant
1403:             *       bits per destination color component; ignored for floating point
1404:             *       data.  If <code>null</code>, defaults to the value returned by
1405:             *       <code>dest.getSampleModel().getSampleSize()</code>, or the sample
1406:             *       size of the newly created destination WritableRaster if dest is
1407:             *       null.
1408:             * @return <code>dest</code> color converted from <code>src</code>
1409:             *         or a new, <code>WritableRaster</code> containing the converted
1410:             *         pixels if <code>dest</code> is <code>null</code>.
1411:             * @exception IllegalArgumentException if <code>src</code> is
1412:             *            <code>null</code>, the number of source or destination
1413:             *            bands does not equal the number of components of the
1414:             *            respective color space, or either component size array
1415:             *            is non-null and has length not equal to the number of
1416:             *            bands in the respective <code>Raster</code>.
1417:             *
1418:             */
1419:            public abstract WritableRaster toCIEXYZ(Raster src,
1420:                    int[] srcComponentSize, WritableRaster dest,
1421:                    int[] destComponentSize);
1422:
1423:            /**
1424:             * Transforms the pixel data in the source <code>Raster</code> from
1425:             * the color space represented by this class to sRGB.
1426:             * If the destination <code>WritableRaster</code> is <code>null</code>,
1427:             * a new <code>WritableRaster</code> will be created.  The
1428:             * <code>Raster</code>s are treated as having no alpha channel, i.e.,
1429:             * all bands are color bands.
1430:             *
1431:             * <p> If required by the underlying transformation, integral data will
1432:             * be normalized according to the number of bits of the respective
1433:             * component; floating point data should be between 0.0 and 1.0.
1434:             * All integral data are assumed to be unsigned; signed data should be
1435:             * shifted by the caller before invoking this method.
1436:             *
1437:             * @param src the source <code>Raster</code> to be converted.
1438:             * @param srcComponentSize array that specifies the number of significant
1439:             *      bits per source color component; ignored for floating point data.
1440:             *      If <code>null</code> defaults to the value returned by
1441:             *      <code>src.getSampleModel().getSampleSize()</code>.
1442:             * @param dest the destination <code>WritableRaster</code>,
1443:             *        or <code>null</code>.
1444:             * @param destComponentSize array that specifies the number of significant
1445:             *       bits per destination color component; ignored for floating point
1446:             *       data.  If <code>null</code>, defaults to the value returned by
1447:             *       <code>dest.getSampleModel().getSampleSize()</code>, or the sample
1448:             *       size of the newly created destination WritableRaster if dest is
1449:             *       null.
1450:             * @return <code>dest</code> color converted from <code>src</code>
1451:             *         or a new, <code>WritableRaster</code> containing the converted
1452:             *         pixels if <code>dest</code> is <code>null</code>.
1453:             * @exception IllegalArgumentException if <code>src</code> is
1454:             *            <code>null</code>, the number of source or destination
1455:             *            bands does not equal the number of components of the
1456:             *            respective color space, or either component size array
1457:             *            is non-null and has length not equal to the number of
1458:             *            bands in the respective <code>Raster</code>.
1459:             *
1460:             */
1461:            public abstract WritableRaster toRGB(Raster src,
1462:                    int[] srcComponentSize, WritableRaster dest,
1463:                    int[] destComponentSize);
1464:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.