1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 ********************************************************************** 28 ********************************************************************** 29 ********************************************************************** 30 *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** 31 *** As an unpublished work pursuant to Title 17 of the United *** 32 *** States Code. All rights reserved. *** 33 ********************************************************************** 34 ********************************************************************** 35 **********************************************************************/ 36 37 package java.awt.color; 38 39 import sun.java2d.cmm.PCMM; 40 import sun.java2d.cmm.CMSManager; 41 import sun.java2d.cmm.Profile; 42 import sun.java2d.cmm.ProfileDataVerifier; 43 import sun.java2d.cmm.ProfileDeferralMgr; 44 import sun.java2d.cmm.ProfileDeferralInfo; 45 import sun.java2d.cmm.ProfileActivator; 46 47 import java.io.File; 48 import java.io.FileInputStream; 49 import java.io.FileNotFoundException; 50 import java.io.FileOutputStream; 51 import java.io.FilePermission; 52 import java.io.IOException; 53 import java.io.InputStream; 54 import java.io.ObjectInputStream; 55 import java.io.ObjectOutputStream; 56 import java.io.ObjectStreamException; 57 import java.io.OutputStream; 58 import java.io.Serializable; 59 60 import java.util.StringTokenizer; 61 62 import java.security.AccessController; 63 import java.security.PrivilegedAction; 64 65 66 /** 67 * A representation of color profile data for device independent and 68 * device dependent color spaces based on the International Color 69 * Consortium Specification ICC.1:2001-12, File Format for Color Profiles, 70 * (see <A href="http://www.color.org"> http://www.color.org</A>). 71 * <p> 72 * An ICC_ColorSpace object can be constructed from an appropriate 73 * ICC_Profile. 74 * Typically, an ICC_ColorSpace would be associated with an ICC 75 * Profile which is either an input, display, or output profile (see 76 * the ICC specification). There are also device link, abstract, 77 * color space conversion, and named color profiles. These are less 78 * useful for tagging a color or image, but are useful for other 79 * purposes (in particular device link profiles can provide improved 80 * performance for converting from one device's color space to 81 * another's). 82 * <p> 83 * ICC Profiles represent transformations from the color space of 84 * the profile (e.g. a monitor) to a Profile Connection Space (PCS). 85 * Profiles of interest for tagging images or colors have a PCS 86 * which is one of the two specific device independent 87 * spaces (one CIEXYZ space and one CIELab space) defined in the 88 * ICC Profile Format Specification. Most profiles of interest 89 * either have invertible transformations or explicitly specify 90 * transformations going both directions. 91 * @see ICC_ColorSpace 92 */ 93 94 95 public class ICC_Profile implements Serializable { 96 97 private static final long serialVersionUID = -3938515861990936766L; 98 99 private transient Profile cmmProfile; 100 101 private transient ProfileDeferralInfo deferralInfo; 102 private transient ProfileActivator profileActivator; 103 104 // Registry of singleton profile objects for specific color spaces 105 // defined in the ColorSpace class (e.g. CS_sRGB), see 106 // getInstance(int cspace) factory method. 107 private static ICC_Profile sRGBprofile; 108 private static ICC_Profile XYZprofile; 109 private static ICC_Profile PYCCprofile; 110 private static ICC_Profile GRAYprofile; 111 private static ICC_Profile LINEAR_RGBprofile; 112 113 114 /** 115 * Profile class is input. 116 */ 117 public static final int CLASS_INPUT = 0; 118 119 /** 120 * Profile class is display. 121 */ 122 public static final int CLASS_DISPLAY = 1; 123 124 /** 125 * Profile class is output. 126 */ 127 public static final int CLASS_OUTPUT = 2; 128 129 /** 130 * Profile class is device link. 131 */ 132 public static final int CLASS_DEVICELINK = 3; 133 134 /** 135 * Profile class is color space conversion. 136 */ 137 public static final int CLASS_COLORSPACECONVERSION = 4; 138 139 /** 140 * Profile class is abstract. 141 */ 142 public static final int CLASS_ABSTRACT = 5; 143 144 /** 145 * Profile class is named color. 146 */ 147 public static final int CLASS_NAMEDCOLOR = 6; 148 149 150 /** 151 * ICC Profile Color Space Type Signature: 'XYZ '. 152 */ 153 public static final int icSigXYZData = 0x58595A20; /* 'XYZ ' */ 154 155 /** 156 * ICC Profile Color Space Type Signature: 'Lab '. 157 */ 158 public static final int icSigLabData = 0x4C616220; /* 'Lab ' */ 159 160 /** 161 * ICC Profile Color Space Type Signature: 'Luv '. 162 */ 163 public static final int icSigLuvData = 0x4C757620; /* 'Luv ' */ 164 165 /** 166 * ICC Profile Color Space Type Signature: 'YCbr'. 167 */ 168 public static final int icSigYCbCrData = 0x59436272; /* 'YCbr' */ 169 170 /** 171 * ICC Profile Color Space Type Signature: 'Yxy '. 172 */ 173 public static final int icSigYxyData = 0x59787920; /* 'Yxy ' */ 174 175 /** 176 * ICC Profile Color Space Type Signature: 'RGB '. 177 */ 178 public static final int icSigRgbData = 0x52474220; /* 'RGB ' */ 179 180 /** 181 * ICC Profile Color Space Type Signature: 'GRAY'. 182 */ 183 public static final int icSigGrayData = 0x47524159; /* 'GRAY' */ 184 185 /** 186 * ICC Profile Color Space Type Signature: 'HSV'. 187 */ 188 public static final int icSigHsvData = 0x48535620; /* 'HSV ' */ 189 190 /** 191 * ICC Profile Color Space Type Signature: 'HLS'. 192 */ 193 public static final int icSigHlsData = 0x484C5320; /* 'HLS ' */ 194 195 /** 196 * ICC Profile Color Space Type Signature: 'CMYK'. 197 */ 198 public static final int icSigCmykData = 0x434D594B; /* 'CMYK' */ 199 200 /** 201 * ICC Profile Color Space Type Signature: 'CMY '. 202 */ 203 public static final int icSigCmyData = 0x434D5920; /* 'CMY ' */ 204 205 /** 206 * ICC Profile Color Space Type Signature: '2CLR'. 207 */ 208 public static final int icSigSpace2CLR = 0x32434C52; /* '2CLR' */ 209 210 /** 211 * ICC Profile Color Space Type Signature: '3CLR'. 212 */ 213 public static final int icSigSpace3CLR = 0x33434C52; /* '3CLR' */ 214 215 /** 216 * ICC Profile Color Space Type Signature: '4CLR'. 217 */ 218 public static final int icSigSpace4CLR = 0x34434C52; /* '4CLR' */ 219 220 /** 221 * ICC Profile Color Space Type Signature: '5CLR'. 222 */ 223 public static final int icSigSpace5CLR = 0x35434C52; /* '5CLR' */ 224 225 /** 226 * ICC Profile Color Space Type Signature: '6CLR'. 227 */ 228 public static final int icSigSpace6CLR = 0x36434C52; /* '6CLR' */ 229 230 /** 231 * ICC Profile Color Space Type Signature: '7CLR'. 232 */ 233 public static final int icSigSpace7CLR = 0x37434C52; /* '7CLR' */ 234 235 /** 236 * ICC Profile Color Space Type Signature: '8CLR'. 237 */ 238 public static final int icSigSpace8CLR = 0x38434C52; /* '8CLR' */ 239 240 /** 241 * ICC Profile Color Space Type Signature: '9CLR'. 242 */ 243 public static final int icSigSpace9CLR = 0x39434C52; /* '9CLR' */ 244 245 /** 246 * ICC Profile Color Space Type Signature: 'ACLR'. 247 */ 248 public static final int icSigSpaceACLR = 0x41434C52; /* 'ACLR' */ 249 250 /** 251 * ICC Profile Color Space Type Signature: 'BCLR'. 252 */ 253 public static final int icSigSpaceBCLR = 0x42434C52; /* 'BCLR' */ 254 255 /** 256 * ICC Profile Color Space Type Signature: 'CCLR'. 257 */ 258 public static final int icSigSpaceCCLR = 0x43434C52; /* 'CCLR' */ 259 260 /** 261 * ICC Profile Color Space Type Signature: 'DCLR'. 262 */ 263 public static final int icSigSpaceDCLR = 0x44434C52; /* 'DCLR' */ 264 265 /** 266 * ICC Profile Color Space Type Signature: 'ECLR'. 267 */ 268 public static final int icSigSpaceECLR = 0x45434C52; /* 'ECLR' */ 269 270 /** 271 * ICC Profile Color Space Type Signature: 'FCLR'. 272 */ 273 public static final int icSigSpaceFCLR = 0x46434C52; /* 'FCLR' */ 274 275 276 /** 277 * ICC Profile Class Signature: 'scnr'. 278 */ 279 public static final int icSigInputClass = 0x73636E72; /* 'scnr' */ 280 281 /** 282 * ICC Profile Class Signature: 'mntr'. 283 */ 284 public static final int icSigDisplayClass = 0x6D6E7472; /* 'mntr' */ 285 286 /** 287 * ICC Profile Class Signature: 'prtr'. 288 */ 289 public static final int icSigOutputClass = 0x70727472; /* 'prtr' */ 290 291 /** 292 * ICC Profile Class Signature: 'link'. 293 */ 294 public static final int icSigLinkClass = 0x6C696E6B; /* 'link' */ 295 296 /** 297 * ICC Profile Class Signature: 'abst'. 298 */ 299 public static final int icSigAbstractClass = 0x61627374; /* 'abst' */ 300 301 /** 302 * ICC Profile Class Signature: 'spac'. 303 */ 304 public static final int icSigColorSpaceClass = 0x73706163; /* 'spac' */ 305 306 /** 307 * ICC Profile Class Signature: 'nmcl'. 308 */ 309 public static final int icSigNamedColorClass = 0x6e6d636c; /* 'nmcl' */ 310 311 312 /** 313 * ICC Profile Rendering Intent: Perceptual. 314 */ 315 public static final int icPerceptual = 0; 316 317 /** 318 * ICC Profile Rendering Intent: RelativeColorimetric. 319 */ 320 public static final int icRelativeColorimetric = 1; 321 322 /** 323 * ICC Profile Rendering Intent: Media-RelativeColorimetric. 324 * @since 1.5 325 */ 326 public static final int icMediaRelativeColorimetric = 1; 327 328 /** 329 * ICC Profile Rendering Intent: Saturation. 330 */ 331 public static final int icSaturation = 2; 332 333 /** 334 * ICC Profile Rendering Intent: AbsoluteColorimetric. 335 */ 336 public static final int icAbsoluteColorimetric = 3; 337 338 /** 339 * ICC Profile Rendering Intent: ICC-AbsoluteColorimetric. 340 * @since 1.5 341 */ 342 public static final int icICCAbsoluteColorimetric = 3; 343 344 345 /** 346 * ICC Profile Tag Signature: 'head' - special. 347 */ 348 public static final int icSigHead = 0x68656164; /* 'head' - special */ 349 350 /** 351 * ICC Profile Tag Signature: 'A2B0'. 352 */ 353 public static final int icSigAToB0Tag = 0x41324230; /* 'A2B0' */ 354 355 /** 356 * ICC Profile Tag Signature: 'A2B1'. 357 */ 358 public static final int icSigAToB1Tag = 0x41324231; /* 'A2B1' */ 359 360 /** 361 * ICC Profile Tag Signature: 'A2B2'. 362 */ 363 public static final int icSigAToB2Tag = 0x41324232; /* 'A2B2' */ 364 365 /** 366 * ICC Profile Tag Signature: 'bXYZ'. 367 */ 368 public static final int icSigBlueColorantTag = 0x6258595A; /* 'bXYZ' */ 369 370 /** 371 * ICC Profile Tag Signature: 'bXYZ'. 372 * @since 1.5 373 */ 374 public static final int icSigBlueMatrixColumnTag = 0x6258595A; /* 'bXYZ' */ 375 376 /** 377 * ICC Profile Tag Signature: 'bTRC'. 378 */ 379 public static final int icSigBlueTRCTag = 0x62545243; /* 'bTRC' */ 380 381 /** 382 * ICC Profile Tag Signature: 'B2A0'. 383 */ 384 public static final int icSigBToA0Tag = 0x42324130; /* 'B2A0' */ 385 386 /** 387 * ICC Profile Tag Signature: 'B2A1'. 388 */ 389 public static final int icSigBToA1Tag = 0x42324131; /* 'B2A1' */ 390 391 /** 392 * ICC Profile Tag Signature: 'B2A2'. 393 */ 394 public static final int icSigBToA2Tag = 0x42324132; /* 'B2A2' */ 395 396 /** 397 * ICC Profile Tag Signature: 'calt'. 398 */ 399 public static final int icSigCalibrationDateTimeTag = 0x63616C74; 400 /* 'calt' */ 401 402 /** 403 * ICC Profile Tag Signature: 'targ'. 404 */ 405 public static final int icSigCharTargetTag = 0x74617267; /* 'targ' */ 406 407 /** 408 * ICC Profile Tag Signature: 'cprt'. 409 */ 410 public static final int icSigCopyrightTag = 0x63707274; /* 'cprt' */ 411 412 /** 413 * ICC Profile Tag Signature: 'crdi'. 414 */ 415 public static final int icSigCrdInfoTag = 0x63726469; /* 'crdi' */ 416 417 /** 418 * ICC Profile Tag Signature: 'dmnd'. 419 */ 420 public static final int icSigDeviceMfgDescTag = 0x646D6E64; /* 'dmnd' */ 421 422 /** 423 * ICC Profile Tag Signature: 'dmdd'. 424 */ 425 public static final int icSigDeviceModelDescTag = 0x646D6464; /* 'dmdd' */ 426 427 /** 428 * ICC Profile Tag Signature: 'devs'. 429 */ 430 public static final int icSigDeviceSettingsTag = 0x64657673; /* 'devs' */ 431 432 /** 433 * ICC Profile Tag Signature: 'gamt'. 434 */ 435 public static final int icSigGamutTag = 0x67616D74; /* 'gamt' */ 436 437 /** 438 * ICC Profile Tag Signature: 'kTRC'. 439 */ 440 public static final int icSigGrayTRCTag = 0x6b545243; /* 'kTRC' */ 441 442 /** 443 * ICC Profile Tag Signature: 'gXYZ'. 444 */ 445 public static final int icSigGreenColorantTag = 0x6758595A; /* 'gXYZ' */ 446 447 /** 448 * ICC Profile Tag Signature: 'gXYZ'. 449 * @since 1.5 450 */ 451 public static final int icSigGreenMatrixColumnTag = 0x6758595A;/* 'gXYZ' */ 452 453 /** 454 * ICC Profile Tag Signature: 'gTRC'. 455 */ 456 public static final int icSigGreenTRCTag = 0x67545243; /* 'gTRC' */ 457 458 /** 459 * ICC Profile Tag Signature: 'lumi'. 460 */ 461 public static final int icSigLuminanceTag = 0x6C756d69; /* 'lumi' */ 462 463 /** 464 * ICC Profile Tag Signature: 'meas'. 465 */ 466 public static final int icSigMeasurementTag = 0x6D656173; /* 'meas' */ 467 468 /** 469 * ICC Profile Tag Signature: 'bkpt'. 470 */ 471 public static final int icSigMediaBlackPointTag = 0x626B7074; /* 'bkpt' */ 472 473 /** 474 * ICC Profile Tag Signature: 'wtpt'. 475 */ 476 public static final int icSigMediaWhitePointTag = 0x77747074; /* 'wtpt' */ 477 478 /** 479 * ICC Profile Tag Signature: 'ncl2'. 480 */ 481 public static final int icSigNamedColor2Tag = 0x6E636C32; /* 'ncl2' */ 482 483 /** 484 * ICC Profile Tag Signature: 'resp'. 485 */ 486 public static final int icSigOutputResponseTag = 0x72657370; /* 'resp' */ 487 488 /** 489 * ICC Profile Tag Signature: 'pre0'. 490 */ 491 public static final int icSigPreview0Tag = 0x70726530; /* 'pre0' */ 492 493 /** 494 * ICC Profile Tag Signature: 'pre1'. 495 */ 496 public static final int icSigPreview1Tag = 0x70726531; /* 'pre1' */ 497 498 /** 499 * ICC Profile Tag Signature: 'pre2'. 500 */ 501 public static final int icSigPreview2Tag = 0x70726532; /* 'pre2' */ 502 503 /** 504 * ICC Profile Tag Signature: 'desc'. 505 */ 506 public static final int icSigProfileDescriptionTag = 0x64657363; 507 /* 'desc' */ 508 509 /** 510 * ICC Profile Tag Signature: 'pseq'. 511 */ 512 public static final int icSigProfileSequenceDescTag = 0x70736571; 513 /* 'pseq' */ 514 515 /** 516 * ICC Profile Tag Signature: 'psd0'. 517 */ 518 public static final int icSigPs2CRD0Tag = 0x70736430; /* 'psd0' */ 519 520 /** 521 * ICC Profile Tag Signature: 'psd1'. 522 */ 523 public static final int icSigPs2CRD1Tag = 0x70736431; /* 'psd1' */ 524 525 /** 526 * ICC Profile Tag Signature: 'psd2'. 527 */ 528 public static final int icSigPs2CRD2Tag = 0x70736432; /* 'psd2' */ 529 530 /** 531 * ICC Profile Tag Signature: 'psd3'. 532 */ 533 public static final int icSigPs2CRD3Tag = 0x70736433; /* 'psd3' */ 534 535 /** 536 * ICC Profile Tag Signature: 'ps2s'. 537 */ 538 public static final int icSigPs2CSATag = 0x70733273; /* 'ps2s' */ 539 540 /** 541 * ICC Profile Tag Signature: 'ps2i'. 542 */ 543 public static final int icSigPs2RenderingIntentTag = 0x70733269; 544 /* 'ps2i' */ 545 546 /** 547 * ICC Profile Tag Signature: 'rXYZ'. 548 */ 549 public static final int icSigRedColorantTag = 0x7258595A; /* 'rXYZ' */ 550 551 /** 552 * ICC Profile Tag Signature: 'rXYZ'. 553 * @since 1.5 554 */ 555 public static final int icSigRedMatrixColumnTag = 0x7258595A; /* 'rXYZ' */ 556 557 /** 558 * ICC Profile Tag Signature: 'rTRC'. 559 */ 560 public static final int icSigRedTRCTag = 0x72545243; /* 'rTRC' */ 561 562 /** 563 * ICC Profile Tag Signature: 'scrd'. 564 */ 565 public static final int icSigScreeningDescTag = 0x73637264; /* 'scrd' */ 566 567 /** 568 * ICC Profile Tag Signature: 'scrn'. 569 */ 570 public static final int icSigScreeningTag = 0x7363726E; /* 'scrn' */ 571 572 /** 573 * ICC Profile Tag Signature: 'tech'. 574 */ 575 public static final int icSigTechnologyTag = 0x74656368; /* 'tech' */ 576 577 /** 578 * ICC Profile Tag Signature: 'bfd '. 579 */ 580 public static final int icSigUcrBgTag = 0x62666420; /* 'bfd ' */ 581 582 /** 583 * ICC Profile Tag Signature: 'vued'. 584 */ 585 public static final int icSigViewingCondDescTag = 0x76756564; /* 'vued' */ 586 587 /** 588 * ICC Profile Tag Signature: 'view'. 589 */ 590 public static final int icSigViewingConditionsTag = 0x76696577;/* 'view' */ 591 592 /** 593 * ICC Profile Tag Signature: 'chrm'. 594 */ 595 public static final int icSigChromaticityTag = 0x6368726d; /* 'chrm' */ 596 597 /** 598 * ICC Profile Tag Signature: 'chad'. 599 * @since 1.5 600 */ 601 public static final int icSigChromaticAdaptationTag = 0x63686164;/* 'chad' */ 602 603 /** 604 * ICC Profile Tag Signature: 'clro'. 605 * @since 1.5 606 */ 607 public static final int icSigColorantOrderTag = 0x636C726F; /* 'clro' */ 608 609 /** 610 * ICC Profile Tag Signature: 'clrt'. 611 * @since 1.5 612 */ 613 public static final int icSigColorantTableTag = 0x636C7274; /* 'clrt' */ 614 615 616 /** 617 * ICC Profile Header Location: profile size in bytes. 618 */ 619 public static final int icHdrSize = 0; /* Profile size in bytes */ 620 621 /** 622 * ICC Profile Header Location: CMM for this profile. 623 */ 624 public static final int icHdrCmmId = 4; /* CMM for this profile */ 625 626 /** 627 * ICC Profile Header Location: format version number. 628 */ 629 public static final int icHdrVersion = 8; /* Format version number */ 630 631 /** 632 * ICC Profile Header Location: type of profile. 633 */ 634 public static final int icHdrDeviceClass = 12; /* Type of profile */ 635 636 /** 637 * ICC Profile Header Location: color space of data. 638 */ 639 public static final int icHdrColorSpace = 16; /* Color space of data */ 640 641 /** 642 * ICC Profile Header Location: PCS - XYZ or Lab only. 643 */ 644 public static final int icHdrPcs = 20; /* PCS - XYZ or Lab only */ 645 646 /** 647 * ICC Profile Header Location: date profile was created. 648 */ 649 public static final int icHdrDate = 24; /* Date profile was created */ 650 651 /** 652 * ICC Profile Header Location: icMagicNumber. 653 */ 654 public static final int icHdrMagic = 36; /* icMagicNumber */ 655 656 /** 657 * ICC Profile Header Location: primary platform. 658 */ 659 public static final int icHdrPlatform = 40; /* Primary Platform */ 660 661 /** 662 * ICC Profile Header Location: various bit settings. 663 */ 664 public static final int icHdrFlags = 44; /* Various bit settings */ 665 666 /** 667 * ICC Profile Header Location: device manufacturer. 668 */ 669 public static final int icHdrManufacturer = 48; /* Device manufacturer */ 670 671 /** 672 * ICC Profile Header Location: device model number. 673 */ 674 public static final int icHdrModel = 52; /* Device model number */ 675 676 /** 677 * ICC Profile Header Location: device attributes. 678 */ 679 public static final int icHdrAttributes = 56; /* Device attributes */ 680 681 /** 682 * ICC Profile Header Location: rendering intent. 683 */ 684 public static final int icHdrRenderingIntent = 64; /* Rendering intent */ 685 686 /** 687 * ICC Profile Header Location: profile illuminant. 688 */ 689 public static final int icHdrIlluminant = 68; /* Profile illuminant */ 690 691 /** 692 * ICC Profile Header Location: profile creator. 693 */ 694 public static final int icHdrCreator = 80; /* Profile creator */ 695 696 /** 697 * ICC Profile Header Location: profile's ID. 698 * @since 1.5 699 */ 700 public static final int icHdrProfileID = 84; /* Profile's ID */ 701 702 703 /** 704 * ICC Profile Constant: tag type signature. 705 */ 706 public static final int icTagType = 0; /* tag type signature */ 707 708 /** 709 * ICC Profile Constant: reserved. 710 */ 711 public static final int icTagReserved = 4; /* reserved */ 712 713 /** 714 * ICC Profile Constant: curveType count. 715 */ 716 public static final int icCurveCount = 8; /* curveType count */ 717 718 /** 719 * ICC Profile Constant: curveType data. 720 */ 721 public static final int icCurveData = 12; /* curveType data */ 722 723 /** 724 * ICC Profile Constant: XYZNumber X. 725 */ 726 public static final int icXYZNumberX = 8; /* XYZNumber X */ 727 728 729 /** 730 * Constructs an ICC_Profile object with a given ID. 731 */ 732 ICC_Profile(Profile p) { 733 this.cmmProfile = p; 734 } 735 736 737 /** 738 * Constructs an ICC_Profile object whose loading will be deferred. 739 * The ID will be 0 until the profile is loaded. 740 */ 741 ICC_Profile(ProfileDeferralInfo pdi) { 742 this.deferralInfo = pdi; 743 this.profileActivator = new ProfileActivator() { 744 public void activate() throws ProfileDataException { 745 activateDeferredProfile(); 746 } 747 }; 748 ProfileDeferralMgr.registerDeferral(this.profileActivator); 749 } 750 751 752 /** 753 * Frees the resources associated with an ICC_Profile object. 754 */ 755 protected void finalize () { 756 if (cmmProfile != null) { 757 CMSManager.getModule().freeProfile(cmmProfile); 758 } else if (profileActivator != null) { 759 ProfileDeferralMgr.unregisterDeferral(profileActivator); 760 } 761 } 762 763 764 /** 765 * Constructs an ICC_Profile object corresponding to the data in 766 * a byte array. Throws an IllegalArgumentException if the data 767 * does not correspond to a valid ICC Profile. 768 * @param data the specified ICC Profile data 769 * @return an {@code ICC_Profile} object corresponding to 770 * the data in the specified {@code data} array. 771 */ 772 public static ICC_Profile getInstance(byte[] data) { 773 ICC_Profile thisProfile; 774 775 Profile p = null; 776 777 if (ProfileDeferralMgr.deferring) { 778 ProfileDeferralMgr.activateProfiles(); 779 } 780 781 ProfileDataVerifier.verify(data); 782 783 try { 784 p = CMSManager.getModule().loadProfile(data); 785 } catch (CMMException c) { 786 throw new IllegalArgumentException("Invalid ICC Profile Data"); 787 } 788 789 try { 790 if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) && 791 (getData (p, icSigMediaWhitePointTag) != null) && 792 (getData (p, icSigGrayTRCTag) != null)) { 793 thisProfile = new ICC_ProfileGray (p); 794 } 795 else if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) && 796 (getData (p, icSigMediaWhitePointTag) != null) && 797 (getData (p, icSigRedColorantTag) != null) && 798 (getData (p, icSigGreenColorantTag) != null) && 799 (getData (p, icSigBlueColorantTag) != null) && 800 (getData (p, icSigRedTRCTag) != null) && 801 (getData (p, icSigGreenTRCTag) != null) && 802 (getData (p, icSigBlueTRCTag) != null)) { 803 thisProfile = new ICC_ProfileRGB (p); 804 } 805 else { 806 thisProfile = new ICC_Profile (p); 807 } 808 } catch (CMMException c) { 809 thisProfile = new ICC_Profile (p); 810 } 811 return thisProfile; 812 } 813 814 815 816 /** 817 * Constructs an ICC_Profile corresponding to one of the specific color 818 * spaces defined by the ColorSpace class (for example CS_sRGB). 819 * Throws an IllegalArgumentException if cspace is not one of the 820 * defined color spaces. 821 * 822 * @param cspace the type of color space to create a profile for. 823 * The specified type is one of the color 824 * space constants defined in the {@code ColorSpace} class. 825 * 826 * @return an {@code ICC_Profile} object corresponding to 827 * the specified {@code ColorSpace} type. 828 * @exception IllegalArgumentException If {@code cspace} is not 829 * one of the predefined color space types. 830 */ 831 public static ICC_Profile getInstance (int cspace) { 832 ICC_Profile thisProfile = null; 833 String fileName; 834 835 switch (cspace) { 836 case ColorSpace.CS_sRGB: 837 synchronized(ICC_Profile.class) { 838 if (sRGBprofile == null) { 839 /* 840 * Deferral is only used for standard profiles. 841 * Enabling the appropriate access privileges is handled 842 * at a lower level. 843 */ 844 ProfileDeferralInfo pInfo = 845 new ProfileDeferralInfo("sRGB.pf", 846 ColorSpace.TYPE_RGB, 3, 847 CLASS_DISPLAY); 848 sRGBprofile = getDeferredInstance(pInfo); 849 } 850 thisProfile = sRGBprofile; 851 } 852 853 break; 854 855 case ColorSpace.CS_CIEXYZ: 856 synchronized(ICC_Profile.class) { 857 if (XYZprofile == null) { 858 ProfileDeferralInfo pInfo = 859 new ProfileDeferralInfo("CIEXYZ.pf", 860 ColorSpace.TYPE_XYZ, 3, 861 CLASS_DISPLAY); 862 XYZprofile = getDeferredInstance(pInfo); 863 } 864 thisProfile = XYZprofile; 865 } 866 867 break; 868 869 case ColorSpace.CS_PYCC: 870 synchronized(ICC_Profile.class) { 871 if (PYCCprofile == null) { 872 if (standardProfileExists("PYCC.pf")) 873 { 874 ProfileDeferralInfo pInfo = 875 new ProfileDeferralInfo("PYCC.pf", 876 ColorSpace.TYPE_3CLR, 3, 877 CLASS_DISPLAY); 878 PYCCprofile = getDeferredInstance(pInfo); 879 } else { 880 throw new IllegalArgumentException( 881 "Can't load standard profile: PYCC.pf"); 882 } 883 } 884 thisProfile = PYCCprofile; 885 } 886 887 break; 888 889 case ColorSpace.CS_GRAY: 890 synchronized(ICC_Profile.class) { 891 if (GRAYprofile == null) { 892 ProfileDeferralInfo pInfo = 893 new ProfileDeferralInfo("GRAY.pf", 894 ColorSpace.TYPE_GRAY, 1, 895 CLASS_DISPLAY); 896 GRAYprofile = getDeferredInstance(pInfo); 897 } 898 thisProfile = GRAYprofile; 899 } 900 901 break; 902 903 case ColorSpace.CS_LINEAR_RGB: 904 synchronized(ICC_Profile.class) { 905 if (LINEAR_RGBprofile == null) { 906 ProfileDeferralInfo pInfo = 907 new ProfileDeferralInfo("LINEAR_RGB.pf", 908 ColorSpace.TYPE_RGB, 3, 909 CLASS_DISPLAY); 910 LINEAR_RGBprofile = getDeferredInstance(pInfo); 911 } 912 thisProfile = LINEAR_RGBprofile; 913 } 914 915 break; 916 917 default: 918 throw new IllegalArgumentException("Unknown color space"); 919 } 920 921 return thisProfile; 922 } 923 924 /* This asserts system privileges, so is used only for the 925 * standard profiles. 926 */ 927 private static ICC_Profile getStandardProfile(final String name) { 928 929 return AccessController.doPrivileged( 930 new PrivilegedAction<ICC_Profile>() { 931 public ICC_Profile run() { 932 ICC_Profile p = null; 933 try { 934 p = getInstance (name); 935 } catch (IOException ex) { 936 throw new IllegalArgumentException( 937 "Can't load standard profile: " + name); 938 } 939 return p; 940 } 941 }); 942 } 943 944 /** 945 * Constructs an ICC_Profile corresponding to the data in a file. 946 * fileName may be an absolute or a relative file specification. 947 * Relative file names are looked for in several places: first, relative 948 * to any directories specified by the java.iccprofile.path property; 949 * second, relative to any directories specified by the java.class.path 950 * property; finally, in a directory used to store profiles always 951 * available, such as the profile for sRGB. Built-in profiles use .pf as 952 * the file name extension for profiles, e.g. sRGB.pf. 953 * This method throws an IOException if the specified file cannot be 954 * opened or if an I/O error occurs while reading the file. It throws 955 * an IllegalArgumentException if the file does not contain valid ICC 956 * Profile data. 957 * @param fileName The file that contains the data for the profile. 958 * 959 * @return an {@code ICC_Profile} object corresponding to 960 * the data in the specified file. 961 * @exception IOException If the specified file cannot be opened or 962 * an I/O error occurs while reading the file. 963 * 964 * @exception IllegalArgumentException If the file does not 965 * contain valid ICC Profile data. 966 * 967 * @exception SecurityException If a security manager is installed 968 * and it does not permit read access to the given file. 969 */ 970 public static ICC_Profile getInstance(String fileName) throws IOException { 971 ICC_Profile thisProfile; 972 InputStream is = null; 973 974 975 File f = getProfileFile(fileName); 976 if (f != null) { 977 is = new FileInputStream(f); 978 } else { 979 is = getStandardProfileInputStream(fileName); 980 } 981 if (is == null) { 982 throw new IOException("Cannot open file " + fileName); 983 } 984 985 thisProfile = getInstance(is); 986 987 is.close(); /* close the file */ 988 989 return thisProfile; 990 } 991 992 993 /** 994 * Constructs an ICC_Profile corresponding to the data in an InputStream. 995 * This method throws an IllegalArgumentException if the stream does not 996 * contain valid ICC Profile data. It throws an IOException if an I/O 997 * error occurs while reading the stream. 998 * @param s The input stream from which to read the profile data. 999 * 1000 * @return an {@code ICC_Profile} object corresponding to the 1001 * data in the specified {@code InputStream}. 1002 * 1003 * @exception IOException If an I/O error occurs while reading the stream. 1004 * 1005 * @exception IllegalArgumentException If the stream does not 1006 * contain valid ICC Profile data. 1007 */ 1008 public static ICC_Profile getInstance(InputStream s) throws IOException { 1009 byte profileData[]; 1010 1011 if (s instanceof ProfileDeferralInfo) { 1012 /* hack to detect profiles whose loading can be deferred */ 1013 return getDeferredInstance((ProfileDeferralInfo) s); 1014 } 1015 1016 if ((profileData = getProfileDataFromStream(s)) == null) { 1017 throw new IllegalArgumentException("Invalid ICC Profile Data"); 1018 } 1019 1020 return getInstance(profileData); 1021 } 1022 1023 1024 static byte[] getProfileDataFromStream(InputStream s) throws IOException { 1025 byte profileData[]; 1026 int profileSize; 1027 1028 byte header[] = new byte[128]; 1029 int bytestoread = 128; 1030 int bytesread = 0; 1031 int n; 1032 1033 while (bytestoread != 0) { 1034 if ((n = s.read(header, bytesread, bytestoread)) < 0) { 1035 return null; 1036 } 1037 bytesread += n; 1038 bytestoread -= n; 1039 } 1040 if (header[36] != 0x61 || header[37] != 0x63 || 1041 header[38] != 0x73 || header[39] != 0x70) { 1042 return null; /* not a valid profile */ 1043 } 1044 profileSize = ((header[0] & 0xff) << 24) | 1045 ((header[1] & 0xff) << 16) | 1046 ((header[2] & 0xff) << 8) | 1047 (header[3] & 0xff); 1048 profileData = new byte[profileSize]; 1049 System.arraycopy(header, 0, profileData, 0, 128); 1050 bytestoread = profileSize - 128; 1051 bytesread = 128; 1052 while (bytestoread != 0) { 1053 if ((n = s.read(profileData, bytesread, bytestoread)) < 0) { 1054 return null; 1055 } 1056 bytesread += n; 1057 bytestoread -= n; 1058 } 1059 1060 return profileData; 1061 } 1062 1063 1064 /** 1065 * Constructs an ICC_Profile for which the actual loading of the 1066 * profile data from a file and the initialization of the CMM should 1067 * be deferred as long as possible. 1068 * Deferral is only used for standard profiles. 1069 * If deferring is disabled, then getStandardProfile() ensures 1070 * that all of the appropriate access privileges are granted 1071 * when loading this profile. 1072 * If deferring is enabled, then the deferred activation 1073 * code will take care of access privileges. 1074 * @see activateDeferredProfile() 1075 */ 1076 static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) { 1077 if (!ProfileDeferralMgr.deferring) { 1078 return getStandardProfile(pdi.filename); 1079 } 1080 if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) { 1081 return new ICC_ProfileRGB(pdi); 1082 } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) { 1083 return new ICC_ProfileGray(pdi); 1084 } else { 1085 return new ICC_Profile(pdi); 1086 } 1087 } 1088 1089 1090 void activateDeferredProfile() throws ProfileDataException { 1091 byte profileData[]; 1092 final String fileName = deferralInfo.filename; 1093 1094 profileActivator = null; 1095 deferralInfo = null; 1096 InputStream is = getStandardProfileInputStream(fileName); 1097 if (is == null) { 1098 throw new ProfileDataException("Cannot open file " + fileName); 1099 } 1100 try { 1101 profileData = getProfileDataFromStream(is); 1102 is.close(); /* close the file */ 1103 } 1104 catch (IOException e) { 1105 ProfileDataException pde = new 1106 ProfileDataException("Invalid ICC Profile Data" + fileName); 1107 pde.initCause(e); 1108 throw pde; 1109 } 1110 if (profileData == null) { 1111 throw new ProfileDataException("Invalid ICC Profile Data" + 1112 fileName); 1113 } 1114 try { 1115 cmmProfile = CMSManager.getModule().loadProfile(profileData); 1116 } catch (CMMException c) { 1117 ProfileDataException pde = new 1118 ProfileDataException("Invalid ICC Profile Data" + fileName); 1119 pde.initCause(c); 1120 throw pde; 1121 } 1122 } 1123 1124 1125 /** 1126 * Returns profile major version. 1127 * @return The major version of the profile. 1128 */ 1129 public int getMajorVersion() { 1130 byte[] theHeader; 1131 1132 theHeader = getData(icSigHead); /* getData will activate deferred 1133 profiles if necessary */ 1134 1135 return (int) theHeader[8]; 1136 } 1137 1138 /** 1139 * Returns profile minor version. 1140 * @return The minor version of the profile. 1141 */ 1142 public int getMinorVersion() { 1143 byte[] theHeader; 1144 1145 theHeader = getData(icSigHead); /* getData will activate deferred 1146 profiles if necessary */ 1147 1148 return (int) theHeader[9]; 1149 } 1150 1151 /** 1152 * Returns the profile class. 1153 * @return One of the predefined profile class constants. 1154 */ 1155 public int getProfileClass() { 1156 byte[] theHeader; 1157 int theClassSig, theClass; 1158 1159 if (deferralInfo != null) { 1160 return deferralInfo.profileClass; /* Need to have this info for 1161 ICC_ColorSpace without 1162 causing a deferred profile 1163 to be loaded */ 1164 } 1165 1166 theHeader = getData(icSigHead); 1167 1168 theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass); 1169 1170 switch (theClassSig) { 1171 case icSigInputClass: 1172 theClass = CLASS_INPUT; 1173 break; 1174 1175 case icSigDisplayClass: 1176 theClass = CLASS_DISPLAY; 1177 break; 1178 1179 case icSigOutputClass: 1180 theClass = CLASS_OUTPUT; 1181 break; 1182 1183 case icSigLinkClass: 1184 theClass = CLASS_DEVICELINK; 1185 break; 1186 1187 case icSigColorSpaceClass: 1188 theClass = CLASS_COLORSPACECONVERSION; 1189 break; 1190 1191 case icSigAbstractClass: 1192 theClass = CLASS_ABSTRACT; 1193 break; 1194 1195 case icSigNamedColorClass: 1196 theClass = CLASS_NAMEDCOLOR; 1197 break; 1198 1199 default: 1200 throw new IllegalArgumentException("Unknown profile class"); 1201 } 1202 1203 return theClass; 1204 } 1205 1206 /** 1207 * Returns the color space type. Returns one of the color space type 1208 * constants defined by the ColorSpace class. This is the 1209 * "input" color space of the profile. The type defines the 1210 * number of components of the color space and the interpretation, 1211 * e.g. TYPE_RGB identifies a color space with three components - red, 1212 * green, and blue. It does not define the particular color 1213 * characteristics of the space, e.g. the chromaticities of the 1214 * primaries. 1215 * @return One of the color space type constants defined in the 1216 * {@code ColorSpace} class. 1217 */ 1218 public int getColorSpaceType() { 1219 if (deferralInfo != null) { 1220 return deferralInfo.colorSpaceType; /* Need to have this info for 1221 ICC_ColorSpace without 1222 causing a deferred profile 1223 to be loaded */ 1224 } 1225 return getColorSpaceType(cmmProfile); 1226 } 1227 1228 static int getColorSpaceType(Profile p) { 1229 byte[] theHeader; 1230 int theColorSpaceSig, theColorSpace; 1231 1232 theHeader = getData(p, icSigHead); 1233 theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); 1234 theColorSpace = iccCStoJCS (theColorSpaceSig); 1235 return theColorSpace; 1236 } 1237 1238 /** 1239 * Returns the color space type of the Profile Connection Space (PCS). 1240 * Returns one of the color space type constants defined by the 1241 * ColorSpace class. This is the "output" color space of the 1242 * profile. For an input, display, or output profile useful 1243 * for tagging colors or images, this will be either TYPE_XYZ or 1244 * TYPE_Lab and should be interpreted as the corresponding specific 1245 * color space defined in the ICC specification. For a device 1246 * link profile, this could be any of the color space type constants. 1247 * @return One of the color space type constants defined in the 1248 * {@code ColorSpace} class. 1249 */ 1250 public int getPCSType() { 1251 if (ProfileDeferralMgr.deferring) { 1252 ProfileDeferralMgr.activateProfiles(); 1253 } 1254 return getPCSType(cmmProfile); 1255 } 1256 1257 1258 static int getPCSType(Profile p) { 1259 byte[] theHeader; 1260 int thePCSSig, thePCS; 1261 1262 theHeader = getData(p, icSigHead); 1263 thePCSSig = intFromBigEndian(theHeader, icHdrPcs); 1264 thePCS = iccCStoJCS(thePCSSig); 1265 return thePCS; 1266 } 1267 1268 1269 /** 1270 * Write this ICC_Profile to a file. 1271 * 1272 * @param fileName The file to write the profile data to. 1273 * 1274 * @exception IOException If the file cannot be opened for writing 1275 * or an I/O error occurs while writing to the file. 1276 */ 1277 public void write(String fileName) throws IOException { 1278 FileOutputStream outputFile; 1279 byte profileData[]; 1280 1281 profileData = getData(); /* this will activate deferred 1282 profiles if necessary */ 1283 outputFile = new FileOutputStream(fileName); 1284 outputFile.write(profileData); 1285 outputFile.close (); 1286 } 1287 1288 1289 /** 1290 * Write this ICC_Profile to an OutputStream. 1291 * 1292 * @param s The stream to write the profile data to. 1293 * 1294 * @exception IOException If an I/O error occurs while writing to the 1295 * stream. 1296 */ 1297 public void write(OutputStream s) throws IOException { 1298 byte profileData[]; 1299 1300 profileData = getData(); /* this will activate deferred 1301 profiles if necessary */ 1302 s.write(profileData); 1303 } 1304 1305 1306 /** 1307 * Returns a byte array corresponding to the data of this ICC_Profile. 1308 * @return A byte array that contains the profile data. 1309 * @see #setData(int, byte[]) 1310 */ 1311 public byte[] getData() { 1312 int profileSize; 1313 byte[] profileData; 1314 1315 if (ProfileDeferralMgr.deferring) { 1316 ProfileDeferralMgr.activateProfiles(); 1317 } 1318 1319 PCMM mdl = CMSManager.getModule(); 1320 1321 /* get the number of bytes needed for this profile */ 1322 profileSize = mdl.getProfileSize(cmmProfile); 1323 1324 profileData = new byte [profileSize]; 1325 1326 /* get the data for the profile */ 1327 mdl.getProfileData(cmmProfile, profileData); 1328 1329 return profileData; 1330 } 1331 1332 1333 /** 1334 * Returns a particular tagged data element from the profile as 1335 * a byte array. Elements are identified by signatures 1336 * as defined in the ICC specification. The signature 1337 * icSigHead can be used to get the header. This method is useful 1338 * for advanced applets or applications which need to access 1339 * profile data directly. 1340 * 1341 * @param tagSignature The ICC tag signature for the data element you 1342 * want to get. 1343 * 1344 * @return A byte array that contains the tagged data element. Returns 1345 * {@code null} if the specified tag doesn't exist. 1346 * @see #setData(int, byte[]) 1347 */ 1348 public byte[] getData(int tagSignature) { 1349 1350 if (ProfileDeferralMgr.deferring) { 1351 ProfileDeferralMgr.activateProfiles(); 1352 } 1353 1354 return getData(cmmProfile, tagSignature); 1355 } 1356 1357 1358 static byte[] getData(Profile p, int tagSignature) { 1359 int tagSize; 1360 byte[] tagData; 1361 1362 try { 1363 PCMM mdl = CMSManager.getModule(); 1364 1365 /* get the number of bytes needed for this tag */ 1366 tagSize = mdl.getTagSize(p, tagSignature); 1367 1368 tagData = new byte[tagSize]; /* get an array for the tag */ 1369 1370 /* get the tag's data */ 1371 mdl.getTagData(p, tagSignature, tagData); 1372 } catch(CMMException c) { 1373 tagData = null; 1374 } 1375 1376 return tagData; 1377 } 1378 1379 /** 1380 * Sets a particular tagged data element in the profile from 1381 * a byte array. The array should contain data in a format, corresponded 1382 * to the {@code tagSignature} as defined in the ICC specification, section 10. 1383 * This method is useful for advanced applets or applications which need to 1384 * access profile data directly. 1385 * 1386 * @param tagSignature The ICC tag signature for the data element 1387 * you want to set. 1388 * @param tagData the data to set for the specified tag signature 1389 * @throws IllegalArgumentException if {@code tagSignature} is not a signature 1390 * as defined in the ICC specification. 1391 * @throws IllegalArgumentException if a content of the {@code tagData} 1392 * array can not be interpreted as valid tag data, corresponding 1393 * to the {@code tagSignature}. 1394 * @see #getData 1395 */ 1396 public void setData(int tagSignature, byte[] tagData) { 1397 1398 if (ProfileDeferralMgr.deferring) { 1399 ProfileDeferralMgr.activateProfiles(); 1400 } 1401 1402 CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData); 1403 } 1404 1405 /** 1406 * Sets the rendering intent of the profile. 1407 * This is used to select the proper transform from a profile that 1408 * has multiple transforms. 1409 */ 1410 void setRenderingIntent(int renderingIntent) { 1411 byte[] theHeader = getData(icSigHead);/* getData will activate deferred 1412 profiles if necessary */ 1413 intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent); 1414 /* set the rendering intent */ 1415 setData (icSigHead, theHeader); 1416 } 1417 1418 1419 /** 1420 * Returns the rendering intent of the profile. 1421 * This is used to select the proper transform from a profile that 1422 * has multiple transforms. It is typically set in a source profile 1423 * to select a transform from an output profile. 1424 */ 1425 int getRenderingIntent() { 1426 byte[] theHeader = getData(icSigHead);/* getData will activate deferred 1427 profiles if necessary */ 1428 1429 int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent); 1430 /* set the rendering intent */ 1431 1432 /* According to ICC spec, only the least-significant 16 bits shall be 1433 * used to encode the rendering intent. The most significant 16 bits 1434 * shall be set to zero. Thus, we are ignoring two most significant 1435 * bytes here. 1436 * 1437 * See http://www.color.org/ICC1v42_2006-05.pdf, section 7.2.15. 1438 */ 1439 return (0xffff & renderingIntent); 1440 } 1441 1442 1443 /** 1444 * Returns the number of color components in the "input" color 1445 * space of this profile. For example if the color space type 1446 * of this profile is TYPE_RGB, then this method will return 3. 1447 * 1448 * @return The number of color components in the profile's input 1449 * color space. 1450 * 1451 * @throws ProfileDataException if color space is in the profile 1452 * is invalid 1453 */ 1454 public int getNumComponents() { 1455 byte[] theHeader; 1456 int theColorSpaceSig, theNumComponents; 1457 1458 if (deferralInfo != null) { 1459 return deferralInfo.numComponents; /* Need to have this info for 1460 ICC_ColorSpace without 1461 causing a deferred profile 1462 to be loaded */ 1463 } 1464 theHeader = getData(icSigHead); 1465 1466 theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace); 1467 1468 switch (theColorSpaceSig) { 1469 case icSigGrayData: 1470 theNumComponents = 1; 1471 break; 1472 1473 case icSigSpace2CLR: 1474 theNumComponents = 2; 1475 break; 1476 1477 case icSigXYZData: 1478 case icSigLabData: 1479 case icSigLuvData: 1480 case icSigYCbCrData: 1481 case icSigYxyData: 1482 case icSigRgbData: 1483 case icSigHsvData: 1484 case icSigHlsData: 1485 case icSigCmyData: 1486 case icSigSpace3CLR: 1487 theNumComponents = 3; 1488 break; 1489 1490 case icSigCmykData: 1491 case icSigSpace4CLR: 1492 theNumComponents = 4; 1493 break; 1494 1495 case icSigSpace5CLR: 1496 theNumComponents = 5; 1497 break; 1498 1499 case icSigSpace6CLR: 1500 theNumComponents = 6; 1501 break; 1502 1503 case icSigSpace7CLR: 1504 theNumComponents = 7; 1505 break; 1506 1507 case icSigSpace8CLR: 1508 theNumComponents = 8; 1509 break; 1510 1511 case icSigSpace9CLR: 1512 theNumComponents = 9; 1513 break; 1514 1515 case icSigSpaceACLR: 1516 theNumComponents = 10; 1517 break; 1518 1519 case icSigSpaceBCLR: 1520 theNumComponents = 11; 1521 break; 1522 1523 case icSigSpaceCCLR: 1524 theNumComponents = 12; 1525 break; 1526 1527 case icSigSpaceDCLR: 1528 theNumComponents = 13; 1529 break; 1530 1531 case icSigSpaceECLR: 1532 theNumComponents = 14; 1533 break; 1534 1535 case icSigSpaceFCLR: 1536 theNumComponents = 15; 1537 break; 1538 1539 default: 1540 throw new ProfileDataException ("invalid ICC color space"); 1541 } 1542 1543 return theNumComponents; 1544 } 1545 1546 1547 /** 1548 * Returns a float array of length 3 containing the X, Y, and Z 1549 * components of the mediaWhitePointTag in the ICC profile. 1550 */ 1551 float[] getMediaWhitePoint() { 1552 return getXYZTag(icSigMediaWhitePointTag); 1553 /* get the media white point tag */ 1554 } 1555 1556 1557 /** 1558 * Returns a float array of length 3 containing the X, Y, and Z 1559 * components encoded in an XYZType tag. 1560 */ 1561 float[] getXYZTag(int theTagSignature) { 1562 byte[] theData; 1563 float[] theXYZNumber; 1564 int i1, i2, theS15Fixed16; 1565 1566 theData = getData(theTagSignature); /* get the tag data */ 1567 /* getData will activate deferred 1568 profiles if necessary */ 1569 1570 theXYZNumber = new float [3]; /* array to return */ 1571 1572 /* convert s15Fixed16Number to float */ 1573 for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) { 1574 theS15Fixed16 = intFromBigEndian(theData, i2); 1575 theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f; 1576 } 1577 return theXYZNumber; 1578 } 1579 1580 1581 /** 1582 * Returns a gamma value representing a tone reproduction 1583 * curve (TRC). If the profile represents the TRC as a table rather 1584 * than a single gamma value, then an exception is thrown. In this 1585 * case the actual table can be obtained via getTRC(). 1586 * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag, 1587 * icSigGreenTRCTag, or icSigBlueTRCTag. 1588 * @return the gamma value as a float. 1589 * @exception ProfileDataException if the profile does not specify 1590 * the TRC as a single gamma value. 1591 */ 1592 float getGamma(int theTagSignature) { 1593 byte[] theTRCData; 1594 float theGamma; 1595 int theU8Fixed8; 1596 1597 theTRCData = getData(theTagSignature); /* get the TRC */ 1598 /* getData will activate deferred 1599 profiles if necessary */ 1600 1601 if (intFromBigEndian (theTRCData, icCurveCount) != 1) { 1602 throw new ProfileDataException ("TRC is not a gamma"); 1603 } 1604 1605 /* convert u8Fixed8 to float */ 1606 theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff; 1607 1608 theGamma = ((float) theU8Fixed8) / 256.0f; 1609 1610 return theGamma; 1611 } 1612 1613 1614 /** 1615 * Returns the TRC as an array of shorts. If the profile has 1616 * specified the TRC as linear (gamma = 1.0) or as a simple gamma 1617 * value, this method throws an exception, and the getGamma() method 1618 * should be used to get the gamma value. Otherwise the short array 1619 * returned here represents a lookup table where the input Gray value 1620 * is conceptually in the range [0.0, 1.0]. Value 0.0 maps 1621 * to array index 0 and value 1.0 maps to array index length-1. 1622 * Interpolation may be used to generate output values for 1623 * input values which do not map exactly to an index in the 1624 * array. Output values also map linearly to the range [0.0, 1.0]. 1625 * Value 0.0 is represented by an array value of 0x0000 and 1626 * value 1.0 by 0xFFFF, i.e. the values are really unsigned 1627 * short values, although they are returned in a short array. 1628 * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag, 1629 * icSigGreenTRCTag, or icSigBlueTRCTag. 1630 * @return a short array representing the TRC. 1631 * @exception ProfileDataException if the profile does not specify 1632 * the TRC as a table. 1633 */ 1634 short[] getTRC(int theTagSignature) { 1635 byte[] theTRCData; 1636 short[] theTRC; 1637 int i1, i2, nElements, theU8Fixed8; 1638 1639 theTRCData = getData(theTagSignature); /* get the TRC */ 1640 /* getData will activate deferred 1641 profiles if necessary */ 1642 1643 nElements = intFromBigEndian(theTRCData, icCurveCount); 1644 1645 if (nElements == 1) { 1646 throw new ProfileDataException("TRC is not a table"); 1647 } 1648 1649 /* make the short array */ 1650 theTRC = new short [nElements]; 1651 1652 for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) { 1653 theTRC[i1] = shortFromBigEndian(theTRCData, i2); 1654 } 1655 1656 return theTRC; 1657 } 1658 1659 1660 /* convert an ICC color space signature into a Java color space type */ 1661 static int iccCStoJCS(int theColorSpaceSig) { 1662 int theColorSpace; 1663 1664 switch (theColorSpaceSig) { 1665 case icSigXYZData: 1666 theColorSpace = ColorSpace.TYPE_XYZ; 1667 break; 1668 1669 case icSigLabData: 1670 theColorSpace = ColorSpace.TYPE_Lab; 1671 break; 1672 1673 case icSigLuvData: 1674 theColorSpace = ColorSpace.TYPE_Luv; 1675 break; 1676 1677 case icSigYCbCrData: 1678 theColorSpace = ColorSpace.TYPE_YCbCr; 1679 break; 1680 1681 case icSigYxyData: 1682 theColorSpace = ColorSpace.TYPE_Yxy; 1683 break; 1684 1685 case icSigRgbData: 1686 theColorSpace = ColorSpace.TYPE_RGB; 1687 break; 1688 1689 case icSigGrayData: 1690 theColorSpace = ColorSpace.TYPE_GRAY; 1691 break; 1692 1693 case icSigHsvData: 1694 theColorSpace = ColorSpace.TYPE_HSV; 1695 break; 1696 1697 case icSigHlsData: 1698 theColorSpace = ColorSpace.TYPE_HLS; 1699 break; 1700 1701 case icSigCmykData: 1702 theColorSpace = ColorSpace.TYPE_CMYK; 1703 break; 1704 1705 case icSigCmyData: 1706 theColorSpace = ColorSpace.TYPE_CMY; 1707 break; 1708 1709 case icSigSpace2CLR: 1710 theColorSpace = ColorSpace.TYPE_2CLR; 1711 break; 1712 1713 case icSigSpace3CLR: 1714 theColorSpace = ColorSpace.TYPE_3CLR; 1715 break; 1716 1717 case icSigSpace4CLR: 1718 theColorSpace = ColorSpace.TYPE_4CLR; 1719 break; 1720 1721 case icSigSpace5CLR: 1722 theColorSpace = ColorSpace.TYPE_5CLR; 1723 break; 1724 1725 case icSigSpace6CLR: 1726 theColorSpace = ColorSpace.TYPE_6CLR; 1727 break; 1728 1729 case icSigSpace7CLR: 1730 theColorSpace = ColorSpace.TYPE_7CLR; 1731 break; 1732 1733 case icSigSpace8CLR: 1734 theColorSpace = ColorSpace.TYPE_8CLR; 1735 break; 1736 1737 case icSigSpace9CLR: 1738 theColorSpace = ColorSpace.TYPE_9CLR; 1739 break; 1740 1741 case icSigSpaceACLR: 1742 theColorSpace = ColorSpace.TYPE_ACLR; 1743 break; 1744 1745 case icSigSpaceBCLR: 1746 theColorSpace = ColorSpace.TYPE_BCLR; 1747 break; 1748 1749 case icSigSpaceCCLR: 1750 theColorSpace = ColorSpace.TYPE_CCLR; 1751 break; 1752 1753 case icSigSpaceDCLR: 1754 theColorSpace = ColorSpace.TYPE_DCLR; 1755 break; 1756 1757 case icSigSpaceECLR: 1758 theColorSpace = ColorSpace.TYPE_ECLR; 1759 break; 1760 1761 case icSigSpaceFCLR: 1762 theColorSpace = ColorSpace.TYPE_FCLR; 1763 break; 1764 1765 default: 1766 throw new IllegalArgumentException ("Unknown color space"); 1767 } 1768 1769 return theColorSpace; 1770 } 1771 1772 1773 static int intFromBigEndian(byte[] array, int index) { 1774 return (((array[index] & 0xff) << 24) | 1775 ((array[index+1] & 0xff) << 16) | 1776 ((array[index+2] & 0xff) << 8) | 1777 (array[index+3] & 0xff)); 1778 } 1779 1780 1781 static void intToBigEndian(int value, byte[] array, int index) { 1782 array[index] = (byte) (value >> 24); 1783 array[index+1] = (byte) (value >> 16); 1784 array[index+2] = (byte) (value >> 8); 1785 array[index+3] = (byte) (value); 1786 } 1787 1788 1789 static short shortFromBigEndian(byte[] array, int index) { 1790 return (short) (((array[index] & 0xff) << 8) | 1791 (array[index+1] & 0xff)); 1792 } 1793 1794 1795 static void shortToBigEndian(short value, byte[] array, int index) { 1796 array[index] = (byte) (value >> 8); 1797 array[index+1] = (byte) (value); 1798 } 1799 1800 1801 /* 1802 * fileName may be an absolute or a relative file specification. 1803 * Relative file names are looked for in several places: first, relative 1804 * to any directories specified by the java.iccprofile.path property; 1805 * second, relative to any directories specified by the java.class.path. 1806 * The built-in profile files are now loaded as resources, since they 1807 * may not be individual disk files, and so this method will not find 1808 * these and on a null return, the caller needs to try as resources. 1809 * Built-in profiles use .pf as the file name extension for profiles, 1810 * e.g. sRGB.pf. 1811 */ 1812 private static File getProfileFile(String fileName) { 1813 String path, dir, fullPath; 1814 1815 File f = new File(fileName); /* try absolute file name */ 1816 if (f.isAbsolute()) { 1817 /* Rest of code has little sense for an absolute pathname, 1818 so return here. */ 1819 return f.isFile() ? f : null; 1820 } 1821 if ((!f.isFile()) && 1822 ((path = System.getProperty("java.iccprofile.path")) != null)){ 1823 /* try relative to java.iccprofile.path */ 1824 StringTokenizer st = 1825 new StringTokenizer(path, File.pathSeparator); 1826 while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) { 1827 dir = st.nextToken(); 1828 fullPath = dir + File.separatorChar + fileName; 1829 f = new File(fullPath); 1830 if (!isChildOf(f, dir)) { 1831 f = null; 1832 } 1833 } 1834 } 1835 1836 if (((f == null) || (!f.isFile())) && 1837 ((path = System.getProperty("java.class.path")) != null)) { 1838 /* try relative to java.class.path */ 1839 StringTokenizer st = 1840 new StringTokenizer(path, File.pathSeparator); 1841 while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) { 1842 dir = st.nextToken(); 1843 fullPath = dir + File.separatorChar + fileName; 1844 f = new File(fullPath); 1845 } 1846 } 1847 1848 if (f != null && !f.isFile()) { 1849 f = null; 1850 } 1851 return f; 1852 } 1853 1854 /** 1855 * Returns a stream corresponding to a built-in profile 1856 * specified by fileName. 1857 * If there is no built-in profile with such name, then the method 1858 * returns null. 1859 */ 1860 private static InputStream getStandardProfileInputStream(String fileName) { 1861 return AccessController.doPrivileged( 1862 new PrivilegedAction<InputStream>() { 1863 public InputStream run () { 1864 return 1865 PCMM.class.getResourceAsStream("profiles/" + fileName); 1866 } 1867 }, null, new FilePermission("<<ALL FILES>>", "read")); 1868 } 1869 1870 /** 1871 * Checks whether given file resides inside give directory. 1872 */ 1873 private static boolean isChildOf(File f, String dirName) { 1874 try { 1875 File dir = new File(dirName); 1876 String canonicalDirName = dir.getCanonicalPath(); 1877 if (!canonicalDirName.endsWith(File.separator)) { 1878 canonicalDirName += File.separator; 1879 } 1880 String canonicalFileName = f.getCanonicalPath(); 1881 return canonicalFileName.startsWith(canonicalDirName); 1882 } catch (IOException e) { 1883 /* we do not expect the IOException here, because invocation 1884 * of this function is always preceded by isFile() call. 1885 */ 1886 return false; 1887 } 1888 } 1889 1890 /** 1891 * Checks whether built-in profile specified by fileName exists. 1892 */ 1893 private static boolean standardProfileExists(final String fileName) { 1894 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 1895 public Boolean run() { 1896 return PCMM.class.getResource("profiles/"+fileName) != null; 1897 } 1898 }); 1899 } 1900 1901 1902 /* 1903 * Serialization support. 1904 * 1905 * Directly deserialized profiles are useless since they are not 1906 * registered with CMM. We don't allow constructor to be called 1907 * directly and instead have clients to call one of getInstance 1908 * factory methods that will register the profile with CMM. For 1909 * deserialization we implement readResolve method that will 1910 * resolve the bogus deserialized profile object with one obtained 1911 * with getInstance as well. 1912 * 1913 * There are two primary factory methods for construction of ICC 1914 * profiles: getInstance(int cspace) and getInstance(byte[] data). 1915 * This implementation of ICC_Profile uses the former to return a 1916 * cached singleton profile object, other implementations will 1917 * likely use this technique too. To preserve the singleton 1918 * pattern across serialization we serialize cached singleton 1919 * profiles in such a way that deserializing VM could call 1920 * getInstance(int cspace) method that will resolve deserialized 1921 * object into the corresponding singleton as well. 1922 * 1923 * Since the singletons are private to ICC_Profile the readResolve 1924 * method have to be `protected' instead of `private' so that 1925 * singletons that are instances of subclasses of ICC_Profile 1926 * could be correctly deserialized. 1927 */ 1928 1929 1930 /** 1931 * Version of the format of additional serialized data in the 1932 * stream. Version {@code 1} corresponds to Java 2 1933 * Platform, v1.3. 1934 * @since 1.3 1935 * @serial 1936 */ 1937 private int iccProfileSerializedDataVersion = 1; 1938 1939 1940 /** 1941 * Writes default serializable fields to the stream. Writes a 1942 * string and an array of bytes to the stream as additional data. 1943 * 1944 * @param s stream used for serialization. 1945 * @throws IOException 1946 * thrown by {@code ObjectInputStream}. 1947 * @serialData 1948 * The {@code String} is the name of one of 1949 * <code>CS_<var>*</var></code> constants defined in the 1950 * {@link ColorSpace} class if the profile object is a profile 1951 * for a predefined color space (for example 1952 * {@code "CS_sRGB"}). The string is {@code null} 1953 * otherwise. 1954 * <p> 1955 * The {@code byte[]} array is the profile data for the 1956 * profile. For predefined color spaces {@code null} is 1957 * written instead of the profile data. If in the future 1958 * versions of Java API new predefined color spaces will be 1959 * added, future versions of this class may choose to write 1960 * for new predefined color spaces not only the color space 1961 * name, but the profile data as well so that older versions 1962 * could still deserialize the object. 1963 */ 1964 private void writeObject(ObjectOutputStream s) 1965 throws IOException 1966 { 1967 s.defaultWriteObject(); 1968 1969 String csName = null; 1970 if (this == sRGBprofile) { 1971 csName = "CS_sRGB"; 1972 } else if (this == XYZprofile) { 1973 csName = "CS_CIEXYZ"; 1974 } else if (this == PYCCprofile) { 1975 csName = "CS_PYCC"; 1976 } else if (this == GRAYprofile) { 1977 csName = "CS_GRAY"; 1978 } else if (this == LINEAR_RGBprofile) { 1979 csName = "CS_LINEAR_RGB"; 1980 } 1981 1982 // Future versions may choose to write profile data for new 1983 // predefined color spaces as well, if any will be introduced, 1984 // so that old versions that don't recognize the new CS name 1985 // may fall back to constructing profile from the data. 1986 byte[] data = null; 1987 if (csName == null) { 1988 // getData will activate deferred profile if necessary 1989 data = getData(); 1990 } 1991 1992 s.writeObject(csName); 1993 s.writeObject(data); 1994 } 1995 1996 // Temporary storage used by readObject to store resolved profile 1997 // (obtained with getInstance) for readResolve to return. 1998 private transient ICC_Profile resolvedDeserializedProfile; 1999 2000 /** 2001 * Reads default serializable fields from the stream. Reads from 2002 * the stream a string and an array of bytes as additional data. 2003 * 2004 * @param s stream used for deserialization. 2005 * @throws IOException 2006 * thrown by {@code ObjectInputStream}. 2007 * @throws ClassNotFoundException 2008 * thrown by {@code ObjectInputStream}. 2009 * @serialData 2010 * The {@code String} is the name of one of 2011 * <code>CS_<var>*</var></code> constants defined in the 2012 * {@link ColorSpace} class if the profile object is a profile 2013 * for a predefined color space (for example 2014 * {@code "CS_sRGB"}). The string is {@code null} 2015 * otherwise. 2016 * <p> 2017 * The {@code byte[]} array is the profile data for the 2018 * profile. It will usually be {@code null} for the 2019 * predefined profiles. 2020 * <p> 2021 * If the string is recognized as a constant name for 2022 * predefined color space the object will be resolved into 2023 * profile obtained with 2024 * <code>getInstance(int cspace)</code> and the profile 2025 * data are ignored. Otherwise the object will be resolved 2026 * into profile obtained with 2027 * <code>getInstance(byte[] data)</code>. 2028 * @see #readResolve() 2029 * @see #getInstance(int) 2030 * @see #getInstance(byte[]) 2031 */ 2032 private void readObject(ObjectInputStream s) 2033 throws IOException, ClassNotFoundException 2034 { 2035 s.defaultReadObject(); 2036 2037 String csName = (String)s.readObject(); 2038 byte[] data = (byte[])s.readObject(); 2039 2040 int cspace = 0; // ColorSpace.CS_* constant if known 2041 boolean isKnownPredefinedCS = false; 2042 if (csName != null) { 2043 isKnownPredefinedCS = true; 2044 if (csName.equals("CS_sRGB")) { 2045 cspace = ColorSpace.CS_sRGB; 2046 } else if (csName.equals("CS_CIEXYZ")) { 2047 cspace = ColorSpace.CS_CIEXYZ; 2048 } else if (csName.equals("CS_PYCC")) { 2049 cspace = ColorSpace.CS_PYCC; 2050 } else if (csName.equals("CS_GRAY")) { 2051 cspace = ColorSpace.CS_GRAY; 2052 } else if (csName.equals("CS_LINEAR_RGB")) { 2053 cspace = ColorSpace.CS_LINEAR_RGB; 2054 } else { 2055 isKnownPredefinedCS = false; 2056 } 2057 } 2058 2059 if (isKnownPredefinedCS) { 2060 resolvedDeserializedProfile = getInstance(cspace); 2061 } else { 2062 resolvedDeserializedProfile = getInstance(data); 2063 } 2064 } 2065 2066 /** 2067 * Resolves instances being deserialized into instances registered 2068 * with CMM. 2069 * @return ICC_Profile object for profile registered with CMM. 2070 * @throws ObjectStreamException 2071 * never thrown, but mandated by the serialization spec. 2072 * @since 1.3 2073 */ 2074 protected Object readResolve() throws ObjectStreamException { 2075 return resolvedDeserializedProfile; 2076 } 2077 }