1 /* 2 * Copyright (c) 1997, 2017, 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 * @deprecated The {@code finalize} method has been deprecated. 756 * Subclasses that override {@code finalize} in order to perform cleanup 757 * should be modified to use alternative cleanup mechanisms and 758 * to remove the overriding {@code finalize} method. 759 * When overriding the {@code finalize} method, its implementation must explicitly 760 * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. 761 * See the specification for {@link Object#finalize()} for further 762 * information about migration options. 763 */ 764 @Deprecated(since="9") 765 protected void finalize () { 766 if (cmmProfile != null) { 767 CMSManager.getModule().freeProfile(cmmProfile); 768 } else if (profileActivator != null) { 769 ProfileDeferralMgr.unregisterDeferral(profileActivator); 770 } 771 } 772 773 774 /** 775 * Constructs an ICC_Profile object corresponding to the data in 776 * a byte array. Throws an IllegalArgumentException if the data 777 * does not correspond to a valid ICC Profile. 778 * @param data the specified ICC Profile data 779 * @return an {@code ICC_Profile} object corresponding to 780 * the data in the specified {@code data} array. 781 */ 782 public static ICC_Profile getInstance(byte[] data) { 783 ICC_Profile thisProfile; 784 785 Profile p = null; 786 787 if (ProfileDeferralMgr.deferring) { 788 ProfileDeferralMgr.activateProfiles(); 789 } 790 791 ProfileDataVerifier.verify(data); 792 793 try { 794 p = CMSManager.getModule().loadProfile(data); 795 } catch (CMMException c) { 796 throw new IllegalArgumentException("Invalid ICC Profile Data"); 797 } 798 799 try { 800 if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) && 801 (getData (p, icSigMediaWhitePointTag) != null) && 802 (getData (p, icSigGrayTRCTag) != null)) { 803 thisProfile = new ICC_ProfileGray (p); 804 } 805 else if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) && 806 (getData (p, icSigMediaWhitePointTag) != null) && 807 (getData (p, icSigRedColorantTag) != null) && 808 (getData (p, icSigGreenColorantTag) != null) && 809 (getData (p, icSigBlueColorantTag) != null) && 810 (getData (p, icSigRedTRCTag) != null) && 811 (getData (p, icSigGreenTRCTag) != null) && 812 (getData (p, icSigBlueTRCTag) != null)) { 813 thisProfile = new ICC_ProfileRGB (p); 814 } 815 else { 816 thisProfile = new ICC_Profile (p); 817 } 818 } catch (CMMException c) { 819 thisProfile = new ICC_Profile (p); 820 } 821 return thisProfile; 822 } 823 824 825 826 /** 827 * Constructs an ICC_Profile corresponding to one of the specific color 828 * spaces defined by the ColorSpace class (for example CS_sRGB). 829 * Throws an IllegalArgumentException if cspace is not one of the 830 * defined color spaces. 831 * 832 * @param cspace the type of color space to create a profile for. 833 * The specified type is one of the color 834 * space constants defined in the {@code ColorSpace} class. 835 * 836 * @return an {@code ICC_Profile} object corresponding to 837 * the specified {@code ColorSpace} type. 838 * @exception IllegalArgumentException If {@code cspace} is not 839 * one of the predefined color space types. 840 */ 841 public static ICC_Profile getInstance (int cspace) { 842 ICC_Profile thisProfile = null; 843 String fileName; 844 845 switch (cspace) { 846 case ColorSpace.CS_sRGB: 847 synchronized(ICC_Profile.class) { 848 if (sRGBprofile == null) { 849 /* 850 * Deferral is only used for standard profiles. 851 * Enabling the appropriate access privileges is handled 852 * at a lower level. 853 */ 854 ProfileDeferralInfo pInfo = 855 new ProfileDeferralInfo("sRGB.pf", 856 ColorSpace.TYPE_RGB, 3, 857 CLASS_DISPLAY); 858 sRGBprofile = getDeferredInstance(pInfo); 859 } 860 thisProfile = sRGBprofile; 861 } 862 863 break; 864 865 case ColorSpace.CS_CIEXYZ: 866 synchronized(ICC_Profile.class) { 867 if (XYZprofile == null) { 868 ProfileDeferralInfo pInfo = 869 new ProfileDeferralInfo("CIEXYZ.pf", 870 ColorSpace.TYPE_XYZ, 3, 871 CLASS_DISPLAY); 872 XYZprofile = getDeferredInstance(pInfo); 873 } 874 thisProfile = XYZprofile; 875 } 876 877 break; 878 879 case ColorSpace.CS_PYCC: 880 synchronized(ICC_Profile.class) { 881 if (PYCCprofile == null) { 882 if (standardProfileExists("PYCC.pf")) 883 { 884 ProfileDeferralInfo pInfo = 885 new ProfileDeferralInfo("PYCC.pf", 886 ColorSpace.TYPE_3CLR, 3, 887 CLASS_DISPLAY); 888 PYCCprofile = getDeferredInstance(pInfo); 889 } else { 890 throw new IllegalArgumentException( 891 "Can't load standard profile: PYCC.pf"); 892 } 893 } 894 thisProfile = PYCCprofile; 895 } 896 897 break; 898 899 case ColorSpace.CS_GRAY: 900 synchronized(ICC_Profile.class) { 901 if (GRAYprofile == null) { 902 ProfileDeferralInfo pInfo = 903 new ProfileDeferralInfo("GRAY.pf", 904 ColorSpace.TYPE_GRAY, 1, 905 CLASS_DISPLAY); 906 GRAYprofile = getDeferredInstance(pInfo); 907 } 908 thisProfile = GRAYprofile; 909 } 910 911 break; 912 913 case ColorSpace.CS_LINEAR_RGB: 914 synchronized(ICC_Profile.class) { 915 if (LINEAR_RGBprofile == null) { 916 ProfileDeferralInfo pInfo = 917 new ProfileDeferralInfo("LINEAR_RGB.pf", 918 ColorSpace.TYPE_RGB, 3, 919 CLASS_DISPLAY); 920 LINEAR_RGBprofile = getDeferredInstance(pInfo); 921 } 922 thisProfile = LINEAR_RGBprofile; 923 } 924 925 break; 926 927 default: 928 throw new IllegalArgumentException("Unknown color space"); 929 } 930 931 return thisProfile; 932 } 933 934 /* This asserts system privileges, so is used only for the 935 * standard profiles. 936 */ 937 private static ICC_Profile getStandardProfile(final String name) { 938 939 return AccessController.doPrivileged( 940 new PrivilegedAction<ICC_Profile>() { 941 public ICC_Profile run() { 942 ICC_Profile p = null; 943 try { 944 p = getInstance (name); 945 } catch (IOException ex) { 946 throw new IllegalArgumentException( 947 "Can't load standard profile: " + name); 948 } 949 return p; 950 } 951 }); 952 } 953 954 /** 955 * Constructs an ICC_Profile corresponding to the data in a file. 956 * fileName may be an absolute or a relative file specification. 957 * Relative file names are looked for in several places: first, relative 958 * to any directories specified by the java.iccprofile.path property; 959 * second, relative to any directories specified by the java.class.path 960 * property; finally, in a directory used to store profiles always 961 * available, such as the profile for sRGB. Built-in profiles use .pf as 962 * the file name extension for profiles, e.g. sRGB.pf. 963 * This method throws an IOException if the specified file cannot be 964 * opened or if an I/O error occurs while reading the file. It throws 965 * an IllegalArgumentException if the file does not contain valid ICC 966 * Profile data. 967 * @param fileName The file that contains the data for the profile. 968 * 969 * @return an {@code ICC_Profile} object corresponding to 970 * the data in the specified file. 971 * @exception IOException If the specified file cannot be opened or 972 * an I/O error occurs while reading the file. 973 * 974 * @exception IllegalArgumentException If the file does not 975 * contain valid ICC Profile data. 976 * 977 * @exception SecurityException If a security manager is installed 978 * and it does not permit read access to the given file. 979 */ 980 public static ICC_Profile getInstance(String fileName) throws IOException { 981 ICC_Profile thisProfile; 982 InputStream is = null; 983 984 985 File f = getProfileFile(fileName); 986 if (f != null) { 987 is = new FileInputStream(f); 988 } else { 989 is = getStandardProfileInputStream(fileName); 990 } 991 if (is == null) { 992 throw new IOException("Cannot open file " + fileName); 993 } 994 995 thisProfile = getInstance(is); 996 997 is.close(); /* close the file */ 998 999 return thisProfile; 1000 } 1001 1002 1003 /** 1004 * Constructs an ICC_Profile corresponding to the data in an InputStream. 1005 * This method throws an IllegalArgumentException if the stream does not 1006 * contain valid ICC Profile data. It throws an IOException if an I/O 1007 * error occurs while reading the stream. 1008 * @param s The input stream from which to read the profile data. 1009 * 1010 * @return an {@code ICC_Profile} object corresponding to the 1011 * data in the specified {@code InputStream}. 1012 * 1013 * @exception IOException If an I/O error occurs while reading the stream. 1014 * 1015 * @exception IllegalArgumentException If the stream does not 1016 * contain valid ICC Profile data. 1017 */ 1018 public static ICC_Profile getInstance(InputStream s) throws IOException { 1019 byte profileData[]; 1020 1021 if (s instanceof ProfileDeferralInfo) { 1022 /* hack to detect profiles whose loading can be deferred */ 1023 return getDeferredInstance((ProfileDeferralInfo) s); 1024 } 1025 1026 if ((profileData = getProfileDataFromStream(s)) == null) { 1027 throw new IllegalArgumentException("Invalid ICC Profile Data"); 1028 } 1029 1030 return getInstance(profileData); 1031 } 1032 1033 1034 static byte[] getProfileDataFromStream(InputStream s) throws IOException { 1035 byte profileData[]; 1036 int profileSize; 1037 1038 byte header[] = new byte[128]; 1039 int bytestoread = 128; 1040 int bytesread = 0; 1041 int n; 1042 1043 while (bytestoread != 0) { 1044 if ((n = s.read(header, bytesread, bytestoread)) < 0) { 1045 return null; 1046 } 1047 bytesread += n; 1048 bytestoread -= n; 1049 } 1050 if (header[36] != 0x61 || header[37] != 0x63 || 1051 header[38] != 0x73 || header[39] != 0x70) { 1052 return null; /* not a valid profile */ 1053 } 1054 profileSize = ((header[0] & 0xff) << 24) | 1055 ((header[1] & 0xff) << 16) | 1056 ((header[2] & 0xff) << 8) | 1057 (header[3] & 0xff); 1058 profileData = new byte[profileSize]; 1059 System.arraycopy(header, 0, profileData, 0, 128); 1060 bytestoread = profileSize - 128; 1061 bytesread = 128; 1062 while (bytestoread != 0) { 1063 if ((n = s.read(profileData, bytesread, bytestoread)) < 0) { 1064 return null; 1065 } 1066 bytesread += n; 1067 bytestoread -= n; 1068 } 1069 1070 return profileData; 1071 } 1072 1073 1074 /** 1075 * Constructs an ICC_Profile for which the actual loading of the 1076 * profile data from a file and the initialization of the CMM should 1077 * be deferred as long as possible. 1078 * Deferral is only used for standard profiles. 1079 * If deferring is disabled, then getStandardProfile() ensures 1080 * that all of the appropriate access privileges are granted 1081 * when loading this profile. 1082 * If deferring is enabled, then the deferred activation 1083 * code will take care of access privileges. 1084 * @see #activateDeferredProfile() 1085 */ 1086 static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) { 1087 if (!ProfileDeferralMgr.deferring) { 1088 return getStandardProfile(pdi.filename); 1089 } 1090 if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) { 1091 return new ICC_ProfileRGB(pdi); 1092 } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) { 1093 return new ICC_ProfileGray(pdi); 1094 } else { 1095 return new ICC_Profile(pdi); 1096 } 1097 } 1098 1099 1100 void activateDeferredProfile() throws ProfileDataException { 1101 byte profileData[]; 1102 final String fileName = deferralInfo.filename; 1103 1104 profileActivator = null; 1105 deferralInfo = null; 1106 InputStream is = getStandardProfileInputStream(fileName); 1107 if (is == null) { 1108 throw new ProfileDataException("Cannot open file " + fileName); 1109 } 1110 try { 1111 profileData = getProfileDataFromStream(is); 1112 is.close(); /* close the file */ 1113 } 1114 catch (IOException e) { 1115 ProfileDataException pde = new 1116 ProfileDataException("Invalid ICC Profile Data" + fileName); 1117 pde.initCause(e); 1118 throw pde; 1119 } 1120 if (profileData == null) { 1121 throw new ProfileDataException("Invalid ICC Profile Data" + 1122 fileName); 1123 } 1124 try { 1125 cmmProfile = CMSManager.getModule().loadProfile(profileData); 1126 } catch (CMMException c) { 1127 ProfileDataException pde = new 1128 ProfileDataException("Invalid ICC Profile Data" + fileName); 1129 pde.initCause(c); 1130 throw pde; 1131 } 1132 } 1133 1134 1135 /** 1136 * Returns profile major version. 1137 * @return The major version of the profile. 1138 */ 1139 public int getMajorVersion() { 1140 byte[] theHeader; 1141 1142 theHeader = getData(icSigHead); /* getData will activate deferred 1143 profiles if necessary */ 1144 1145 return (int) theHeader[8]; 1146 } 1147 1148 /** 1149 * Returns profile minor version. 1150 * @return The minor version of the profile. 1151 */ 1152 public int getMinorVersion() { 1153 byte[] theHeader; 1154 1155 theHeader = getData(icSigHead); /* getData will activate deferred 1156 profiles if necessary */ 1157 1158 return (int) theHeader[9]; 1159 } 1160 1161 /** 1162 * Returns the profile class. 1163 * @return One of the predefined profile class constants. 1164 */ 1165 public int getProfileClass() { 1166 byte[] theHeader; 1167 int theClassSig, theClass; 1168 1169 if (deferralInfo != null) { 1170 return deferralInfo.profileClass; /* Need to have this info for 1171 ICC_ColorSpace without 1172 causing a deferred profile 1173 to be loaded */ 1174 } 1175 1176 theHeader = getData(icSigHead); 1177 1178 theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass); 1179 1180 switch (theClassSig) { 1181 case icSigInputClass: 1182 theClass = CLASS_INPUT; 1183 break; 1184 1185 case icSigDisplayClass: 1186 theClass = CLASS_DISPLAY; 1187 break; 1188 1189 case icSigOutputClass: 1190 theClass = CLASS_OUTPUT; 1191 break; 1192 1193 case icSigLinkClass: 1194 theClass = CLASS_DEVICELINK; 1195 break; 1196 1197 case icSigColorSpaceClass: 1198 theClass = CLASS_COLORSPACECONVERSION; 1199 break; 1200 1201 case icSigAbstractClass: 1202 theClass = CLASS_ABSTRACT; 1203 break; 1204 1205 case icSigNamedColorClass: 1206 theClass = CLASS_NAMEDCOLOR; 1207 break; 1208 1209 default: 1210 throw new IllegalArgumentException("Unknown profile class"); 1211 } 1212 1213 return theClass; 1214 } 1215 1216 /** 1217 * Returns the color space type. Returns one of the color space type 1218 * constants defined by the ColorSpace class. This is the 1219 * "input" color space of the profile. The type defines the 1220 * number of components of the color space and the interpretation, 1221 * e.g. TYPE_RGB identifies a color space with three components - red, 1222 * green, and blue. It does not define the particular color 1223 * characteristics of the space, e.g. the chromaticities of the 1224 * primaries. 1225 * @return One of the color space type constants defined in the 1226 * {@code ColorSpace} class. 1227 */ 1228 public int getColorSpaceType() { 1229 if (deferralInfo != null) { 1230 return deferralInfo.colorSpaceType; /* Need to have this info for 1231 ICC_ColorSpace without 1232 causing a deferred profile 1233 to be loaded */ 1234 } 1235 return getColorSpaceType(cmmProfile); 1236 } 1237 1238 static int getColorSpaceType(Profile p) { 1239 byte[] theHeader; 1240 int theColorSpaceSig, theColorSpace; 1241 1242 theHeader = getData(p, icSigHead); 1243 theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); 1244 theColorSpace = iccCStoJCS (theColorSpaceSig); 1245 return theColorSpace; 1246 } 1247 1248 /** 1249 * Returns the color space type of the Profile Connection Space (PCS). 1250 * Returns one of the color space type constants defined by the 1251 * ColorSpace class. This is the "output" color space of the 1252 * profile. For an input, display, or output profile useful 1253 * for tagging colors or images, this will be either TYPE_XYZ or 1254 * TYPE_Lab and should be interpreted as the corresponding specific 1255 * color space defined in the ICC specification. For a device 1256 * link profile, this could be any of the color space type constants. 1257 * @return One of the color space type constants defined in the 1258 * {@code ColorSpace} class. 1259 */ 1260 public int getPCSType() { 1261 if (ProfileDeferralMgr.deferring) { 1262 ProfileDeferralMgr.activateProfiles(); 1263 } 1264 return getPCSType(cmmProfile); 1265 } 1266 1267 1268 static int getPCSType(Profile p) { 1269 byte[] theHeader; 1270 int thePCSSig, thePCS; 1271 1272 theHeader = getData(p, icSigHead); 1273 thePCSSig = intFromBigEndian(theHeader, icHdrPcs); 1274 thePCS = iccCStoJCS(thePCSSig); 1275 return thePCS; 1276 } 1277 1278 1279 /** 1280 * Write this ICC_Profile to a file. 1281 * 1282 * @param fileName The file to write the profile data to. 1283 * 1284 * @exception IOException If the file cannot be opened for writing 1285 * or an I/O error occurs while writing to the file. 1286 */ 1287 public void write(String fileName) throws IOException { 1288 FileOutputStream outputFile; 1289 byte profileData[]; 1290 1291 profileData = getData(); /* this will activate deferred 1292 profiles if necessary */ 1293 outputFile = new FileOutputStream(fileName); 1294 outputFile.write(profileData); 1295 outputFile.close (); 1296 } 1297 1298 1299 /** 1300 * Write this ICC_Profile to an OutputStream. 1301 * 1302 * @param s The stream to write the profile data to. 1303 * 1304 * @exception IOException If an I/O error occurs while writing to the 1305 * stream. 1306 */ 1307 public void write(OutputStream s) throws IOException { 1308 byte profileData[]; 1309 1310 profileData = getData(); /* this will activate deferred 1311 profiles if necessary */ 1312 s.write(profileData); 1313 } 1314 1315 1316 /** 1317 * Returns a byte array corresponding to the data of this ICC_Profile. 1318 * @return A byte array that contains the profile data. 1319 * @see #setData(int, byte[]) 1320 */ 1321 public byte[] getData() { 1322 int profileSize; 1323 byte[] profileData; 1324 1325 if (ProfileDeferralMgr.deferring) { 1326 ProfileDeferralMgr.activateProfiles(); 1327 } 1328 1329 PCMM mdl = CMSManager.getModule(); 1330 1331 /* get the number of bytes needed for this profile */ 1332 profileSize = mdl.getProfileSize(cmmProfile); 1333 1334 profileData = new byte [profileSize]; 1335 1336 /* get the data for the profile */ 1337 mdl.getProfileData(cmmProfile, profileData); 1338 1339 return profileData; 1340 } 1341 1342 1343 /** 1344 * Returns a particular tagged data element from the profile as 1345 * a byte array. Elements are identified by signatures 1346 * as defined in the ICC specification. The signature 1347 * icSigHead can be used to get the header. This method is useful 1348 * for advanced applets or applications which need to access 1349 * profile data directly. 1350 * 1351 * @param tagSignature The ICC tag signature for the data element you 1352 * want to get. 1353 * 1354 * @return A byte array that contains the tagged data element. Returns 1355 * {@code null} if the specified tag doesn't exist. 1356 * @see #setData(int, byte[]) 1357 */ 1358 public byte[] getData(int tagSignature) { 1359 1360 if (ProfileDeferralMgr.deferring) { 1361 ProfileDeferralMgr.activateProfiles(); 1362 } 1363 1364 return getData(cmmProfile, tagSignature); 1365 } 1366 1367 1368 static byte[] getData(Profile p, int tagSignature) { 1369 int tagSize; 1370 byte[] tagData; 1371 1372 try { 1373 PCMM mdl = CMSManager.getModule(); 1374 1375 /* get the number of bytes needed for this tag */ 1376 tagSize = mdl.getTagSize(p, tagSignature); 1377 1378 tagData = new byte[tagSize]; /* get an array for the tag */ 1379 1380 /* get the tag's data */ 1381 mdl.getTagData(p, tagSignature, tagData); 1382 } catch(CMMException c) { 1383 tagData = null; 1384 } 1385 1386 return tagData; 1387 } 1388 1389 /** 1390 * Sets a particular tagged data element in the profile from 1391 * a byte array. The array should contain data in a format, corresponded 1392 * to the {@code tagSignature} as defined in the ICC specification, section 10. 1393 * This method is useful for advanced applets or applications which need to 1394 * access profile data directly. 1395 * 1396 * @param tagSignature The ICC tag signature for the data element 1397 * you want to set. 1398 * @param tagData the data to set for the specified tag signature 1399 * @throws IllegalArgumentException if {@code tagSignature} is not a signature 1400 * as defined in the ICC specification. 1401 * @throws IllegalArgumentException if a content of the {@code tagData} 1402 * array can not be interpreted as valid tag data, corresponding 1403 * to the {@code tagSignature}. 1404 * @see #getData 1405 */ 1406 public void setData(int tagSignature, byte[] tagData) { 1407 1408 if (ProfileDeferralMgr.deferring) { 1409 ProfileDeferralMgr.activateProfiles(); 1410 } 1411 1412 CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData); 1413 } 1414 1415 /** 1416 * Sets the rendering intent of the profile. 1417 * This is used to select the proper transform from a profile that 1418 * has multiple transforms. 1419 */ 1420 void setRenderingIntent(int renderingIntent) { 1421 byte[] theHeader = getData(icSigHead);/* getData will activate deferred 1422 profiles if necessary */ 1423 intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent); 1424 /* set the rendering intent */ 1425 setData (icSigHead, theHeader); 1426 } 1427 1428 1429 /** 1430 * Returns the rendering intent of the profile. 1431 * This is used to select the proper transform from a profile that 1432 * has multiple transforms. It is typically set in a source profile 1433 * to select a transform from an output profile. 1434 */ 1435 int getRenderingIntent() { 1436 byte[] theHeader = getData(icSigHead);/* getData will activate deferred 1437 profiles if necessary */ 1438 1439 int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent); 1440 /* set the rendering intent */ 1441 1442 /* According to ICC spec, only the least-significant 16 bits shall be 1443 * used to encode the rendering intent. The most significant 16 bits 1444 * shall be set to zero. Thus, we are ignoring two most significant 1445 * bytes here. 1446 * 1447 * See http://www.color.org/ICC1v42_2006-05.pdf, section 7.2.15. 1448 */ 1449 return (0xffff & renderingIntent); 1450 } 1451 1452 1453 /** 1454 * Returns the number of color components in the "input" color 1455 * space of this profile. For example if the color space type 1456 * of this profile is TYPE_RGB, then this method will return 3. 1457 * 1458 * @return The number of color components in the profile's input 1459 * color space. 1460 * 1461 * @throws ProfileDataException if color space is in the profile 1462 * is invalid 1463 */ 1464 public int getNumComponents() { 1465 byte[] theHeader; 1466 int theColorSpaceSig, theNumComponents; 1467 1468 if (deferralInfo != null) { 1469 return deferralInfo.numComponents; /* Need to have this info for 1470 ICC_ColorSpace without 1471 causing a deferred profile 1472 to be loaded */ 1473 } 1474 theHeader = getData(icSigHead); 1475 1476 theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace); 1477 1478 switch (theColorSpaceSig) { 1479 case icSigGrayData: 1480 theNumComponents = 1; 1481 break; 1482 1483 case icSigSpace2CLR: 1484 theNumComponents = 2; 1485 break; 1486 1487 case icSigXYZData: 1488 case icSigLabData: 1489 case icSigLuvData: 1490 case icSigYCbCrData: 1491 case icSigYxyData: 1492 case icSigRgbData: 1493 case icSigHsvData: 1494 case icSigHlsData: 1495 case icSigCmyData: 1496 case icSigSpace3CLR: 1497 theNumComponents = 3; 1498 break; 1499 1500 case icSigCmykData: 1501 case icSigSpace4CLR: 1502 theNumComponents = 4; 1503 break; 1504 1505 case icSigSpace5CLR: 1506 theNumComponents = 5; 1507 break; 1508 1509 case icSigSpace6CLR: 1510 theNumComponents = 6; 1511 break; 1512 1513 case icSigSpace7CLR: 1514 theNumComponents = 7; 1515 break; 1516 1517 case icSigSpace8CLR: 1518 theNumComponents = 8; 1519 break; 1520 1521 case icSigSpace9CLR: 1522 theNumComponents = 9; 1523 break; 1524 1525 case icSigSpaceACLR: 1526 theNumComponents = 10; 1527 break; 1528 1529 case icSigSpaceBCLR: 1530 theNumComponents = 11; 1531 break; 1532 1533 case icSigSpaceCCLR: 1534 theNumComponents = 12; 1535 break; 1536 1537 case icSigSpaceDCLR: 1538 theNumComponents = 13; 1539 break; 1540 1541 case icSigSpaceECLR: 1542 theNumComponents = 14; 1543 break; 1544 1545 case icSigSpaceFCLR: 1546 theNumComponents = 15; 1547 break; 1548 1549 default: 1550 throw new ProfileDataException ("invalid ICC color space"); 1551 } 1552 1553 return theNumComponents; 1554 } 1555 1556 1557 /** 1558 * Returns a float array of length 3 containing the X, Y, and Z 1559 * components of the mediaWhitePointTag in the ICC profile. 1560 */ 1561 float[] getMediaWhitePoint() { 1562 return getXYZTag(icSigMediaWhitePointTag); 1563 /* get the media white point tag */ 1564 } 1565 1566 1567 /** 1568 * Returns a float array of length 3 containing the X, Y, and Z 1569 * components encoded in an XYZType tag. 1570 */ 1571 float[] getXYZTag(int theTagSignature) { 1572 byte[] theData; 1573 float[] theXYZNumber; 1574 int i1, i2, theS15Fixed16; 1575 1576 theData = getData(theTagSignature); /* get the tag data */ 1577 /* getData will activate deferred 1578 profiles if necessary */ 1579 1580 theXYZNumber = new float [3]; /* array to return */ 1581 1582 /* convert s15Fixed16Number to float */ 1583 for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) { 1584 theS15Fixed16 = intFromBigEndian(theData, i2); 1585 theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f; 1586 } 1587 return theXYZNumber; 1588 } 1589 1590 1591 /** 1592 * Returns a gamma value representing a tone reproduction 1593 * curve (TRC). If the profile represents the TRC as a table rather 1594 * than a single gamma value, then an exception is thrown. In this 1595 * case the actual table can be obtained via getTRC(). 1596 * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag, 1597 * icSigGreenTRCTag, or icSigBlueTRCTag. 1598 * @return the gamma value as a float. 1599 * @exception ProfileDataException if the profile does not specify 1600 * the TRC as a single gamma value. 1601 */ 1602 float getGamma(int theTagSignature) { 1603 byte[] theTRCData; 1604 float theGamma; 1605 int theU8Fixed8; 1606 1607 theTRCData = getData(theTagSignature); /* get the TRC */ 1608 /* getData will activate deferred 1609 profiles if necessary */ 1610 1611 if (intFromBigEndian (theTRCData, icCurveCount) != 1) { 1612 throw new ProfileDataException ("TRC is not a gamma"); 1613 } 1614 1615 /* convert u8Fixed8 to float */ 1616 theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff; 1617 1618 theGamma = ((float) theU8Fixed8) / 256.0f; 1619 1620 return theGamma; 1621 } 1622 1623 1624 /** 1625 * Returns the TRC as an array of shorts. If the profile has 1626 * specified the TRC as linear (gamma = 1.0) or as a simple gamma 1627 * value, this method throws an exception, and the getGamma() method 1628 * should be used to get the gamma value. Otherwise the short array 1629 * returned here represents a lookup table where the input Gray value 1630 * is conceptually in the range [0.0, 1.0]. Value 0.0 maps 1631 * to array index 0 and value 1.0 maps to array index length-1. 1632 * Interpolation may be used to generate output values for 1633 * input values which do not map exactly to an index in the 1634 * array. Output values also map linearly to the range [0.0, 1.0]. 1635 * Value 0.0 is represented by an array value of 0x0000 and 1636 * value 1.0 by 0xFFFF, i.e. the values are really unsigned 1637 * short values, although they are returned in a short array. 1638 * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag, 1639 * icSigGreenTRCTag, or icSigBlueTRCTag. 1640 * @return a short array representing the TRC. 1641 * @exception ProfileDataException if the profile does not specify 1642 * the TRC as a table. 1643 */ 1644 short[] getTRC(int theTagSignature) { 1645 byte[] theTRCData; 1646 short[] theTRC; 1647 int i1, i2, nElements, theU8Fixed8; 1648 1649 theTRCData = getData(theTagSignature); /* get the TRC */ 1650 /* getData will activate deferred 1651 profiles if necessary */ 1652 1653 nElements = intFromBigEndian(theTRCData, icCurveCount); 1654 1655 if (nElements == 1) { 1656 throw new ProfileDataException("TRC is not a table"); 1657 } 1658 1659 /* make the short array */ 1660 theTRC = new short [nElements]; 1661 1662 for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) { 1663 theTRC[i1] = shortFromBigEndian(theTRCData, i2); 1664 } 1665 1666 return theTRC; 1667 } 1668 1669 1670 /* convert an ICC color space signature into a Java color space type */ 1671 static int iccCStoJCS(int theColorSpaceSig) { 1672 int theColorSpace; 1673 1674 switch (theColorSpaceSig) { 1675 case icSigXYZData: 1676 theColorSpace = ColorSpace.TYPE_XYZ; 1677 break; 1678 1679 case icSigLabData: 1680 theColorSpace = ColorSpace.TYPE_Lab; 1681 break; 1682 1683 case icSigLuvData: 1684 theColorSpace = ColorSpace.TYPE_Luv; 1685 break; 1686 1687 case icSigYCbCrData: 1688 theColorSpace = ColorSpace.TYPE_YCbCr; 1689 break; 1690 1691 case icSigYxyData: 1692 theColorSpace = ColorSpace.TYPE_Yxy; 1693 break; 1694 1695 case icSigRgbData: 1696 theColorSpace = ColorSpace.TYPE_RGB; 1697 break; 1698 1699 case icSigGrayData: 1700 theColorSpace = ColorSpace.TYPE_GRAY; 1701 break; 1702 1703 case icSigHsvData: 1704 theColorSpace = ColorSpace.TYPE_HSV; 1705 break; 1706 1707 case icSigHlsData: 1708 theColorSpace = ColorSpace.TYPE_HLS; 1709 break; 1710 1711 case icSigCmykData: 1712 theColorSpace = ColorSpace.TYPE_CMYK; 1713 break; 1714 1715 case icSigCmyData: 1716 theColorSpace = ColorSpace.TYPE_CMY; 1717 break; 1718 1719 case icSigSpace2CLR: 1720 theColorSpace = ColorSpace.TYPE_2CLR; 1721 break; 1722 1723 case icSigSpace3CLR: 1724 theColorSpace = ColorSpace.TYPE_3CLR; 1725 break; 1726 1727 case icSigSpace4CLR: 1728 theColorSpace = ColorSpace.TYPE_4CLR; 1729 break; 1730 1731 case icSigSpace5CLR: 1732 theColorSpace = ColorSpace.TYPE_5CLR; 1733 break; 1734 1735 case icSigSpace6CLR: 1736 theColorSpace = ColorSpace.TYPE_6CLR; 1737 break; 1738 1739 case icSigSpace7CLR: 1740 theColorSpace = ColorSpace.TYPE_7CLR; 1741 break; 1742 1743 case icSigSpace8CLR: 1744 theColorSpace = ColorSpace.TYPE_8CLR; 1745 break; 1746 1747 case icSigSpace9CLR: 1748 theColorSpace = ColorSpace.TYPE_9CLR; 1749 break; 1750 1751 case icSigSpaceACLR: 1752 theColorSpace = ColorSpace.TYPE_ACLR; 1753 break; 1754 1755 case icSigSpaceBCLR: 1756 theColorSpace = ColorSpace.TYPE_BCLR; 1757 break; 1758 1759 case icSigSpaceCCLR: 1760 theColorSpace = ColorSpace.TYPE_CCLR; 1761 break; 1762 1763 case icSigSpaceDCLR: 1764 theColorSpace = ColorSpace.TYPE_DCLR; 1765 break; 1766 1767 case icSigSpaceECLR: 1768 theColorSpace = ColorSpace.TYPE_ECLR; 1769 break; 1770 1771 case icSigSpaceFCLR: 1772 theColorSpace = ColorSpace.TYPE_FCLR; 1773 break; 1774 1775 default: 1776 throw new IllegalArgumentException ("Unknown color space"); 1777 } 1778 1779 return theColorSpace; 1780 } 1781 1782 1783 static int intFromBigEndian(byte[] array, int index) { 1784 return (((array[index] & 0xff) << 24) | 1785 ((array[index+1] & 0xff) << 16) | 1786 ((array[index+2] & 0xff) << 8) | 1787 (array[index+3] & 0xff)); 1788 } 1789 1790 1791 static void intToBigEndian(int value, byte[] array, int index) { 1792 array[index] = (byte) (value >> 24); 1793 array[index+1] = (byte) (value >> 16); 1794 array[index+2] = (byte) (value >> 8); 1795 array[index+3] = (byte) (value); 1796 } 1797 1798 1799 static short shortFromBigEndian(byte[] array, int index) { 1800 return (short) (((array[index] & 0xff) << 8) | 1801 (array[index+1] & 0xff)); 1802 } 1803 1804 1805 static void shortToBigEndian(short value, byte[] array, int index) { 1806 array[index] = (byte) (value >> 8); 1807 array[index+1] = (byte) (value); 1808 } 1809 1810 1811 /* 1812 * fileName may be an absolute or a relative file specification. 1813 * Relative file names are looked for in several places: first, relative 1814 * to any directories specified by the java.iccprofile.path property; 1815 * second, relative to any directories specified by the java.class.path. 1816 * The built-in profile files are now loaded as resources, since they 1817 * may not be individual disk files, and so this method will not find 1818 * these and on a null return, the caller needs to try as resources. 1819 * Built-in profiles use .pf as the file name extension for profiles, 1820 * e.g. sRGB.pf. 1821 */ 1822 private static File getProfileFile(String fileName) { 1823 String path, dir, fullPath; 1824 1825 File f = new File(fileName); /* try absolute file name */ 1826 if (f.isAbsolute()) { 1827 /* Rest of code has little sense for an absolute pathname, 1828 so return here. */ 1829 return f.isFile() ? f : null; 1830 } 1831 if ((!f.isFile()) && 1832 ((path = System.getProperty("java.iccprofile.path")) != null)){ 1833 /* try relative to java.iccprofile.path */ 1834 StringTokenizer st = 1835 new StringTokenizer(path, File.pathSeparator); 1836 while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) { 1837 dir = st.nextToken(); 1838 fullPath = dir + File.separatorChar + fileName; 1839 f = new File(fullPath); 1840 if (!isChildOf(f, dir)) { 1841 f = null; 1842 } 1843 } 1844 } 1845 1846 if (((f == null) || (!f.isFile())) && 1847 ((path = System.getProperty("java.class.path")) != null)) { 1848 /* try relative to java.class.path */ 1849 StringTokenizer st = 1850 new StringTokenizer(path, File.pathSeparator); 1851 while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) { 1852 dir = st.nextToken(); 1853 fullPath = dir + File.separatorChar + fileName; 1854 f = new File(fullPath); 1855 } 1856 } 1857 1858 if (f != null && !f.isFile()) { 1859 f = null; 1860 } 1861 return f; 1862 } 1863 1864 /** 1865 * Returns a stream corresponding to a built-in profile 1866 * specified by fileName. 1867 * If there is no built-in profile with such name, then the method 1868 * returns null. 1869 */ 1870 private static InputStream getStandardProfileInputStream(String fileName) { 1871 return AccessController.doPrivileged( 1872 new PrivilegedAction<InputStream>() { 1873 public InputStream run () { 1874 return 1875 PCMM.class.getResourceAsStream("profiles/" + fileName); 1876 } 1877 }, null, new FilePermission("<<ALL FILES>>", "read"), 1878 new RuntimePermission("accessSystemModules")); 1879 } 1880 1881 /** 1882 * Checks whether given file resides inside give directory. 1883 */ 1884 private static boolean isChildOf(File f, String dirName) { 1885 try { 1886 File dir = new File(dirName); 1887 String canonicalDirName = dir.getCanonicalPath(); 1888 if (!canonicalDirName.endsWith(File.separator)) { 1889 canonicalDirName += File.separator; 1890 } 1891 String canonicalFileName = f.getCanonicalPath(); 1892 return canonicalFileName.startsWith(canonicalDirName); 1893 } catch (IOException e) { 1894 /* we do not expect the IOException here, because invocation 1895 * of this function is always preceded by isFile() call. 1896 */ 1897 return false; 1898 } 1899 } 1900 1901 /** 1902 * Checks whether built-in profile specified by fileName exists. 1903 */ 1904 private static boolean standardProfileExists(final String fileName) { 1905 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 1906 public Boolean run() { 1907 return PCMM.class.getResource("profiles/"+fileName) != null; 1908 } 1909 }); 1910 } 1911 1912 1913 /* 1914 * Serialization support. 1915 * 1916 * Directly deserialized profiles are useless since they are not 1917 * registered with CMM. We don't allow constructor to be called 1918 * directly and instead have clients to call one of getInstance 1919 * factory methods that will register the profile with CMM. For 1920 * deserialization we implement readResolve method that will 1921 * resolve the bogus deserialized profile object with one obtained 1922 * with getInstance as well. 1923 * 1924 * There are two primary factory methods for construction of ICC 1925 * profiles: getInstance(int cspace) and getInstance(byte[] data). 1926 * This implementation of ICC_Profile uses the former to return a 1927 * cached singleton profile object, other implementations will 1928 * likely use this technique too. To preserve the singleton 1929 * pattern across serialization we serialize cached singleton 1930 * profiles in such a way that deserializing VM could call 1931 * getInstance(int cspace) method that will resolve deserialized 1932 * object into the corresponding singleton as well. 1933 * 1934 * Since the singletons are private to ICC_Profile the readResolve 1935 * method have to be `protected' instead of `private' so that 1936 * singletons that are instances of subclasses of ICC_Profile 1937 * could be correctly deserialized. 1938 */ 1939 1940 1941 /** 1942 * Version of the format of additional serialized data in the 1943 * stream. Version {@code 1} corresponds to Java 2 1944 * Platform, v1.3. 1945 * @since 1.3 1946 * @serial 1947 */ 1948 private int iccProfileSerializedDataVersion = 1; 1949 1950 1951 /** 1952 * Writes default serializable fields to the stream. Writes a 1953 * string and an array of bytes to the stream as additional data. 1954 * 1955 * @param s stream used for serialization. 1956 * @throws IOException 1957 * thrown by {@code ObjectInputStream}. 1958 * @serialData 1959 * The {@code String} is the name of one of 1960 * <code>CS_<var>*</var></code> constants defined in the 1961 * {@link ColorSpace} class if the profile object is a profile 1962 * for a predefined color space (for example 1963 * {@code "CS_sRGB"}). The string is {@code null} 1964 * otherwise. 1965 * <p> 1966 * The {@code byte[]} array is the profile data for the 1967 * profile. For predefined color spaces {@code null} is 1968 * written instead of the profile data. If in the future 1969 * versions of Java API new predefined color spaces will be 1970 * added, future versions of this class may choose to write 1971 * for new predefined color spaces not only the color space 1972 * name, but the profile data as well so that older versions 1973 * could still deserialize the object. 1974 */ 1975 private void writeObject(ObjectOutputStream s) 1976 throws IOException 1977 { 1978 s.defaultWriteObject(); 1979 1980 String csName = null; 1981 if (this == sRGBprofile) { 1982 csName = "CS_sRGB"; 1983 } else if (this == XYZprofile) { 1984 csName = "CS_CIEXYZ"; 1985 } else if (this == PYCCprofile) { 1986 csName = "CS_PYCC"; 1987 } else if (this == GRAYprofile) { 1988 csName = "CS_GRAY"; 1989 } else if (this == LINEAR_RGBprofile) { 1990 csName = "CS_LINEAR_RGB"; 1991 } 1992 1993 // Future versions may choose to write profile data for new 1994 // predefined color spaces as well, if any will be introduced, 1995 // so that old versions that don't recognize the new CS name 1996 // may fall back to constructing profile from the data. 1997 byte[] data = null; 1998 if (csName == null) { 1999 // getData will activate deferred profile if necessary 2000 data = getData(); 2001 } 2002 2003 s.writeObject(csName); 2004 s.writeObject(data); 2005 } 2006 2007 // Temporary storage used by readObject to store resolved profile 2008 // (obtained with getInstance) for readResolve to return. 2009 private transient ICC_Profile resolvedDeserializedProfile; 2010 2011 /** 2012 * Reads default serializable fields from the stream. Reads from 2013 * the stream a string and an array of bytes as additional data. 2014 * 2015 * @param s stream used for deserialization. 2016 * @throws IOException 2017 * thrown by {@code ObjectInputStream}. 2018 * @throws ClassNotFoundException 2019 * thrown by {@code ObjectInputStream}. 2020 * @serialData 2021 * The {@code String} is the name of one of 2022 * <code>CS_<var>*</var></code> constants defined in the 2023 * {@link ColorSpace} class if the profile object is a profile 2024 * for a predefined color space (for example 2025 * {@code "CS_sRGB"}). The string is {@code null} 2026 * otherwise. 2027 * <p> 2028 * The {@code byte[]} array is the profile data for the 2029 * profile. It will usually be {@code null} for the 2030 * predefined profiles. 2031 * <p> 2032 * If the string is recognized as a constant name for 2033 * predefined color space the object will be resolved into 2034 * profile obtained with 2035 * <code>getInstance(int cspace)</code> and the profile 2036 * data are ignored. Otherwise the object will be resolved 2037 * into profile obtained with 2038 * <code>getInstance(byte[] data)</code>. 2039 * @see #readResolve() 2040 * @see #getInstance(int) 2041 * @see #getInstance(byte[]) 2042 */ 2043 private void readObject(ObjectInputStream s) 2044 throws IOException, ClassNotFoundException 2045 { 2046 s.defaultReadObject(); 2047 2048 String csName = (String)s.readObject(); 2049 byte[] data = (byte[])s.readObject(); 2050 2051 int cspace = 0; // ColorSpace.CS_* constant if known 2052 boolean isKnownPredefinedCS = false; 2053 if (csName != null) { 2054 isKnownPredefinedCS = true; 2055 if (csName.equals("CS_sRGB")) { 2056 cspace = ColorSpace.CS_sRGB; 2057 } else if (csName.equals("CS_CIEXYZ")) { 2058 cspace = ColorSpace.CS_CIEXYZ; 2059 } else if (csName.equals("CS_PYCC")) { 2060 cspace = ColorSpace.CS_PYCC; 2061 } else if (csName.equals("CS_GRAY")) { 2062 cspace = ColorSpace.CS_GRAY; 2063 } else if (csName.equals("CS_LINEAR_RGB")) { 2064 cspace = ColorSpace.CS_LINEAR_RGB; 2065 } else { 2066 isKnownPredefinedCS = false; 2067 } 2068 } 2069 2070 if (isKnownPredefinedCS) { 2071 resolvedDeserializedProfile = getInstance(cspace); 2072 } else { 2073 resolvedDeserializedProfile = getInstance(data); 2074 } 2075 } 2076 2077 /** 2078 * Resolves instances being deserialized into instances registered 2079 * with CMM. 2080 * @return ICC_Profile object for profile registered with CMM. 2081 * @throws ObjectStreamException 2082 * never thrown, but mandated by the serialization spec. 2083 * @since 1.3 2084 */ 2085 protected Object readResolve() throws ObjectStreamException { 2086 return resolvedDeserializedProfile; 2087 } 2088 }