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