Source Code Cross Referenced for IHSColorSpace.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: IHSColorSpace.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.2 $
0009:         * $Date: 2005/11/16 22:58:16 $
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.image.Raster;
0017:        import java.awt.image.WritableRaster;
0018:        import java.awt.image.DataBuffer;
0019:        import java.awt.image.DataBufferByte;
0020:        import java.awt.image.DataBufferShort;
0021:        import java.awt.image.DataBufferInt;
0022:        import java.awt.image.SampleModel;
0023:        import java.lang.ref.SoftReference;
0024:
0025:        /**
0026:         * Singleton class representing the IHS (<i>I</i>ntensity, <i>H</i>ue,
0027:         * <i>S</i>aturation) color space (also known as  HSI or HIS).
0028:         *
0029:         * <p> The RGB-to-IHS transformation is defined by the equations:
0030:         * <ul>
0031:         * <li> I = (R+G+B)/3</li>
0032:         * <li> S = 1-min(R, G, B)/I </li>
0033:         * <li> H = G > B ? h : 2*<code>PI</code> - h, where <br>
0034:         *      h = cos<sup>-1</sup>{[(R-G)+(R-B)]/2[(R-G)<sup>2</sup>+
0035:         *		                             (R-G)(G-B)]<sup>1/2</sup>}</li>
0036:         * </ul>
0037:         * where the R, G, B values have been normalized to the range [0.0,&nbsp;1.0].
0038:         * Refer to <i>Practical Algorithms for Image Analysis</i>, Seul, et. al.,
0039:         * (Cambridge, 2000), pages 50-55, for more information.
0040:         *
0041:         * The inverse transformation (IHS-to-RGB) is defined as:
0042:         *
0043:         * <p>When <code>H</code> is in <code>[2PI/3, 4PI/3]</code>, <code>R</code>
0044:         * should be the smallest. Then, there exists
0045:         * <p><code>R = (1-S)I</code>
0046:         * <p>and <code><ul><li>G = (c1 + c2)/2</li>
0047:         *    <li>B = (c1 - c2)/2</li></ul></code>
0048:         * <p>where <code>c1 = 3I-R</code> and <code>c2 = sqrt(3)(R-I)tg(H)</code>
0049:         *
0050:         * <p>when <code>H</code> is in <code>[4PI/3, 2PI]</code>,
0051:         *
0052:         * <p><code>G = (1-S)I</code>
0053:         * <p>and <code><ul><li>B = (c1 + c2)/2</li>
0054:         *        <li>R = (c1 - c2)/2</li></ul></code>
0055:         * <p>where c1 = 3I-G and c2 = sqrt(3)(G-I)tg(H-2PI/3)
0056:         *
0057:         * <p> when <code>H</code> is in <code>[0, 2PI/3]</code>,
0058:         *
0059:         * <p><code>B = (1-S)I</code>
0060:         * <p>and <code><ul><li>R = (c1 + c2)/2</li>
0061:         *	 <li>G = (c1 - c2)/2</li></ul></code>
0062:         *
0063:         * <p>where <code>c1 = 3I-B</code> and <code>c2 = sqrt(3)(B-I)tg(H-4PI/3)</code>
0064:         * <p> Methods defined in the superclasses are not commented extensively.
0065:         *
0066:         * @see ColorSpaceJAI
0067:         *
0068:         * @since JAI 1.1
0069:         */
0070:        // Old RGB-to-IHS equations ("Practical Algorithms for Image Analysis",
0071:        // Seul, et. al., Cambridge, 2000):
0072:        //
0073:        // <ul>
0074:        // <li> I = (R+G+B)/3</li>
0075:        // <li> S = 1-min(R, G, B)/I </li>
0076:        // <li> H = G > B ? h : 2*<code>PI</code> - h, where <br>
0077:        //      h = cos<sup>-1</sup>{[(R-G)+(R-B)]/2[(R-G)<sup>2</sup>+
0078:        //		                             (R-G)(G-B)]<sup>1/2</sup>}</li>
0079:        // </ul>
0080:        // where the R, G, B values have been normalized to the range [0.0,&nbsp;1.0].
0081:        // <p> The RGB-to-IHS transformation is defined by the equations:
0082:        // <ul>
0083:        // <li><pre>
0084:        // [ I ]   [  1/3        1/3       1/3       ] [ R ]
0085:        // [ U ] = [ -1/sqrt(6) -1/sqrt(6) 2/sqrt(6) ] [ G ]
0086:        // [ V ]   [  1/sqrt(6) -2/sqrt(6) 0         ] [ B ]
0087:        // </pre></li>
0088:        // <li> H = atan(V/U) </li>
0089:        // <li> S = sqrt(U<sup>2</sup> + V<sup>2</sup>) </li>
0090:        // </ul>
0091:        //
0092:        // The inverse IHS-to-RGB transformation is defined by:
0093:        // <ul>
0094:        // <li> U = S*cos(H) </li>
0095:        // <li> V = S*sin(H) </li>
0096:        // <li><pre>
0097:        // [ R ] = [ 4/3 -2*sqrt(6)/9  sqrt(6)/3 ] [ I ]
0098:        // [ G ] = [ 2/3    sqrt(6)/9 -sqrt(6)/3 ] [ U ]
0099:        // [ B ]   [ 1      sqrt(6)/3  0         ] [ V ]
0100:        // </pre></li>
0101:        // </ul>
0102:        //
0103:        // Refer to <i>Digital Image Processing</i>, Second Edition, William K. Pratt
0104:        // (Wiley, 1991), pages 71-72, for more information.
0105:        public final class IHSColorSpace extends ColorSpaceJAI {
0106:            // Constant for rgb-to-ihs
0107:            private static final double PI2 = Math.PI * 2.0;
0108:
0109:            // Constants for ihs-to-rgb
0110:            private static final double PI23 = PI2 / 3.0;
0111:            private static final double PI43 = PI23 * 2.0;
0112:            private static final double SQRT3 = Math.sqrt(3.0);
0113:
0114:            private final static double BYTESCALE = 127.5 / Math.PI;
0115:
0116:            private static SoftReference reference = new SoftReference(null);
0117:
0118:            /* tables and their softrefrences */
0119:            private static byte[] acosTable = null;
0120:            private static double[] sqrtTable = null;
0121:            private static double[] tanTable = null;
0122:            private static SoftReference acosSoftRef;
0123:            private static SoftReference sqrtSoftRef;
0124:            private static SoftReference tanSoftRef;
0125:
0126:            /**
0127:             * Retrieves the unique instance of this class the construction of
0128:             * which is deferred until the first invocation of this method.
0129:             */
0130:            public static IHSColorSpace getInstance() {
0131:                synchronized (reference) {
0132:                    Object referent = reference.get();
0133:                    IHSColorSpace cs;
0134:                    if (referent == null) {
0135:                        // First invocation or SoftReference has been cleared.
0136:                        reference = new SoftReference(cs = new IHSColorSpace());
0137:                    } else {
0138:                        // SoftReference has not been cleared.
0139:                        cs = (IHSColorSpace) referent;
0140:                    }
0141:
0142:                    return cs;
0143:                }
0144:            }
0145:
0146:            /**
0147:             * Constructs an instance of this class with <code>type</code>
0148:             * <code>ColorSpace.TYPE_HSV</code>, 3 components, and preferred
0149:             * intermediary space sRGB.
0150:             */
0151:            protected IHSColorSpace() {
0152:                super (ColorSpace.TYPE_HSV, 3, true);
0153:            }
0154:
0155:            // generate the cos table used in RGBtoIHS for byte type
0156:            private synchronized void generateACosTable() {
0157:
0158:                if ((acosSoftRef == null) || (acosSoftRef.get() == null)) {
0159:                    acosTable = new byte[1001];
0160:                    acosSoftRef = new SoftReference(acosTable);
0161:
0162:                    for (int i = 0; i <= 1000; i++)
0163:                        acosTable[i] = (byte) (BYTESCALE
0164:                                * Math.acos((i - 500) * 0.002) + 0.5);
0165:                }
0166:            }
0167:
0168:            // generate the square root table used in RGBtoIHS for byte type
0169:            private synchronized void generateSqrtTable() {
0170:                if ((sqrtSoftRef == null) || (sqrtSoftRef.get() == null)) {
0171:                    sqrtTable = new double[1001];
0172:                    sqrtSoftRef = new SoftReference(sqrtTable);
0173:
0174:                    for (int i = 0; i <= 1000; i++)
0175:                        sqrtTable[i] = Math.sqrt(i / 1000.0);
0176:                }
0177:            }
0178:
0179:            // generate the tangent table used in IHStoRGB for byte type
0180:            private synchronized void generateTanTable() {
0181:                if ((tanSoftRef == null) || (tanSoftRef.get() == null)) {
0182:                    tanTable = new double[256];
0183:                    tanSoftRef = new SoftReference(tanTable);
0184:
0185:                    for (int i = 0; i < 256; i++)
0186:                        tanTable[i] = Math.tan(i * PI2 / 255.0);
0187:                }
0188:            }
0189:
0190:            /**
0191:             * Converts a single color value from CIEXYZ to IHS.
0192:             */
0193:            public float[] fromCIEXYZ(float[] colorValue) {
0194:                float[] rgb = new float[3];
0195:                XYZ2RGB(colorValue, rgb);
0196:
0197:                float r = rgb[0];
0198:                float g = rgb[1];
0199:                float b = rgb[2];
0200:
0201:                float[] ihs = new float[3];
0202:
0203:                ihs[0] = (r + g + b) / 3.0f;
0204:                float drg = r - g;
0205:                float drb = r - b;
0206:                float temp = (float) Math.sqrt(drg * (double) drg + drb
0207:                        * (double) (drb - drg));
0208:
0209:                // when temp is zero, R=G=B. Hue should be NaN. To make
0210:                // numerically consistent, set it to 2PI
0211:                if (temp != 0.0f) {
0212:                    temp = (float) Math.acos((drg + drb) / (double) temp / 2);
0213:                    if (g < b)
0214:                        ihs[1] = (float) (PI2 - temp);
0215:                    else
0216:                        ihs[1] = temp;
0217:                } else
0218:                    ihs[1] = (float) PI2;
0219:
0220:                float min = (r < g) ? r : g;
0221:                min = (min < b) ? min : b;
0222:
0223:                // when intensity is 0, means R=G=B=0. S can be set to 0 to indicate
0224:                // R=G=B.
0225:                if (ihs[0] == 0.0f)
0226:                    ihs[2] = 0.0f;
0227:                else
0228:                    ihs[2] = 1.0f - min / ihs[0];
0229:
0230:                return ihs;
0231:            }
0232:
0233:            /**
0234:             * Converts a single color value from sRGB to IHS.
0235:             */
0236:            public float[] fromRGB(float[] rgbValue) {
0237:                float r = rgbValue[0];
0238:                float g = rgbValue[1];
0239:                float b = rgbValue[2];
0240:
0241:                r = (r < 0.0f) ? 0.0f : ((r > 1.0f) ? 1.0f : r);
0242:                g = (g < 0.0f) ? 0.0f : ((g > 1.0f) ? 1.0f : g);
0243:                b = (b < 0.0f) ? 0.0f : ((b > 1.0f) ? 1.0f : b);
0244:
0245:                float[] ihs = new float[3];
0246:
0247:                ihs[0] = (r + g + b) / 3.0f;
0248:                float drg = r - g;
0249:                float drb = r - b;
0250:                float temp = (float) Math.sqrt(drg * (double) drg + drb
0251:                        * (double) (drb - drg));
0252:
0253:                // when temp is zero, R=G=B. Hue should be NaN. To make
0254:                // numerically consistent, set it to 2PI
0255:                if (temp != 0.0f) {
0256:                    temp = (float) Math.acos((drg + drb) / (double) temp / 2);
0257:                    if (g < b)
0258:                        ihs[1] = (float) (PI2 - temp);
0259:                    else
0260:                        ihs[1] = temp;
0261:                } else
0262:                    ihs[1] = (float) PI2;
0263:
0264:                float min = (r < g) ? r : g;
0265:                min = (min < b) ? min : b;
0266:
0267:                // when intensity is 0, means R=G=B=0. S can be set to 0 to indicate
0268:                // R=G=B.
0269:                if (ihs[0] == 0.0f)
0270:                    ihs[2] = 0.0f;
0271:                else
0272:                    ihs[2] = 1.0f - min / ihs[0];
0273:
0274:                return ihs;
0275:            }
0276:
0277:            /**
0278:             * Converts a single color value from IHS to CIEXYZ.
0279:             */
0280:            public float[] toCIEXYZ(float[] colorValue) {
0281:                float i = colorValue[0];
0282:                float h = colorValue[1];
0283:                float s = colorValue[2];
0284:
0285:                i = (i < 0.0f) ? 0.0f : ((i > 1.0f) ? 1.0f : i);
0286:                h = (h < 0.0f) ? 0.0f : ((h > (float) PI2) ? (float) PI2 : h);
0287:                s = (s < 0.0f) ? 0.0f : ((s > 1.0f) ? 1.0f : s);
0288:
0289:                float r = 0.0f, g = 0.0f, b = 0.0f;
0290:
0291:                // when the saturation is zero, means this color is grey color.
0292:                // so R=G=B.
0293:                if (s == 0.0f) {
0294:                    r = g = b = i;
0295:                } else {
0296:                    if (h >= PI23 && h < PI43) {
0297:                        r = (1 - s) * i;
0298:                        float c1 = 3 * i - r;
0299:                        float c2 = (float) (SQRT3 * (r - i) * Math.tan(h));
0300:                        g = (c1 + c2) / 2;
0301:                        b = (c1 - c2) / 2;
0302:                    } else if (h > PI43) {
0303:                        g = (1 - s) * i;
0304:                        float c1 = 3 * i - g;
0305:                        float c2 = (float) (SQRT3 * (g - i) * Math
0306:                                .tan(h - PI23));
0307:                        b = (c1 + c2) / 2;
0308:                        r = (c1 - c2) / 2;
0309:                    } else if (h < PI23) {
0310:                        b = (1 - s) * i;
0311:                        float c1 = 3 * i - b;
0312:                        float c2 = (float) (SQRT3 * (b - i) * Math
0313:                                .tan(h - PI43));
0314:                        r = (c1 + c2) / 2;
0315:                        g = (c1 - c2) / 2;
0316:                    }
0317:                }
0318:
0319:                float[] xyz = new float[3];
0320:                float[] rgb = new float[3];
0321:                rgb[0] = r;
0322:                rgb[1] = g;
0323:                rgb[2] = b;
0324:
0325:                RGB2XYZ(rgb, xyz);
0326:
0327:                return xyz;
0328:            }
0329:
0330:            /**
0331:             * Converts a single color value from IHS to sRGB.
0332:             */
0333:            public float[] toRGB(float[] colorValue) {
0334:                float i = colorValue[0];
0335:                float h = colorValue[1];
0336:                float s = colorValue[2];
0337:
0338:                i = (i < 0.0f) ? 0.0f : ((i > 1.0f) ? 1.0f : i);
0339:                h = (h < 0.0f) ? 0.0f : ((h > (float) PI2) ? (float) PI2 : h);
0340:                s = (s < 0.0f) ? 0.0f : ((s > 1.0f) ? 1.0f : s);
0341:
0342:                float[] rgb = new float[3];
0343:
0344:                // when the saturation is 0, the color is grey. so R=G=B=I.
0345:                if (s == 0.0f) {
0346:                    rgb[0] = rgb[1] = rgb[2] = i;
0347:                } else {
0348:                    if (h >= PI23 && h <= PI43) {
0349:                        float r = (1 - s) * i;
0350:                        float c1 = 3 * i - r;
0351:                        float c2 = (float) (SQRT3 * (r - i) * Math.tan(h));
0352:                        rgb[0] = r;
0353:                        rgb[1] = (c1 + c2) / 2;
0354:                        rgb[2] = (c1 - c2) / 2;
0355:                    } else if (h > PI43) {
0356:                        float g = (1 - s) * i;
0357:                        float c1 = 3 * i - g;
0358:                        float c2 = (float) (SQRT3 * (g - i) * Math
0359:                                .tan(h - PI23));
0360:                        rgb[0] = (c1 - c2) / 2;
0361:                        rgb[1] = g;
0362:                        rgb[2] = (c1 + c2) / 2;
0363:                    } else if (h < PI23) {
0364:                        float b = (1 - s) * i;
0365:                        float c1 = 3 * i - b;
0366:                        float c2 = (float) (SQRT3 * (b - i) * Math
0367:                                .tan(h - PI43));
0368:                        rgb[0] = (c1 + c2) / 2;
0369:                        rgb[1] = (c1 - c2) / 2;
0370:                        rgb[2] = b;
0371:                    }
0372:                }
0373:
0374:                return rgb;
0375:            }
0376:
0377:            /**
0378:             * Converts a <code>Raster</code> of colors represented as pixels
0379:             * from CIEXYZ to IHS.
0380:             */
0381:            public WritableRaster fromCIEXYZ(Raster src,
0382:                    int[] srcComponentSize, WritableRaster dest,
0383:                    int[] destComponentSize) {
0384:                WritableRaster tempRas = CIEXYZToRGB(src, srcComponentSize,
0385:                        null, null);
0386:                return fromRGB(tempRas, tempRas.getSampleModel()
0387:                        .getSampleSize(), dest, destComponentSize);
0388:            }
0389:
0390:            /**
0391:             * Converts a <code>Raster</code> of colors represented as pixels
0392:             * from sRGB to IHS.
0393:             */
0394:            public WritableRaster fromRGB(Raster src, int[] srcComponentSize,
0395:                    WritableRaster dest, int[] destComponentSize) {
0396:                //Validate the parameters
0397:                checkParameters(src, srcComponentSize, dest, destComponentSize);
0398:
0399:                SampleModel srcSampleModel = src.getSampleModel();
0400:
0401:                // When the parameter is not provided by the caller, set it as the
0402:                // sample sizes of the source
0403:                if (srcComponentSize == null)
0404:                    srcComponentSize = srcSampleModel.getSampleSize();
0405:
0406:                //when the destination ratser is not provided, create a new one
0407:                if (dest == null) {
0408:                    Point origin = new Point(src.getMinX(), src.getMinY());
0409:                    dest = RasterFactory.createWritableRaster(srcSampleModel,
0410:                            origin);
0411:                }
0412:
0413:                SampleModel dstSampleModel = dest.getSampleModel();
0414:                if (destComponentSize == null)
0415:                    destComponentSize = dstSampleModel.getSampleSize();
0416:
0417:                PixelAccessor srcAcc = new PixelAccessor(srcSampleModel, null);
0418:                UnpackedImageData srcUid = srcAcc.getPixels(src, src
0419:                        .getBounds(), srcSampleModel.getDataType(), false);
0420:
0421:                switch (srcSampleModel.getDataType()) {
0422:
0423:                case DataBuffer.TYPE_BYTE:
0424:                    fromRGBByte(srcUid, srcComponentSize, dest,
0425:                            destComponentSize);
0426:                    break;
0427:                case DataBuffer.TYPE_USHORT:
0428:                case DataBuffer.TYPE_SHORT:
0429:                    fromRGBShort(srcUid, srcComponentSize, dest,
0430:                            destComponentSize);
0431:                    break;
0432:                case DataBuffer.TYPE_INT:
0433:                    fromRGBInt(srcUid, srcComponentSize, dest,
0434:                            destComponentSize);
0435:                    break;
0436:                case DataBuffer.TYPE_FLOAT:
0437:                    fromRGBFloat(srcUid, srcComponentSize, dest,
0438:                            destComponentSize);
0439:                    break;
0440:                case DataBuffer.TYPE_DOUBLE:
0441:                    fromRGBDouble(srcUid, srcComponentSize, dest,
0442:                            destComponentSize);
0443:                    break;
0444:                }
0445:                return dest;
0446:            }
0447:
0448:            // convert a byte type raster from RGB to IHS
0449:            private void fromRGBByte(UnpackedImageData src,
0450:                    int[] srcComponentSize, WritableRaster dest,
0451:                    int[] destComponentSize) {
0452:                byte[] rBuf = src.getByteData(0);
0453:                byte[] gBuf = src.getByteData(1);
0454:                byte[] bBuf = src.getByteData(2);
0455:
0456:                int normr = 8 - srcComponentSize[0];
0457:                int normg = 8 - srcComponentSize[1];
0458:                int normb = 8 - srcComponentSize[2];
0459:
0460:                double normi = 1.0 / 255.0, normh = 1.0, norms = 1.0;
0461:
0462:                int bnormi = 0, bnormh = 0, bnorms = 0;
0463:
0464:                int dstType = dest.getSampleModel().getDataType();
0465:                boolean isByte = (dstType == DataBuffer.TYPE_BYTE);
0466:
0467:                if (isByte) {
0468:                    bnormi = 8 - destComponentSize[0];
0469:                    bnormh = 8 - destComponentSize[1];
0470:                    bnorms = 8 - destComponentSize[2];
0471:                    generateACosTable();
0472:                    generateSqrtTable();
0473:                } else if (dstType < DataBuffer.TYPE_FLOAT) {
0474:                    normi = ((1l << destComponentSize[0]) - 1) / 255.0;
0475:                    normh = ((1l << destComponentSize[1]) - 1) / PI2;
0476:                    norms = ((1l << destComponentSize[2]) - 1);
0477:                }
0478:
0479:                int height = dest.getHeight();
0480:                int width = dest.getWidth();
0481:
0482:                double[] dstPixels = null;
0483:                int[] dstIntPixels = null;
0484:
0485:                if (isByte)
0486:                    dstIntPixels = new int[3 * height * width];
0487:                else
0488:                    dstPixels = new double[3 * height * width];
0489:
0490:                int rStart = src.bandOffsets[0];
0491:                int gStart = src.bandOffsets[1];
0492:                int bStart = src.bandOffsets[2];
0493:                int srcPixelStride = src.pixelStride;
0494:                int srcLineStride = src.lineStride;
0495:
0496:                int dIndex = 0;
0497:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
0498:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
0499:                        short R = (short) ((rBuf[rIndex] & 0xFF) << normr);
0500:                        short G = (short) ((gBuf[gIndex] & 0xFF) << normg);
0501:                        short B = (short) ((bBuf[bIndex] & 0xFF) << normb);
0502:
0503:                        if (isByte) {
0504:                            float intensity = (R + G + B) / 3.0f;
0505:                            dstIntPixels[dIndex++] = ((short) (intensity + 0.5f)) >> bnormi;
0506:
0507:                            short drg = (short) (R - G);
0508:                            short drb = (short) (R - B);
0509:
0510:                            int tint = drg * drg + drb * (drb - drg);
0511:
0512:                            short sum = (short) (drg + drb);
0513:                            double temp;
0514:                            if (tint != 0)
0515:                                temp = sqrtTable[(int) (250.0 * sum * sum
0516:                                        / tint + 0.5)];
0517:                            else
0518:                                temp = -1.0;
0519:
0520:                            int hue;
0521:                            if (sum > 0)
0522:                                hue = acosTable[(int) (500 * temp + 0.5) + 500];
0523:                            else
0524:                                hue = acosTable[(int) (-500 * temp - 0.5) + 500];
0525:
0526:                            if (B >= G)
0527:                                dstIntPixels[dIndex++] = (255 - hue) >> bnormh;
0528:                            else
0529:                                dstIntPixels[dIndex++] = hue >> bnormh;
0530:
0531:                            short min = (G > B) ? B : G;
0532:                            min = (R > min) ? min : R;
0533:                            dstIntPixels[dIndex++] = (255 - (int) (255 * min
0534:                                    / intensity + 0.5f)) >> bnorms;
0535:                        } else {
0536:                            float intensity = (R + G + B) / 3.0f;
0537:                            dstPixels[dIndex++] = normi * intensity;
0538:
0539:                            double drg = R - G;
0540:                            double drb = R - B;
0541:                            double temp = Math.sqrt(drg * drg + drb
0542:                                    * (drb - drg));
0543:
0544:                            if (temp != 0) {
0545:                                temp = Math.acos((drg + drb) / temp / 2);
0546:                                if (B >= G)
0547:                                    temp = PI2 - temp;
0548:                            } else
0549:                                temp = PI2;
0550:
0551:                            dstPixels[dIndex++] = normh * temp;
0552:
0553:                            double min = (G > B) ? B : G;
0554:                            min = (R > min) ? min : R;
0555:                            dstPixels[dIndex++] = norms * (1 - min / intensity);
0556:                        }
0557:                    }
0558:                }
0559:                if (isByte)
0560:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0561:                            height, dstIntPixels);
0562:                else {
0563:                    convertToSigned(dstPixels, dstType);
0564:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0565:                            height, dstPixels);
0566:                }
0567:            }
0568:
0569:            // convert a short type ratser from RGB to IHS
0570:            private void fromRGBShort(UnpackedImageData src,
0571:                    int[] srcComponentSize, WritableRaster dest,
0572:                    int[] destComponentSize) {
0573:                short[] rBuf = src.getShortData(0);
0574:                short[] gBuf = src.getShortData(1);
0575:                short[] bBuf = src.getShortData(2);
0576:
0577:                // used to left-shift the input to fill all the bits
0578:                int normr = 16 - srcComponentSize[0];
0579:                int normg = 16 - srcComponentSize[1];
0580:                int normb = 16 - srcComponentSize[2];
0581:
0582:                //map the output to the desired range
0583:                double normi = 1.0 / 65535.0, normh = 1.0, norms = 1.0;
0584:
0585:                //right-shift the output values to the desired range
0586:                int bnormi = 0, bnormh = 0, bnorms = 0;
0587:
0588:                int dstType = dest.getSampleModel().getDataType();
0589:                boolean isByte = (dstType == DataBuffer.TYPE_BYTE);
0590:
0591:                if (isByte) {
0592:                    bnormi = 16 - destComponentSize[0];
0593:                    bnormh = 8 - destComponentSize[1];
0594:                    bnorms = 8 - destComponentSize[2];
0595:                    generateACosTable();
0596:                    generateSqrtTable();
0597:                } else if (dstType < DataBuffer.TYPE_FLOAT) {
0598:                    normi = ((1l << destComponentSize[0]) - 1) / 65535.0;
0599:                    normh = ((1l << destComponentSize[1]) - 1) / PI2;
0600:                    norms = ((1l << destComponentSize[2]) - 1);
0601:                }
0602:
0603:                int height = dest.getHeight();
0604:                int width = dest.getWidth();
0605:
0606:                double[] dstPixels = null;
0607:                int[] dstIntPixels = null;
0608:
0609:                if (isByte)
0610:                    dstIntPixels = new int[3 * height * width];
0611:                else
0612:                    dstPixels = new double[3 * height * width];
0613:
0614:                int rStart = src.bandOffsets[0];
0615:                int gStart = src.bandOffsets[1];
0616:                int bStart = src.bandOffsets[2];
0617:                int srcPixelStride = src.pixelStride;
0618:                int srcLineStride = src.lineStride;
0619:
0620:                int dIndex = 0;
0621:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
0622:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
0623:                        int R = (rBuf[rIndex] & 0xFFFF) << normr;
0624:                        int G = (gBuf[gIndex] & 0xFFFF) << normg;
0625:                        int B = (bBuf[bIndex] & 0xFFFF) << normb;
0626:
0627:                        if (isByte) {
0628:                            float intensity = (R + G + B) / 3.0f;
0629:                            dstIntPixels[dIndex++] = ((int) (intensity + 0.5f)) >> bnormi;
0630:
0631:                            int drg = R - G;
0632:                            int drb = R - B;
0633:
0634:                            double tint = drg * (double) drg + drb
0635:                                    * (double) (drb - drg);
0636:
0637:                            double sum = drg + drb;
0638:                            double temp;
0639:                            if (tint != 0)
0640:                                temp = sqrtTable[(int) (250.0 * sum * sum
0641:                                        / tint + 0.5)];
0642:                            else
0643:                                temp = -1.0;
0644:
0645:                            int hue;
0646:                            if (sum > 0)
0647:                                hue = acosTable[(int) (500 * temp + 0.5) + 500];
0648:                            else
0649:                                hue = acosTable[(int) (-500 * temp - 0.5) + 500];
0650:
0651:                            if (B >= G)
0652:                                dstIntPixels[dIndex++] = (255 - hue) >> bnormh;
0653:                            else
0654:                                dstIntPixels[dIndex++] = hue >> bnormh;
0655:
0656:                            int min = (G > B) ? B : G;
0657:                            min = (R > min) ? min : R;
0658:                            dstIntPixels[dIndex++] = (255 - (int) (255 * min
0659:                                    / intensity + 0.5f)) >> bnorms;
0660:
0661:                        } else {
0662:                            float intensity = (R + G + B) / 3.0f;
0663:                            dstPixels[dIndex++] = normi * intensity;
0664:
0665:                            double drg = R - G;
0666:                            double drb = R - B;
0667:                            double temp = Math.sqrt(drg * drg + drb
0668:                                    * (drb - drg));
0669:
0670:                            if (temp != 0) {
0671:                                temp = Math.acos((drg + drb) / temp / 2);
0672:                                if (B >= G)
0673:                                    temp = PI2 - temp;
0674:                            } else
0675:                                temp = PI2;
0676:
0677:                            dstPixels[dIndex++] = normh * temp;
0678:
0679:                            double min = (G > B) ? B : G;
0680:                            min = (R > min) ? min : R;
0681:                            dstPixels[dIndex++] = norms * (1 - min / intensity);
0682:                        }
0683:                    }
0684:                }
0685:
0686:                if (isByte)
0687:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0688:                            height, dstIntPixels);
0689:                else {
0690:                    convertToSigned(dstPixels, dstType);
0691:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0692:                            height, dstPixels);
0693:                }
0694:            }
0695:
0696:            // convert an int type raster from RGB to IHS
0697:            private void fromRGBInt(UnpackedImageData src,
0698:                    int[] srcComponentSize, WritableRaster dest,
0699:                    int[] destComponentSize) {
0700:                int[] rBuf = src.getIntData(0);
0701:                int[] gBuf = src.getIntData(1);
0702:                int[] bBuf = src.getIntData(2);
0703:
0704:                int normr = 32 - srcComponentSize[0];
0705:                int normg = 32 - srcComponentSize[1];
0706:                int normb = 32 - srcComponentSize[2];
0707:
0708:                double range = Integer.MAX_VALUE - (double) Integer.MIN_VALUE;
0709:                double normi = 1.0 / range, normh = 1.0, norms = 1.0;
0710:
0711:                int bnormi = 0, bnormh = 0, bnorms = 0;
0712:
0713:                int dstType = dest.getSampleModel().getDataType();
0714:                boolean isByte = (dstType == DataBuffer.TYPE_BYTE);
0715:
0716:                if (isByte) {
0717:                    bnormi = 32 - destComponentSize[0];
0718:                    bnormh = 8 - destComponentSize[1];
0719:                    bnorms = 8 - destComponentSize[2];
0720:                    generateACosTable();
0721:                    generateSqrtTable();
0722:                } else if (dstType < DataBuffer.TYPE_FLOAT) {
0723:                    normi = ((1l << destComponentSize[0]) - 1) / range;
0724:                    normh = ((1l << destComponentSize[1]) - 1) / PI2;
0725:                    norms = ((1l << destComponentSize[2]) - 1);
0726:                }
0727:
0728:                int height = dest.getHeight();
0729:                int width = dest.getWidth();
0730:
0731:                double[] dstPixels = null;
0732:                int[] dstIntPixels = null;
0733:
0734:                if (isByte)
0735:                    dstIntPixels = new int[3 * height * width];
0736:                else
0737:                    dstPixels = new double[3 * height * width];
0738:
0739:                int rStart = src.bandOffsets[0];
0740:                int gStart = src.bandOffsets[1];
0741:                int bStart = src.bandOffsets[2];
0742:                int srcPixelStride = src.pixelStride;
0743:                int srcLineStride = src.lineStride;
0744:
0745:                int dIndex = 0;
0746:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
0747:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
0748:                        long R = (rBuf[rIndex] & 0xFFFFFFFFl) << normr;
0749:                        long G = (gBuf[gIndex] & 0xFFFFFFFFl) << normg;
0750:                        long B = (bBuf[bIndex] & 0xFFFFFFFFl) << normb;
0751:
0752:                        if (isByte) {
0753:                            float intensity = (R + G + B) / 3.0f;
0754:                            dstIntPixels[dIndex++] = (int) (((long) (intensity + 0.5f)) >> bnormi);
0755:
0756:                            long drg = R - G;
0757:                            long drb = R - B;
0758:
0759:                            double tint = drg * (double) drg + drb
0760:                                    * (double) (drb - drg);
0761:
0762:                            double sum = drg + drb;
0763:                            double temp;
0764:                            if (tint != 0)
0765:                                temp = sqrtTable[(int) (250.0 * sum * sum
0766:                                        / tint + 0.5)];
0767:                            else
0768:                                temp = -1.0;
0769:
0770:                            int hue;
0771:                            if (sum > 0)
0772:                                hue = acosTable[(int) (500 * temp + 0.5) + 500];
0773:                            else
0774:                                hue = acosTable[(int) (-500 * temp - 0.5) + 500];
0775:
0776:                            if (B >= G)
0777:                                dstIntPixels[dIndex++] = (255 - hue) >> bnormh;
0778:                            else
0779:                                dstIntPixels[dIndex++] = hue >> bnormh;
0780:
0781:                            long min = (G > B) ? B : G;
0782:                            min = (R > min) ? min : R;
0783:                            dstIntPixels[dIndex++] = (255 - (int) (255 * min
0784:                                    / intensity + 0.5f)) >> bnorms;
0785:                        } else {
0786:                            float intensity = (R + G + B) / 3.0f;
0787:                            dstPixels[dIndex++] = normi * intensity;
0788:
0789:                            double drg = R - G;
0790:                            double drb = R - B;
0791:                            double temp = Math.sqrt(drg * drg + drb
0792:                                    * (drb - drg));
0793:
0794:                            if (temp != 0) {
0795:                                temp = Math.acos((drg + drb) / temp / 2);
0796:                                if (B >= G)
0797:                                    temp = PI2 - temp;
0798:                            } else
0799:                                temp = PI2;
0800:
0801:                            dstPixels[dIndex++] = normh * temp;
0802:
0803:                            double min = (G > B) ? B : G;
0804:                            min = (R > min) ? min : R;
0805:                            dstPixels[dIndex++] = norms * (1 - min / intensity);
0806:                        }
0807:                    }
0808:                }
0809:
0810:                if (isByte)
0811:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0812:                            height, dstIntPixels);
0813:                else {
0814:                    convertToSigned(dstPixels, dstType);
0815:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0816:                            height, dstPixels);
0817:                }
0818:            }
0819:
0820:            // convert a float type raster from RGB to IHS
0821:            private void fromRGBFloat(UnpackedImageData src,
0822:                    int[] srcComponentSize, WritableRaster dest,
0823:                    int[] destComponentSize) {
0824:                float[] rBuf = src.getFloatData(0);
0825:                float[] gBuf = src.getFloatData(1);
0826:                float[] bBuf = src.getFloatData(2);
0827:
0828:                double normi = 1.0, normh = 1.0, norms = 1.0;
0829:
0830:                int bnormi = 0, bnormh = 0, bnorms = 0;
0831:
0832:                int dstType = dest.getSampleModel().getDataType();
0833:                boolean isByte = (dstType == DataBuffer.TYPE_BYTE);
0834:
0835:                if (isByte) {
0836:                    bnormi = (1 << destComponentSize[0]) - 1;
0837:                    bnormh = 8 - destComponentSize[1];
0838:                    bnorms = 8 - destComponentSize[2];
0839:                    generateACosTable();
0840:                    generateSqrtTable();
0841:                } else if (dstType < DataBuffer.TYPE_FLOAT) {
0842:                    normi = (1l << destComponentSize[0]) - 1;
0843:                    normh = ((1l << destComponentSize[1]) - 1) / PI2;
0844:                    norms = (1l << destComponentSize[2]) - 1;
0845:                }
0846:
0847:                int height = dest.getHeight();
0848:                int width = dest.getWidth();
0849:
0850:                double[] dstPixels = null;
0851:                int[] dstIntPixels = null;
0852:
0853:                if (isByte)
0854:                    dstIntPixels = new int[3 * height * width];
0855:                else
0856:                    dstPixels = new double[3 * height * width];
0857:
0858:                int rStart = src.bandOffsets[0];
0859:                int gStart = src.bandOffsets[1];
0860:                int bStart = src.bandOffsets[2];
0861:                int srcPixelStride = src.pixelStride;
0862:                int srcLineStride = src.lineStride;
0863:
0864:                int dIndex = 0;
0865:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
0866:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
0867:                        float R = rBuf[rIndex];
0868:                        float G = gBuf[gIndex];
0869:                        float B = bBuf[bIndex];
0870:
0871:                        if (isByte) {
0872:                            float intensity = (R + G + B) / 3.0f;
0873:                            dstIntPixels[dIndex++] = (int) (intensity * bnormi + 0.5f);
0874:
0875:                            float drg = R - G;
0876:                            float drb = R - B;
0877:
0878:                            double tint = drg * (double) drg + drb
0879:                                    * (double) (drb - drg);
0880:
0881:                            double sum = drg + drb;
0882:                            double temp;
0883:                            if (tint != 0)
0884:                                temp = sqrtTable[(int) (250.0 * sum * sum
0885:                                        / tint + 0.5)];
0886:                            else
0887:                                temp = -1.0;
0888:
0889:                            int hue;
0890:                            if (sum > 0)
0891:                                hue = acosTable[(int) (500 * temp + 0.5) + 500];
0892:                            else
0893:                                hue = acosTable[(int) (-500 * temp - 0.5) + 500];
0894:
0895:                            if (B >= G)
0896:                                dstIntPixels[dIndex++] = (255 - hue) >> bnormh;
0897:                            else
0898:                                dstIntPixels[dIndex++] = hue >> bnormh;
0899:
0900:                            float min = (G > B) ? B : G;
0901:                            min = (R > min) ? min : R;
0902:                            dstIntPixels[dIndex++] = (255 - (int) (255 * min
0903:                                    / intensity + 0.5f)) >> bnorms;
0904:                        } else {
0905:                            float intensity = (R + G + B) / 3.0f;
0906:                            dstPixels[dIndex++] = normi * intensity;
0907:
0908:                            double drg = R - G;
0909:                            double drb = R - B;
0910:                            double temp = Math.sqrt(drg * drg + drb
0911:                                    * (drb - drg));
0912:
0913:                            if (temp != 0) {
0914:                                temp = Math.acos((drg + drb) / temp / 2);
0915:                                if (B >= G)
0916:                                    temp = PI2 - temp;
0917:                            } else
0918:                                temp = PI2;
0919:
0920:                            dstPixels[dIndex++] = normh * temp;
0921:
0922:                            double min = (G > B) ? B : G;
0923:                            min = (R > min) ? min : R;
0924:                            dstPixels[dIndex++] = norms * (1 - min / intensity);
0925:                        }
0926:                    }
0927:                }
0928:
0929:                if (isByte)
0930:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0931:                            height, dstIntPixels);
0932:                else {
0933:                    convertToSigned(dstPixels, dstType);
0934:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
0935:                            height, dstPixels);
0936:                }
0937:            }
0938:
0939:            // convert a double type raster from RGB to IHS
0940:            private void fromRGBDouble(UnpackedImageData src,
0941:                    int[] srcComponentSize, WritableRaster dest,
0942:                    int[] destComponentSize) {
0943:                double[] rBuf = src.getDoubleData(0);
0944:                double[] gBuf = src.getDoubleData(1);
0945:                double[] bBuf = src.getDoubleData(2);
0946:
0947:                double normi = 1.0, normh = 1.0, norms = 1.0;
0948:
0949:                int bnormi = 0, bnormh = 0, bnorms = 0;
0950:
0951:                int dstType = dest.getSampleModel().getDataType();
0952:                boolean isByte = (dstType == DataBuffer.TYPE_BYTE);
0953:
0954:                if (isByte) {
0955:                    bnormi = (1 << destComponentSize[0]) - 1;
0956:                    bnormh = 8 - destComponentSize[1];
0957:                    bnorms = 8 - destComponentSize[2];
0958:                    generateACosTable();
0959:                    generateSqrtTable();
0960:                } else if (dstType < DataBuffer.TYPE_FLOAT) {
0961:                    normi = (1l << destComponentSize[0]) - 1;
0962:                    normh = ((1l << destComponentSize[1]) - 1) / PI2;
0963:                    norms = (1l << destComponentSize[2]) - 1;
0964:                }
0965:
0966:                int height = dest.getHeight();
0967:                int width = dest.getWidth();
0968:
0969:                double[] dstPixels = null;
0970:                int[] dstIntPixels = null;
0971:
0972:                if (isByte)
0973:                    dstIntPixels = new int[3 * height * width];
0974:                else
0975:                    dstPixels = new double[3 * height * width];
0976:
0977:                int rStart = src.bandOffsets[0];
0978:                int gStart = src.bandOffsets[1];
0979:                int bStart = src.bandOffsets[2];
0980:                int srcPixelStride = src.pixelStride;
0981:                int srcLineStride = src.lineStride;
0982:
0983:                int dIndex = 0;
0984:                for (int j = 0; j < height; j++, rStart += srcLineStride, gStart += srcLineStride, bStart += srcLineStride) {
0985:                    for (int i = 0, rIndex = rStart, gIndex = gStart, bIndex = bStart; i < width; i++, rIndex += srcPixelStride, gIndex += srcPixelStride, bIndex += srcPixelStride) {
0986:                        double R = rBuf[rIndex];
0987:                        double G = gBuf[gIndex];
0988:                        double B = bBuf[bIndex];
0989:
0990:                        if (isByte) {
0991:                            double intensity = (R + G + B) / 3.0f;
0992:                            dstIntPixels[dIndex++] = (int) (intensity * bnormi + 0.5);
0993:
0994:                            double drg = R - G;
0995:                            double drb = R - B;
0996:
0997:                            double tint = drg * drg + drb * (drb - drg);
0998:
0999:                            double sum = drg + drb;
1000:                            double temp;
1001:                            if (tint != 0.0)
1002:                                temp = sqrtTable[(int) (250.0 * sum * sum
1003:                                        / tint + 0.5)];
1004:                            else
1005:                                temp = -1.0;
1006:
1007:                            int hue;
1008:                            if (sum > 0)
1009:                                hue = acosTable[(int) (500 * temp + 0.5) + 500];
1010:                            else
1011:                                hue = acosTable[(int) (-500 * temp - 0.5) + 500];
1012:
1013:                            if (B >= G)
1014:                                dstIntPixels[dIndex++] = (255 - hue) >> bnormh;
1015:                            else
1016:                                dstIntPixels[dIndex++] = hue >> bnormh;
1017:
1018:                            double min = (G > B) ? B : G;
1019:                            min = (R > min) ? min : R;
1020:                            dstIntPixels[dIndex++] = (255 - (int) (255 * min
1021:                                    / intensity + 0.5f)) >> bnorms;
1022:                        } else {
1023:                            double intensity = (R + G + B) / 3.0f;
1024:                            dstPixels[dIndex++] = normi * intensity;
1025:
1026:                            double drg = R - G;
1027:                            double drb = R - B;
1028:                            double temp = Math.sqrt(drg * drg + drb
1029:                                    * (drb - drg));
1030:
1031:                            if (temp != 0) {
1032:                                temp = Math.acos((drg + drb) / temp / 2);
1033:                                if (B >= G)
1034:                                    temp = PI2 - temp;
1035:                            } else
1036:                                temp = PI2;
1037:
1038:                            dstPixels[dIndex++] = normh * temp;
1039:
1040:                            double min = (G > B) ? B : G;
1041:                            min = (R > min) ? min : R;
1042:                            dstPixels[dIndex++] = norms * (1 - min / intensity);
1043:                        }
1044:                    }
1045:                }
1046:                if (isByte)
1047:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
1048:                            height, dstIntPixels);
1049:                else {
1050:                    convertToSigned(dstPixels, dstType);
1051:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
1052:                            height, dstPixels);
1053:                }
1054:            }
1055:
1056:            /**
1057:             * Converts a <code>Raster</code> of colors represented as pixels
1058:             * from IHS to CIEXYZ.
1059:             */
1060:            public WritableRaster toCIEXYZ(Raster src, int[] srcComponentSize,
1061:                    WritableRaster dest, int[] destComponentSize) {
1062:                WritableRaster tempRas = toRGB(src, srcComponentSize, null,
1063:                        null);
1064:                return RGBToCIEXYZ(tempRas, tempRas.getSampleModel()
1065:                        .getSampleSize(), dest, destComponentSize);
1066:            }
1067:
1068:            /**
1069:             * Converts a <code>Raster</code> of colors represented as pixels
1070:             * from IHS to sRGB.
1071:             */
1072:            public WritableRaster toRGB(Raster src, int[] srcComponentSize,
1073:                    WritableRaster dest, int[] destComponentSize) {
1074:
1075:                checkParameters(src, srcComponentSize, dest, destComponentSize);
1076:
1077:                SampleModel srcSampleModel = src.getSampleModel();
1078:
1079:                if (srcComponentSize == null)
1080:                    srcComponentSize = srcSampleModel.getSampleSize();
1081:
1082:                if (dest == null) {
1083:                    Point origin = new Point(src.getMinX(), src.getMinY());
1084:                    dest = RasterFactory.createWritableRaster(srcSampleModel,
1085:                            origin);
1086:                }
1087:
1088:                SampleModel dstSampleModel = dest.getSampleModel();
1089:                if (destComponentSize == null)
1090:                    destComponentSize = dstSampleModel.getSampleSize();
1091:
1092:                PixelAccessor srcAcc = new PixelAccessor(srcSampleModel, null);
1093:                UnpackedImageData srcUid = srcAcc.getPixels(src, src
1094:                        .getBounds(), srcSampleModel.getDataType(), false);
1095:
1096:                switch (srcSampleModel.getDataType()) {
1097:
1098:                case DataBuffer.TYPE_BYTE:
1099:                    toRGBByte(srcUid, srcComponentSize, dest, destComponentSize);
1100:                    break;
1101:                case DataBuffer.TYPE_USHORT:
1102:                case DataBuffer.TYPE_SHORT:
1103:                    toRGBShort(srcUid, srcComponentSize, dest,
1104:                            destComponentSize);
1105:                    break;
1106:                case DataBuffer.TYPE_INT:
1107:                    toRGBInt(srcUid, srcComponentSize, dest, destComponentSize);
1108:                    break;
1109:                case DataBuffer.TYPE_FLOAT:
1110:                    toRGBFloat(srcUid, srcComponentSize, dest,
1111:                            destComponentSize);
1112:                    break;
1113:                case DataBuffer.TYPE_DOUBLE:
1114:                    toRGBDouble(srcUid, srcComponentSize, dest,
1115:                            destComponentSize);
1116:                    break;
1117:                }
1118:                return dest;
1119:            }
1120:
1121:            // convert a byte type raster from IHS to RGB
1122:            private void toRGBByte(UnpackedImageData src,
1123:                    int[] srcComponentSize, WritableRaster dest,
1124:                    int[] destComponentSize) {
1125:                byte[] iBuf = src.getByteData(0);
1126:                byte[] hBuf = src.getByteData(1);
1127:                byte[] sBuf = src.getByteData(2);
1128:
1129:                double normi = 1.0 / ((1 << srcComponentSize[0]) - 1);
1130:                double normh = 1.0 / ((1 << srcComponentSize[1]) - 1) * PI2;
1131:                double norms = 1.0 / ((1 << srcComponentSize[2]) - 1);
1132:
1133:                double normr = 1.0, normg = 1.0, normb = 1.0;
1134:
1135:                int dstType = dest.getSampleModel().getDataType();
1136:                boolean isByte = (dstType == DataBuffer.TYPE_BYTE);
1137:
1138:                if (isByte) {
1139:                    generateTanTable();
1140:                }
1141:                if (dstType < DataBuffer.TYPE_FLOAT) {
1142:                    normr = (1l << destComponentSize[0]) - 1;
1143:                    normg = (1l << destComponentSize[1]) - 1;
1144:                    normb = (1l << destComponentSize[2]) - 1;
1145:                }
1146:
1147:                int height = dest.getHeight();
1148:                int width = dest.getWidth();
1149:
1150:                double[] dstPixels = null;
1151:                int[] dstIntPixels = null;
1152:
1153:                if (isByte)
1154:                    dstIntPixels = new int[3 * height * width];
1155:                else
1156:                    dstPixels = new double[3 * height * width];
1157:
1158:                int iStart = src.bandOffsets[0];
1159:                int hStart = src.bandOffsets[1];
1160:                int sStart = src.bandOffsets[2];
1161:                int srcPixelStride = src.pixelStride;
1162:                int srcLineStride = src.lineStride;
1163:
1164:                int dIndex = 0;
1165:                for (int j = 0; j < height; j++, iStart += srcLineStride, hStart += srcLineStride, sStart += srcLineStride) {
1166:                    for (int i = 0, iIndex = iStart, hIndex = hStart, sIndex = sStart; i < width; i++, iIndex += srcPixelStride, hIndex += srcPixelStride, sIndex += srcPixelStride) {
1167:                        double I = (iBuf[iIndex] & 0xFF) * normi;
1168:                        int h = hBuf[hIndex] & 0xFF;
1169:                        double S = (sBuf[sIndex] & 0xFF) * norms;
1170:
1171:                        if (isByte) {
1172:                            float r, g, b;
1173:
1174:                            r = g = b = (float) I;
1175:
1176:                            if (S != 0.0) {
1177:                                if (h >= 85 && h <= 170) {
1178:                                    r = (float) ((1 - S) * I);
1179:                                    float c1 = (float) (3 * I - r);
1180:                                    float c2 = (float) (SQRT3 * (r - I) * tanTable[h]);
1181:                                    g = (float) ((c1 + c2) / 2);
1182:                                    b = (float) ((c1 - c2) / 2);
1183:                                } else if (h > 170) {
1184:                                    g = (float) ((1 - S) * I);
1185:                                    float c1 = (float) (3 * I - g);
1186:                                    float c2 = (float) (SQRT3 * (g - I) * tanTable[h - 85]);
1187:                                    b = (c1 + c2) / 2;
1188:                                    r = (c1 - c2) / 2;
1189:                                } else if (h < 85) {
1190:                                    b = (float) ((1 - S) * I);
1191:                                    float c1 = (float) (3 * I - b);
1192:                                    float c2 = (float) (SQRT3 * (b - I) * tanTable[h + 85]);
1193:                                    r = (c1 + c2) / 2;
1194:                                    g = (c1 - c2) / 2;
1195:                                }
1196:                            }
1197:                            dstIntPixels[dIndex++] = (int) (((r < 0.0f) ? 0.0f
1198:                                    : ((r > 1.0f) ? 1.0f : r))
1199:                                    * normr + 0.5);
1200:                            dstIntPixels[dIndex++] = (int) (((g < 0.0f) ? 0.0f
1201:                                    : ((g > 1.0f) ? 1.0f : g))
1202:                                    * normg + 0.5);
1203:                            dstIntPixels[dIndex++] = (int) (((b < 0.0f) ? 0.0f
1204:                                    : ((b > 1.0f) ? 1.0f : b))
1205:                                    * normb + 0.5);
1206:                        } else {
1207:                            double R, G, B;
1208:
1209:                            R = G = B = I;
1210:                            if (S != 0) {
1211:                                double H = h * normh;
1212:                                if (H >= PI23 && H <= PI43) {
1213:                                    R = (1 - S) * I;
1214:                                    double c1 = 3 * I - R;
1215:                                    double c2 = SQRT3 * (R - I) * Math.tan(H);
1216:                                    G = (c1 + c2) / 2;
1217:                                    B = (c1 - c2) / 2;
1218:                                } else if (H > PI43) {
1219:                                    G = (1 - S) * I;
1220:                                    double c1 = 3 * I - G;
1221:                                    double c2 = SQRT3 * (G - I)
1222:                                            * Math.tan(H - PI23);
1223:                                    B = (c1 + c2) / 2;
1224:                                    R = (c1 - c2) / 2;
1225:                                } else if (H < PI23) {
1226:                                    B = (1 - S) * I;
1227:                                    double c1 = 3 * I - B;
1228:                                    double c2 = SQRT3 * (B - I)
1229:                                            * Math.tan(H - PI43);
1230:                                    R = (c1 + c2) / 2;
1231:                                    G = (c1 - c2) / 2;
1232:                                }
1233:                            }
1234:                            dstPixels[dIndex++] = ((R < 0) ? 0
1235:                                    : ((R > 1.0) ? 1.0 : R))
1236:                                    * normr;
1237:                            dstPixels[dIndex++] = ((G < 0) ? 0
1238:                                    : ((G > 1.0) ? 1.0 : G))
1239:                                    * normg;
1240:                            dstPixels[dIndex++] = ((B < 0) ? 0
1241:                                    : ((B > 1.0) ? 1.0 : B))
1242:                                    * normb;
1243:                        }
1244:                    }
1245:                }
1246:
1247:                if (isByte)
1248:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
1249:                            height, dstIntPixels);
1250:                else {
1251:                    convertToSigned(dstPixels, dstType);
1252:                    dest.setPixels(dest.getMinX(), dest.getMinY(), width,
1253:                            height, dstPixels);
1254:                }
1255:
1256:            }
1257:
1258:            // convert a short type ratser from IHS to RGB
1259:            private void toRGBShort(UnpackedImageData src,
1260:                    int[] srcComponentSize, WritableRaster dest,
1261:                    int[] destComponentSize) {
1262:                short[] iBuf = src.getShortData(0);
1263:                short[] hBuf = src.getShortData(1);
1264:                short[] sBuf = src.getShortData(2);
1265:
1266:                double normi = 1.0 / ((1 << srcComponentSize[0]) - 1);
1267:                double normh = 1.0 / ((1 << srcComponentSize[1]) - 1) * PI2;
1268:                double norms = 1.0 / ((1 << srcComponentSize[2]) - 1);
1269:
1270:                double normr = 1.0, normg = 1.0, normb = 1.0;
1271:
1272:                int dstType = dest.getSampleModel().getDataType();
1273:
1274:                if (dstType < DataBuffer.TYPE_FLOAT) {
1275:                    normr = (1l << destComponentSize[0]) - 1;
1276:                    normg = (1l << destComponentSize[1]) - 1;
1277:                    normb = (1l << destComponentSize[2]) - 1;
1278:                }
1279:
1280:                int height = dest.getHeight();
1281:                int width = dest.getWidth();
1282:
1283:                double[] dstPixels = new double[3 * height * width];
1284:
1285:                int iStart = src.bandOffsets[0];
1286:                int hStart = src.bandOffsets[1];
1287:                int sStart = src.bandOffsets[2];
1288:                int srcPixelStride = src.pixelStride;
1289:                int srcLineStride = src.lineStride;
1290:
1291:                int dIndex = 0;
1292:                for (int j = 0; j < height; j++, iStart += srcLineStride, hStart += srcLineStride, sStart += srcLineStride) {
1293:                    for (int i = 0, iIndex = iStart, hIndex = hStart, sIndex = sStart; i < width; i++, iIndex += srcPixelStride, hIndex += srcPixelStride, sIndex += srcPixelStride) {
1294:                        double I = (iBuf[iIndex] & 0xFFFF) * normi;
1295:                        double H = (hBuf[hIndex] & 0xFFFF) * normh;
1296:                        double S = (sBuf[sIndex] & 0xFFFF) * norms;
1297:                        double R, G, B;
1298:
1299:                        R = G = B = I;
1300:                        if (S != 0.0) {
1301:                            if (H >= PI23 && H <= PI43) {
1302:                                R = (1 - S) * I;
1303:                                double c1 = 3 * I - R;
1304:                                double c2 = SQRT3 * (R - I) * Math.tan(H);
1305:                                G = (c1 + c2) / 2;
1306:                                B = (c1 - c2) / 2;
1307:                            } else if (H > PI43) {
1308:                                G = (1 - S) * I;
1309:                                double c1 = 3 * I - G;
1310:                                double c2 = SQRT3 * (G - I)
1311:                                        * Math.tan(H - PI23);
1312:                                B = (c1 + c2) / 2;
1313:                                R = (c1 - c2) / 2;
1314:                            } else if (H < PI23) {
1315:                                B = (1 - S) * I;
1316:                                double c1 = 3 * I - B;
1317:                                double c2 = SQRT3 * (B - I)
1318:                                        * Math.tan(H - PI43);
1319:                                R = (c1 + c2) / 2;
1320:                                G = (c1 - c2) / 2;
1321:                            }
1322:                        }
1323:
1324:                        dstPixels[dIndex++] = ((R < 0) ? 0 : ((R > 1.0) ? 1.0
1325:                                : R))
1326:                                * normr;
1327:                        dstPixels[dIndex++] = ((G < 0) ? 0 : ((G > 1.0) ? 1.0
1328:                                : G))
1329:                                * normg;
1330:                        dstPixels[dIndex++] = ((B < 0) ? 0 : ((B > 1.0) ? 1.0
1331:                                : B))
1332:                                * normb;
1333:                    }
1334:                }
1335:
1336:                convertToSigned(dstPixels, dstType);
1337:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1338:                        dstPixels);
1339:            }
1340:
1341:            private void toRGBInt(UnpackedImageData src,
1342:                    int[] srcComponentSize, WritableRaster dest,
1343:                    int[] destComponentSize) {
1344:                int[] iBuf = src.getIntData(0);
1345:                int[] hBuf = src.getIntData(1);
1346:                int[] sBuf = src.getIntData(2);
1347:
1348:                double normi = 1.0 / ((1l << srcComponentSize[0]) - 1);
1349:                double normh = 1.0 / ((1l << srcComponentSize[1]) - 1) * PI2;
1350:                double norms = 1.0 / ((1l << srcComponentSize[2]) - 1);
1351:
1352:                double normr = 1.0, normg = 1.0, normb = 1.0;
1353:
1354:                int dstType = dest.getSampleModel().getDataType();
1355:
1356:                if (dstType < DataBuffer.TYPE_FLOAT) {
1357:                    normr = (1l << destComponentSize[0]) - 1;
1358:                    normg = (1l << destComponentSize[1]) - 1;
1359:                    normb = (1l << destComponentSize[2]) - 1;
1360:                }
1361:
1362:                int height = dest.getHeight();
1363:                int width = dest.getWidth();
1364:
1365:                double[] dstPixels = new double[3 * height * width];
1366:
1367:                int iStart = src.bandOffsets[0];
1368:                int hStart = src.bandOffsets[1];
1369:                int sStart = src.bandOffsets[2];
1370:                int srcPixelStride = src.pixelStride;
1371:                int srcLineStride = src.lineStride;
1372:
1373:                int dIndex = 0;
1374:                for (int j = 0; j < height; j++, iStart += srcLineStride, hStart += srcLineStride, sStart += srcLineStride) {
1375:                    for (int i = 0, iIndex = iStart, hIndex = hStart, sIndex = sStart; i < width; i++, iIndex += srcPixelStride, hIndex += srcPixelStride, sIndex += srcPixelStride) {
1376:                        double I = (iBuf[iIndex] & 0xFFFFFFFFl) * normi;
1377:                        double H = (hBuf[hIndex] & 0xFFFFFFFFl) * normh;
1378:                        double S = (sBuf[sIndex] & 0xFFFFFFFFl) * norms;
1379:
1380:                        double R, G, B;
1381:
1382:                        R = G = B = I;
1383:                        if (S != 0) {
1384:                            if (H >= PI23 && H <= PI43) {
1385:                                R = (1 - S) * I;
1386:                                double c1 = 3 * I - R;
1387:                                double c2 = SQRT3 * (R - I) * Math.tan(H);
1388:                                G = (c1 + c2) / 2;
1389:                                B = (c1 - c2) / 2;
1390:                            } else if (H > PI43) {
1391:                                G = (1 - S) * I;
1392:                                double c1 = 3 * I - G;
1393:                                double c2 = SQRT3 * (G - I)
1394:                                        * Math.tan(H - PI23);
1395:                                B = (c1 + c2) / 2;
1396:                                R = (c1 - c2) / 2;
1397:                            } else if (H < PI23) {
1398:                                B = (1 - S) * I;
1399:                                double c1 = 3 * I - B;
1400:                                double c2 = SQRT3 * (B - I)
1401:                                        * Math.tan(H - PI43);
1402:                                R = (c1 + c2) / 2;
1403:                                G = (c1 - c2) / 2;
1404:                            }
1405:                        }
1406:
1407:                        dstPixels[dIndex++] = ((R < 0) ? 0 : ((R > 1.0) ? 1.0
1408:                                : R))
1409:                                * normr;
1410:                        dstPixels[dIndex++] = ((G < 0) ? 0 : ((G > 1.0) ? 1.0
1411:                                : G))
1412:                                * normg;
1413:                        dstPixels[dIndex++] = ((B < 0) ? 0 : ((B > 1.0) ? 1.0
1414:                                : B))
1415:                                * normb;
1416:                    }
1417:                }
1418:                convertToSigned(dstPixels, dstType);
1419:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1420:                        dstPixels);
1421:            }
1422:
1423:            private void toRGBFloat(UnpackedImageData src,
1424:                    int[] srcComponentSize, WritableRaster dest,
1425:                    int[] destComponentSize) {
1426:                float[] iBuf = src.getFloatData(0);
1427:                float[] hBuf = src.getFloatData(1);
1428:                float[] sBuf = src.getFloatData(2);
1429:
1430:                double normr = 1.0, normg = 1.0, normb = 1.0;
1431:
1432:                int dstType = dest.getSampleModel().getDataType();
1433:
1434:                if (dstType < DataBuffer.TYPE_FLOAT) {
1435:                    normr = (1l << destComponentSize[0]) - 1;
1436:                    normg = (1l << destComponentSize[1]) - 1;
1437:                    normb = (1l << destComponentSize[2]) - 1;
1438:                }
1439:
1440:                int height = dest.getHeight();
1441:                int width = dest.getWidth();
1442:
1443:                double[] dstPixels = new double[3 * height * width];
1444:
1445:                int iStart = src.bandOffsets[0];
1446:                int hStart = src.bandOffsets[1];
1447:                int sStart = src.bandOffsets[2];
1448:                int srcPixelStride = src.pixelStride;
1449:                int srcLineStride = src.lineStride;
1450:
1451:                int dIndex = 0;
1452:                for (int j = 0; j < height; j++, iStart += srcLineStride, hStart += srcLineStride, sStart += srcLineStride) {
1453:                    for (int i = 0, iIndex = iStart, hIndex = hStart, sIndex = sStart; i < width; i++, iIndex += srcPixelStride, hIndex += srcPixelStride, sIndex += srcPixelStride) {
1454:                        double I = iBuf[iIndex];
1455:                        double H = hBuf[hIndex];
1456:                        double S = sBuf[sIndex];
1457:                        double R, G, B;
1458:
1459:                        R = G = B = I;
1460:                        if (S != 0) {
1461:                            if (H >= PI23 && H <= PI43) {
1462:                                R = (1 - S) * I;
1463:                                double c1 = 3 * I - R;
1464:                                double c2 = SQRT3 * (R - I) * Math.tan(H);
1465:                                G = (c1 + c2) / 2;
1466:                                B = (c1 - c2) / 2;
1467:                            } else if (H > PI43) {
1468:                                G = (1 - S) * I;
1469:                                double c1 = 3 * I - G;
1470:                                double c2 = SQRT3 * (G - I)
1471:                                        * Math.tan(H - PI23);
1472:                                B = (c1 + c2) / 2;
1473:                                R = (c1 - c2) / 2;
1474:                            } else if (H < PI23) {
1475:                                B = (1 - S) * I;
1476:                                double c1 = 3 * I - B;
1477:                                double c2 = SQRT3 * (B - I)
1478:                                        * Math.tan(H - PI43);
1479:                                R = (c1 + c2) / 2;
1480:                                G = (c1 - c2) / 2;
1481:                            }
1482:                        }
1483:
1484:                        dstPixels[dIndex++] = ((R < 0) ? 0 : ((R > 1.0) ? 1.0
1485:                                : R))
1486:                                * normr;
1487:                        dstPixels[dIndex++] = ((G < 0) ? 0 : ((G > 1.0) ? 1.0
1488:                                : G))
1489:                                * normg;
1490:                        dstPixels[dIndex++] = ((B < 0) ? 0 : ((B > 1.0) ? 1.0
1491:                                : B))
1492:                                * normb;
1493:                    }
1494:                }
1495:                convertToSigned(dstPixels, dstType);
1496:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1497:                        dstPixels);
1498:            }
1499:
1500:            private void toRGBDouble(UnpackedImageData src,
1501:                    int[] srcComponentSize, WritableRaster dest,
1502:                    int[] destComponentSize) {
1503:                double[] iBuf = src.getDoubleData(0);
1504:                double[] hBuf = src.getDoubleData(1);
1505:                double[] sBuf = src.getDoubleData(2);
1506:
1507:                double normr = 1.0, normg = 1.0, normb = 1.0;
1508:
1509:                int dstType = dest.getSampleModel().getDataType();
1510:
1511:                if (dstType < DataBuffer.TYPE_FLOAT) {
1512:                    normr = (1l << destComponentSize[0]) - 1;
1513:                    normg = (1l << destComponentSize[1]) - 1;
1514:                    normb = (1l << destComponentSize[2]) - 1;
1515:                }
1516:
1517:                int height = dest.getHeight();
1518:                int width = dest.getWidth();
1519:
1520:                double[] dstPixels = new double[3 * height * width];
1521:
1522:                int iStart = src.bandOffsets[0];
1523:                int hStart = src.bandOffsets[1];
1524:                int sStart = src.bandOffsets[2];
1525:                int srcPixelStride = src.pixelStride;
1526:                int srcLineStride = src.lineStride;
1527:
1528:                int dIndex = 0;
1529:                for (int j = 0; j < height; j++, iStart += srcLineStride, hStart += srcLineStride, sStart += srcLineStride) {
1530:                    for (int i = 0, iIndex = iStart, hIndex = hStart, sIndex = sStart; i < width; i++, iIndex += srcPixelStride, hIndex += srcPixelStride, sIndex += srcPixelStride) {
1531:                        double I = iBuf[iIndex];
1532:                        double H = hBuf[hIndex];
1533:                        double S = sBuf[sIndex];
1534:
1535:                        double R, G, B;
1536:
1537:                        R = G = B = I;
1538:                        if (S != 0) {
1539:                            if (H >= PI23 && H <= PI43) {
1540:                                R = (1 - S) * I;
1541:                                double c1 = 3 * I - R;
1542:                                double c2 = SQRT3 * (R - I) * Math.tan(H);
1543:                                G = (c1 + c2) / 2;
1544:                                B = (c1 - c2) / 2;
1545:                            } else if (H > PI43) {
1546:                                G = (1 - S) * I;
1547:                                double c1 = 3 * I - G;
1548:                                double c2 = SQRT3 * (G - I)
1549:                                        * Math.tan(H - PI23);
1550:                                B = (c1 + c2) / 2;
1551:                                R = (c1 - c2) / 2;
1552:                            } else if (H < PI23) {
1553:                                B = (1 - S) * I;
1554:                                double c1 = 3 * I - B;
1555:                                double c2 = SQRT3 * (B - I)
1556:                                        * Math.tan(H - PI43);
1557:                                R = (c1 + c2) / 2;
1558:                                G = (c1 - c2) / 2;
1559:                            }
1560:                        }
1561:
1562:                        dstPixels[dIndex++] = ((R < 0) ? 0 : ((R > 1.0) ? 1.0
1563:                                : R))
1564:                                * normr;
1565:                        dstPixels[dIndex++] = ((G < 0) ? 0 : ((G > 1.0) ? 1.0
1566:                                : G))
1567:                                * normg;
1568:                        dstPixels[dIndex++] = ((B < 0) ? 0 : ((B > 1.0) ? 1.0
1569:                                : B))
1570:                                * normb;
1571:                    }
1572:                }
1573:                convertToSigned(dstPixels, dstType);
1574:                dest.setPixels(dest.getMinX(), dest.getMinY(), width, height,
1575:                        dstPixels);
1576:            }
1577:
1578:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.