1. /*
  2. * @(#)ICC_Profile.java 1.19 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /**********************************************************************
  8. **********************************************************************
  9. **********************************************************************
  10. *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
  11. *** As an unpublished work pursuant to Title 17 of the United ***
  12. *** States Code. All rights reserved. ***
  13. **********************************************************************
  14. **********************************************************************
  15. **********************************************************************/
  16. package java.awt.color;
  17. import sun.awt.color.CMM;
  18. import sun.awt.color.ProfileDeferralMgr;
  19. import sun.awt.color.ProfileDeferralInfo;
  20. import sun.awt.color.ProfileActivator;
  21. import java.io.*;
  22. import java.util.StringTokenizer;
  23. /**
  24. *
  25. * A representation of color profile data for device
  26. * independent and device dependent color spaces based on the ICC
  27. * Profile Format Specification, Version 3.4, August 15, 1997, from
  28. * the International Color Consortium (see <A href="http://www.color.org">
  29. * http://www.color.org</A>).
  30. * <p>
  31. * An ICC_ColorSpace object can be constructed from an appropriate
  32. * ICC_Profile.
  33. * Typically, an ICC_ColorSpace would be associated with an ICC
  34. * Profile which is either an input, display, or output profile (see
  35. * the ICC specification). There are also device link, abstract,
  36. * color space conversion, and named color profiles. These are less
  37. * useful for tagging a color or image, but are useful for other
  38. * purposes (in particular device link profiles can provide improved
  39. * performance for converting from one device's color space to
  40. * another's).
  41. * <p>
  42. * ICC Profiles represent transformations from the color space of
  43. * the profile (e.g. a monitor) to a Profile Connection Space (PCS).
  44. * Profiles of interest for tagging images or colors have a PCS
  45. * which is one of the two specific device independent
  46. * spaces (one CIEXYZ space and one CIELab space) defined in the
  47. * ICC Profile Format Specification. Most profiles of interest
  48. * either have invertible transformations or explicitly specify
  49. * transformations going both directions.
  50. * <p>
  51. * @version 10 Feb 1997
  52. * @see ICC_ColorSpace
  53. */
  54. public class ICC_Profile
  55. extends Object {
  56. long ID;
  57. private static ICC_Profile sRGBprofile;
  58. private static ICC_Profile XYZprofile;
  59. private static ICC_Profile PYCCprofile;
  60. private static ICC_Profile GRAYprofile;
  61. private static ICC_Profile LINEAR_RGBprofile;
  62. private ProfileDeferralInfo deferralInfo;
  63. private ProfileActivator profileActivator;
  64. /**
  65. * Profile class is input.
  66. */
  67. public static final int CLASS_INPUT = 0;
  68. /**
  69. * Profile class is display.
  70. */
  71. public static final int CLASS_DISPLAY = 1;
  72. /**
  73. * Profile class is output.
  74. */
  75. public static final int CLASS_OUTPUT = 2;
  76. /**
  77. * Profile class is device link.
  78. */
  79. public static final int CLASS_DEVICELINK = 3;
  80. /**
  81. * Profile class is color space conversion.
  82. */
  83. public static final int CLASS_COLORSPACECONVERSION = 4;
  84. /**
  85. * Profile class is abstract.
  86. */
  87. public static final int CLASS_ABSTRACT = 5;
  88. /**
  89. * Profile class is named color.
  90. */
  91. public static final int CLASS_NAMEDCOLOR = 6;
  92. /**
  93. * ICC Profile Color Space Type Signature: 'XYZ '.
  94. */
  95. public static final int icSigXYZData = 0x58595A20; /* 'XYZ ' */
  96. /**
  97. * ICC Profile Color Space Type Signature: 'Lab '.
  98. */
  99. public static final int icSigLabData = 0x4C616220; /* 'Lab ' */
  100. /**
  101. * ICC Profile Color Space Type Signature: 'Luv '.
  102. */
  103. public static final int icSigLuvData = 0x4C757620; /* 'Luv ' */
  104. /**
  105. * ICC Profile Color Space Type Signature: 'YCbr'.
  106. */
  107. public static final int icSigYCbCrData = 0x59436272; /* 'YCbr' */
  108. /**
  109. * ICC Profile Color Space Type Signature: 'Yxy '.
  110. */
  111. public static final int icSigYxyData = 0x59787920; /* 'Yxy ' */
  112. /**
  113. * ICC Profile Color Space Type Signature: 'RGB '.
  114. */
  115. public static final int icSigRgbData = 0x52474220; /* 'RGB ' */
  116. /**
  117. * ICC Profile Color Space Type Signature: 'GRAY'.
  118. */
  119. public static final int icSigGrayData = 0x47524159; /* 'GRAY' */
  120. /**
  121. * ICC Profile Color Space Type Signature: 'HSV'.
  122. */
  123. public static final int icSigHsvData = 0x48535620; /* 'HSV ' */
  124. /**
  125. * ICC Profile Color Space Type Signature: 'HLS'.
  126. */
  127. public static final int icSigHlsData = 0x484C5320; /* 'HLS ' */
  128. /**
  129. * ICC Profile Color Space Type Signature: 'CMYK'.
  130. */
  131. public static final int icSigCmykData = 0x434D594B; /* 'CMYK' */
  132. /**
  133. * ICC Profile Color Space Type Signature: 'CMY '.
  134. */
  135. public static final int icSigCmyData = 0x434D5920; /* 'CMY ' */
  136. /**
  137. * ICC Profile Color Space Type Signature: '2CLR'.
  138. */
  139. public static final int icSigSpace2CLR = 0x32434C52; /* '2CLR' */
  140. /**
  141. * ICC Profile Color Space Type Signature: '3CLR'.
  142. */
  143. public static final int icSigSpace3CLR = 0x33434C52; /* '3CLR' */
  144. /**
  145. * ICC Profile Color Space Type Signature: '4CLR'.
  146. */
  147. public static final int icSigSpace4CLR = 0x34434C52; /* '4CLR' */
  148. /**
  149. * ICC Profile Color Space Type Signature: '5CLR'.
  150. */
  151. public static final int icSigSpace5CLR = 0x35434C52; /* '5CLR' */
  152. /**
  153. * ICC Profile Color Space Type Signature: '6CLR'.
  154. */
  155. public static final int icSigSpace6CLR = 0x36434C52; /* '6CLR' */
  156. /**
  157. * ICC Profile Color Space Type Signature: '7CLR'.
  158. */
  159. public static final int icSigSpace7CLR = 0x37434C52; /* '7CLR' */
  160. /**
  161. * ICC Profile Color Space Type Signature: '8CLR'.
  162. */
  163. public static final int icSigSpace8CLR = 0x38434C52; /* '8CLR' */
  164. /**
  165. * ICC Profile Color Space Type Signature: '9CLR'.
  166. */
  167. public static final int icSigSpace9CLR = 0x39434C52; /* '9CLR' */
  168. /**
  169. * ICC Profile Color Space Type Signature: 'ACLR'.
  170. */
  171. public static final int icSigSpaceACLR = 0x41434C52; /* 'ACLR' */
  172. /**
  173. * ICC Profile Color Space Type Signature: 'BCLR'.
  174. */
  175. public static final int icSigSpaceBCLR = 0x42434C52; /* 'BCLR' */
  176. /**
  177. * ICC Profile Color Space Type Signature: 'CCLR'.
  178. */
  179. public static final int icSigSpaceCCLR = 0x43434C52; /* 'CCLR' */
  180. /**
  181. * ICC Profile Color Space Type Signature: 'DCLR'.
  182. */
  183. public static final int icSigSpaceDCLR = 0x44434C52; /* 'DCLR' */
  184. /**
  185. * ICC Profile Color Space Type Signature: 'ECLR'.
  186. */
  187. public static final int icSigSpaceECLR = 0x45434C52; /* 'ECLR' */
  188. /**
  189. * ICC Profile Color Space Type Signature: 'FCLR'.
  190. */
  191. public static final int icSigSpaceFCLR = 0x46434C52; /* 'FCLR' */
  192. /**
  193. * ICC Profile Class Signature: 'scnr'.
  194. */
  195. public static final int icSigInputClass = 0x73636E72; /* 'scnr' */
  196. /**
  197. * ICC Profile Class Signature: 'mntr'.
  198. */
  199. public static final int icSigDisplayClass = 0x6D6E7472; /* 'mntr' */
  200. /**
  201. * ICC Profile Class Signature: 'prtr'.
  202. */
  203. public static final int icSigOutputClass = 0x70727472; /* 'prtr' */
  204. /**
  205. * ICC Profile Class Signature: 'link'.
  206. */
  207. public static final int icSigLinkClass = 0x6C696E6B; /* 'link' */
  208. /**
  209. * ICC Profile Class Signature: 'abst'.
  210. */
  211. public static final int icSigAbstractClass = 0x61627374; /* 'abst' */
  212. /**
  213. * ICC Profile Class Signature: 'spac'.
  214. */
  215. public static final int icSigColorSpaceClass = 0x73706163; /* 'spac' */
  216. /**
  217. * ICC Profile Class Signature: 'nmcl'.
  218. */
  219. public static final int icSigNamedColorClass = 0x6e6d636c; /* 'nmcl' */
  220. /**
  221. * ICC Profile Rendering Intent: Perceptual.
  222. */
  223. public static final int icPerceptual = 0;
  224. /**
  225. * ICC Profile Rendering Intent: RelativeColorimetric.
  226. */
  227. public static final int icRelativeColorimetric = 1;
  228. /**
  229. * ICC Profile Rendering Intent: Saturation.
  230. */
  231. public static final int icSaturation = 2;
  232. /**
  233. * ICC Profile Rendering Intent: AbsoluteColorimetric.
  234. */
  235. public static final int icAbsoluteColorimetric = 3;
  236. /**
  237. * ICC Profile Tag Signature: 'head' - special.
  238. */
  239. public static final int icSigHead = 0x68656164; /* 'head' - special */
  240. /**
  241. * ICC Profile Tag Signature: 'A2B0'.
  242. */
  243. public static final int icSigAToB0Tag = 0x41324230; /* 'A2B0' */
  244. /**
  245. * ICC Profile Tag Signature: 'A2B1'.
  246. */
  247. public static final int icSigAToB1Tag = 0x41324231; /* 'A2B1' */
  248. /**
  249. * ICC Profile Tag Signature: 'A2B2'.
  250. */
  251. public static final int icSigAToB2Tag = 0x41324232; /* 'A2B2' */
  252. /**
  253. * ICC Profile Tag Signature: 'bXYZ'.
  254. */
  255. public static final int icSigBlueColorantTag = 0x6258595A; /* 'bXYZ' */
  256. /**
  257. * ICC Profile Tag Signature: 'bTRC'.
  258. */
  259. public static final int icSigBlueTRCTag = 0x62545243; /* 'bTRC' */
  260. /**
  261. * ICC Profile Tag Signature: 'B2A0'.
  262. */
  263. public static final int icSigBToA0Tag = 0x42324130; /* 'B2A0' */
  264. /**
  265. * ICC Profile Tag Signature: 'B2A1'.
  266. */
  267. public static final int icSigBToA1Tag = 0x42324131; /* 'B2A1' */
  268. /**
  269. * ICC Profile Tag Signature: 'B2A2'.
  270. */
  271. public static final int icSigBToA2Tag = 0x42324132; /* 'B2A2' */
  272. /**
  273. * ICC Profile Tag Signature: 'calt'.
  274. */
  275. public static final int icSigCalibrationDateTimeTag = 0x63616C74;
  276. /* 'calt' */
  277. /**
  278. * ICC Profile Tag Signature: 'targ'.
  279. */
  280. public static final int icSigCharTargetTag = 0x74617267; /* 'targ' */
  281. /**
  282. * ICC Profile Tag Signature: 'cprt'.
  283. */
  284. public static final int icSigCopyrightTag = 0x63707274; /* 'cprt' */
  285. /**
  286. * ICC Profile Tag Signature: 'dmnd'.
  287. */
  288. public static final int icSigDeviceMfgDescTag = 0x646D6E64; /* 'dmnd' */
  289. /**
  290. * ICC Profile Tag Signature: 'dmdd'.
  291. */
  292. public static final int icSigDeviceModelDescTag = 0x646D6464; /* 'dmdd' */
  293. /**
  294. * ICC Profile Tag Signature: 'gamt'.
  295. */
  296. public static final int icSigGamutTag = 0x67616D74; /* 'gamt' */
  297. /**
  298. * ICC Profile Tag Signature: 'kTRC'.
  299. */
  300. public static final int icSigGrayTRCTag = 0x6b545243; /* 'kTRC' */
  301. /**
  302. * ICC Profile Tag Signature: 'gXYZ'.
  303. */
  304. public static final int icSigGreenColorantTag = 0x6758595A; /* 'gXYZ' */
  305. /**
  306. * ICC Profile Tag Signature: 'gTRC'.
  307. */
  308. public static final int icSigGreenTRCTag = 0x67545243; /* 'gTRC' */
  309. /**
  310. * ICC Profile Tag Signature: 'lumi'.
  311. */
  312. public static final int icSigLuminanceTag = 0x6C756d69; /* 'lumi' */
  313. /**
  314. * ICC Profile Tag Signature: 'meas'.
  315. */
  316. public static final int icSigMeasurementTag = 0x6D656173; /* 'meas' */
  317. /**
  318. * ICC Profile Tag Signature: 'bkpt'.
  319. */
  320. public static final int icSigMediaBlackPointTag = 0x626B7074; /* 'bkpt' */
  321. /**
  322. * ICC Profile Tag Signature: 'wtpt'.
  323. */
  324. public static final int icSigMediaWhitePointTag = 0x77747074; /* 'wtpt' */
  325. /**
  326. * ICC Profile Tag Signature: 'pre0'.
  327. */
  328. public static final int icSigPreview0Tag = 0x70726530; /* 'pre0' */
  329. /**
  330. * ICC Profile Tag Signature: 'pre1'.
  331. */
  332. public static final int icSigPreview1Tag = 0x70726531; /* 'pre1' */
  333. /**
  334. * ICC Profile Tag Signature: 'pre2'.
  335. */
  336. public static final int icSigPreview2Tag = 0x70726532; /* 'pre2' */
  337. /**
  338. * ICC Profile Tag Signature: 'desc'.
  339. */
  340. public static final int icSigProfileDescriptionTag = 0x64657363;
  341. /* 'desc' */
  342. /**
  343. * ICC Profile Tag Signature: 'pseq'.
  344. */
  345. public static final int icSigProfileSequenceDescTag = 0x70736571;
  346. /* 'pseq' */
  347. /**
  348. * ICC Profile Tag Signature: 'psd0'.
  349. */
  350. public static final int icSigPs2CRD0Tag = 0x70736430; /* 'psd0' */
  351. /**
  352. * ICC Profile Tag Signature: 'psd1'.
  353. */
  354. public static final int icSigPs2CRD1Tag = 0x70736431; /* 'psd1' */
  355. /**
  356. * ICC Profile Tag Signature: 'psd2'.
  357. */
  358. public static final int icSigPs2CRD2Tag = 0x70736432; /* 'psd2' */
  359. /**
  360. * ICC Profile Tag Signature: 'psd3'.
  361. */
  362. public static final int icSigPs2CRD3Tag = 0x70736433; /* 'psd3' */
  363. /**
  364. * ICC Profile Tag Signature: 'ps2s'.
  365. */
  366. public static final int icSigPs2CSATag = 0x70733273; /* 'ps2s' */
  367. /**
  368. * ICC Profile Tag Signature: 'ps2i'.
  369. */
  370. public static final int icSigPs2RenderingIntentTag = 0x70733269;
  371. /* 'ps2i' */
  372. /**
  373. * ICC Profile Tag Signature: 'rXYZ'.
  374. */
  375. public static final int icSigRedColorantTag = 0x7258595A; /* 'rXYZ' */
  376. /**
  377. * ICC Profile Tag Signature: 'rTRC'.
  378. */
  379. public static final int icSigRedTRCTag = 0x72545243; /* 'rTRC' */
  380. /**
  381. * ICC Profile Tag Signature: 'scrd'.
  382. */
  383. public static final int icSigScreeningDescTag = 0x73637264; /* 'scrd' */
  384. /**
  385. * ICC Profile Tag Signature: 'scrn'.
  386. */
  387. public static final int icSigScreeningTag = 0x7363726E; /* 'scrn' */
  388. /**
  389. * ICC Profile Tag Signature: 'tech'.
  390. */
  391. public static final int icSigTechnologyTag = 0x74656368; /* 'tech' */
  392. /**
  393. * ICC Profile Tag Signature: 'bfd '.
  394. */
  395. public static final int icSigUcrBgTag = 0x62666420; /* 'bfd ' */
  396. /**
  397. * ICC Profile Tag Signature: 'vued'.
  398. */
  399. public static final int icSigViewingCondDescTag = 0x76756564; /* 'vued' */
  400. /**
  401. * ICC Profile Tag Signature: 'view'.
  402. */
  403. public static final int icSigViewingConditionsTag = 0x76696577;/* 'view' */
  404. /**
  405. * ICC Profile Tag Signature: 'nc12'.
  406. */
  407. public static final int icSigNamedColor2Tag = 0x6E636C32; /* 'ncl2' */
  408. /**
  409. * ICC Profile Header Location: profile size in bytes.
  410. */
  411. public static final int icHdrSize = 0; /* Profile size in bytes */
  412. /**
  413. * ICC Profile Header Location: CMM for this profile.
  414. */
  415. public static final int icHdrCmmId = 4; /* CMM for this profile */
  416. /**
  417. * ICC Profile Header Location: format version number.
  418. */
  419. public static final int icHdrVersion = 8; /* Format version number */
  420. /**
  421. * ICC Profile Header Location: type of profile.
  422. */
  423. public static final int icHdrDeviceClass = 12; /* Type of profile */
  424. /**
  425. * ICC Profile Header Location: color space of data.
  426. */
  427. public static final int icHdrColorSpace = 16; /* Color space of data */
  428. /**
  429. * ICC Profile Header Location: PCS - XYZ or Lab only.
  430. */
  431. public static final int icHdrPcs = 20; /* PCS - XYZ or Lab only */
  432. /**
  433. * ICC Profile Header Location: date profile was created.
  434. */
  435. public static final int icHdrDate = 24; /* Date profile was created */
  436. /**
  437. * ICC Profile Header Location: icMagicNumber.
  438. */
  439. public static final int icHdrMagic = 36; /* icMagicNumber */
  440. /**
  441. * ICC Profile Header Location: primary platform.
  442. */
  443. public static final int icHdrPlatform = 40; /* Primary Platform */
  444. /**
  445. * ICC Profile Header Location: various bit settings.
  446. */
  447. public static final int icHdrFlags = 44; /* Various bit settings */
  448. /**
  449. * ICC Profile Header Location: device manufacturer.
  450. */
  451. public static final int icHdrManufacturer = 48; /* Device manufacturer */
  452. /**
  453. * ICC Profile Header Location: device model number.
  454. */
  455. public static final int icHdrModel = 52; /* Device model number */
  456. /**
  457. * ICC Profile Header Location: device attributes.
  458. */
  459. public static final int icHdrAttributes = 56; /* Device attributes */
  460. /**
  461. * ICC Profile Header Location: rendering intent.
  462. */
  463. public static final int icHdrRenderingIntent = 64; /* Rendering intent */
  464. /**
  465. * ICC Profile Header Location: profile illuminant.
  466. */
  467. public static final int icHdrIlluminant = 68; /* Profile illuminant */
  468. /**
  469. * ICC Profile Header Location: profile creator.
  470. */
  471. public static final int icHdrCreator = 80; /* Profile creator */
  472. /**
  473. * ICC Profile Constant: tag type signaturE.
  474. */
  475. public static final int icTagType = 0; /* tag type signature */
  476. /**
  477. * ICC Profile Constant: reserved.
  478. */
  479. public static final int icTagReserved = 4; /* reserved */
  480. /**
  481. * ICC Profile Constant: curveType count.
  482. */
  483. public static final int icCurveCount = 8; /* curveType count */
  484. /**
  485. * ICC Profile Constant: curveType data.
  486. */
  487. public static final int icCurveData = 12; /* curveType data */
  488. /**
  489. * ICC Profile Constant: XYZNumber X.
  490. */
  491. public static final int icXYZNumberX = 8; /* XYZNumber X */
  492. /**
  493. * Constructs an ICC_Profile object with a given ID.
  494. */
  495. ICC_Profile(long ID) {
  496. this.ID = ID;
  497. }
  498. /**
  499. * Constructs an ICC_Profile object whose loading will be deferred.
  500. * The ID will be 0 until the profile is loaded.
  501. */
  502. ICC_Profile(ProfileDeferralInfo pdi) {
  503. this.deferralInfo = pdi;
  504. this.profileActivator = new ProfileActivator() {
  505. public void activate() {
  506. activateDeferredProfile();
  507. }
  508. };
  509. ProfileDeferralMgr.registerDeferral(this.profileActivator);
  510. }
  511. /**
  512. * Frees the resources associated with an ICC_Profile object.
  513. */
  514. protected void finalize () {
  515. if (ID != 0) {
  516. CMM.checkStatus(CMM.cmmFreeProfile(ID));
  517. } else if (profileActivator != null) {
  518. ProfileDeferralMgr.unregisterDeferral(profileActivator);
  519. }
  520. }
  521. /**
  522. * Constructs an ICC_Profile object corresponding to the data in
  523. * a byte array. Throws an IllegalArgumentException if the data
  524. * does not correspond to a valid ICC Profile.
  525. */
  526. public static ICC_Profile getInstance(byte[] data) {
  527. ICC_Profile thisProfile;
  528. long[] theID = new long [1];
  529. if (ProfileDeferralMgr.deferring) {
  530. ProfileDeferralMgr.activateProfiles();
  531. }
  532. try {
  533. CMM.checkStatus(CMM.cmmLoadProfile(data, theID));
  534. } catch (CMMException c) {
  535. throw new IllegalArgumentException("Invalid ICC Profile Data");
  536. }
  537. try {
  538. if ((getColorSpaceType (theID[0]) == ColorSpace.TYPE_GRAY) &&
  539. (getData (theID[0], icSigMediaWhitePointTag) != null) &&
  540. (getData (theID[0], icSigGrayTRCTag) != null)) {
  541. thisProfile = new ICC_ProfileGray (theID[0]);
  542. }
  543. else if ((getColorSpaceType (theID[0]) == ColorSpace.TYPE_RGB) &&
  544. (getData (theID[0], icSigMediaWhitePointTag) != null) &&
  545. (getData (theID[0], icSigRedColorantTag) != null) &&
  546. (getData (theID[0], icSigGreenColorantTag) != null) &&
  547. (getData (theID[0], icSigBlueColorantTag) != null) &&
  548. (getData (theID[0], icSigRedTRCTag) != null) &&
  549. (getData (theID[0], icSigGreenTRCTag) != null) &&
  550. (getData (theID[0], icSigBlueTRCTag) != null)) {
  551. thisProfile = new ICC_ProfileRGB (theID[0]);
  552. }
  553. else {
  554. thisProfile = new ICC_Profile (theID[0]);
  555. }
  556. } catch (CMMException c) {
  557. thisProfile = new ICC_Profile (theID[0]);
  558. }
  559. return thisProfile;
  560. }
  561. /**
  562. * Constructs an ICC_Profile corresponding to one of the specific color
  563. * spaces defined by the ColorSpace class (for example CS_sRGB).
  564. * Throws an IllegalArgumentException if cspace is not one of the
  565. * defined color spaces.
  566. */
  567. public static ICC_Profile getInstance (int cspace)
  568. {
  569. ICC_Profile thisProfile = null;
  570. String fileName;
  571. try {
  572. switch (cspace) {
  573. case ColorSpace.CS_sRGB:
  574. if (sRGBprofile == null) {
  575. sRGBprofile = getDeferredInstance(
  576. new ProfileDeferralInfo("sRGB.pf", ColorSpace.TYPE_RGB,
  577. 3, CLASS_DISPLAY));
  578. }
  579. thisProfile = sRGBprofile;
  580. break;
  581. case ColorSpace.CS_CIEXYZ:
  582. if (XYZprofile == null) {
  583. XYZprofile = getInstance ("CIEXYZ.pf");
  584. }
  585. thisProfile = XYZprofile;
  586. break;
  587. case ColorSpace.CS_PYCC:
  588. if (PYCCprofile == null) {
  589. PYCCprofile = getInstance ("PYCC.pf");
  590. }
  591. thisProfile = PYCCprofile;
  592. break;
  593. case ColorSpace.CS_GRAY:
  594. if (GRAYprofile == null) {
  595. GRAYprofile = getInstance ("GRAY.pf");
  596. }
  597. thisProfile = GRAYprofile;
  598. break;
  599. case ColorSpace.CS_LINEAR_RGB:
  600. if (LINEAR_RGBprofile == null) {
  601. LINEAR_RGBprofile = getInstance ("LINEAR_RGB.pf");
  602. }
  603. thisProfile = LINEAR_RGBprofile;
  604. break;
  605. default:
  606. throw new IllegalArgumentException("Unknown color space");
  607. }
  608. } catch (IOException e) {
  609. throw new IllegalArgumentException("Can't load standard profile");
  610. }
  611. return thisProfile;
  612. }
  613. /**
  614. * Constructs an ICC_Profile corresponding to the data in a file.
  615. * fileName may be an absolute or a relative file specification.
  616. * Relative file names are looked for in several places: first, relative
  617. * to any directories specified by the java.iccprofile.path property;
  618. * second, relative to any directories specified by the java.class.path
  619. * property; finally, in a directory used to store profiles always
  620. * available, such as the profile for sRGB. Built-in profiles use .pf as
  621. * the file name extension for profiles, e.g. sRGB.pf.
  622. * This method throws an IOException if the specified file cannot be
  623. * opened or if an I/O error occurs while reading the file. It throws
  624. * an IllegalArgumentException if the file does not contain valid ICC
  625. * Profile data.
  626. */
  627. public static ICC_Profile getInstance(String fileName) throws IOException {
  628. ICC_Profile thisProfile;
  629. FileInputStream fis;
  630. if ((fis = openProfile(fileName)) == null) {
  631. throw new IOException("Cannot open file " + fileName);
  632. }
  633. thisProfile = getInstance(fis);
  634. fis.close(); /* close the file */
  635. return thisProfile;
  636. }
  637. /**
  638. * Constructs an ICC_Profile corresponding to the data in an InputStream.
  639. * This method throws an IllegalArgumentException if the stream does not
  640. * contain valid ICC Profile data. It throws an IOException if an I/O
  641. * error occurs while reading the stream.
  642. */
  643. public static ICC_Profile getInstance(InputStream s) throws IOException {
  644. byte profileData[];
  645. if (s instanceof ProfileDeferralInfo) {
  646. /* hack to detect profiles whose loading can be deferred */
  647. return getDeferredInstance((ProfileDeferralInfo) s);
  648. }
  649. if ((profileData = getProfileDataFromStream(s)) == null) {
  650. throw new IllegalArgumentException("Invalid ICC Profile Data");
  651. }
  652. return getInstance(profileData);
  653. }
  654. static byte[] getProfileDataFromStream(InputStream s) throws IOException {
  655. byte profileData[];
  656. int profileSize;
  657. byte header[] = new byte[128];
  658. int bytestoread = 128;
  659. int bytesread = 0;
  660. int n;
  661. while (bytestoread != 0) {
  662. if ((n = s.read(header, bytesread, bytestoread)) < 0) {
  663. return null;
  664. }
  665. bytesread += n;
  666. bytestoread -= n;
  667. }
  668. if (header[36] != 0x61 || header[37] != 0x63 ||
  669. header[38] != 0x73 || header[39] != 0x70) {
  670. return null; /* not a valid profile */
  671. }
  672. profileSize = ((header[0] & 0xff) << 24) |
  673. ((header[1] & 0xff) << 16) |
  674. ((header[2] & 0xff) << 8) |
  675. (header[3] & 0xff);
  676. profileData = new byte[profileSize];
  677. System.arraycopy(header, 0, profileData, 0, 128);
  678. bytestoread = profileSize - 128;
  679. bytesread = 128;
  680. while (bytestoread != 0) {
  681. if ((n = s.read(profileData, bytesread, bytestoread)) < 0) {
  682. return null;
  683. }
  684. bytesread += n;
  685. bytestoread -= n;
  686. }
  687. return profileData;
  688. }
  689. /**
  690. * Constructs an ICC_Profile for which the actual loading of the
  691. * profile data from a file and the initialization of the CMM should
  692. * be deferred as long as possible.
  693. */
  694. static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi)
  695. throws IOException {
  696. if (!ProfileDeferralMgr.deferring) {
  697. return getInstance(pdi.filename);
  698. }
  699. if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
  700. return new ICC_ProfileRGB(pdi);
  701. } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
  702. return new ICC_ProfileGray(pdi);
  703. } else {
  704. return new ICC_Profile(pdi);
  705. }
  706. }
  707. void activateDeferredProfile() {
  708. long[] theID = new long [1];
  709. byte profileData[];
  710. FileInputStream fis;
  711. String fileName = deferralInfo.filename;
  712. profileActivator = null;
  713. deferralInfo = null;
  714. if ((fis = openProfile(fileName)) == null) {
  715. throw new IllegalArgumentException("Cannot open file " + fileName);
  716. }
  717. try {
  718. profileData = getProfileDataFromStream(fis);
  719. fis.close(); /* close the file */
  720. }
  721. catch (IOException e) {
  722. throw new IllegalArgumentException("Invalid ICC Profile Data" +
  723. fileName);
  724. }
  725. if (profileData == null) {
  726. throw new IllegalArgumentException("Invalid ICC Profile Data" +
  727. fileName);
  728. }
  729. try {
  730. CMM.checkStatus(CMM.cmmLoadProfile(profileData, theID));
  731. } catch (CMMException c) {
  732. throw new IllegalArgumentException("Invalid ICC Profile Data" +
  733. fileName);
  734. }
  735. ID = theID[0];
  736. }
  737. /**
  738. * Returns profile major version.
  739. */
  740. public int getMajorVersion() {
  741. byte[] theHeader;
  742. theHeader = getData(icSigHead); /* getData will activate deferred
  743. profiles if necessary */
  744. return (int) theHeader[8];
  745. }
  746. /**
  747. * Returns profile minor version.
  748. */
  749. public int getMinorVersion() {
  750. byte[] theHeader;
  751. theHeader = getData(icSigHead); /* getData will activate deferred
  752. profiles if necessary */
  753. return (int) theHeader[9];
  754. }
  755. /**
  756. * Returns the profile class. Returns one of the predefined profile
  757. * class constants.
  758. */
  759. public int getProfileClass() {
  760. byte[] theHeader;
  761. int theClassSig, theClass;
  762. if (deferralInfo != null) {
  763. return deferralInfo.profileClass; /* Need to have this info for
  764. ICC_ColorSpace without
  765. causing a deferred profile
  766. to be loaded */
  767. }
  768. theHeader = getData(icSigHead);
  769. theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass);
  770. switch (theClassSig) {
  771. case icSigInputClass:
  772. theClass = CLASS_INPUT;
  773. break;
  774. case icSigDisplayClass:
  775. theClass = CLASS_DISPLAY;
  776. break;
  777. case icSigOutputClass:
  778. theClass = CLASS_OUTPUT;
  779. break;
  780. case icSigLinkClass:
  781. theClass = CLASS_DEVICELINK;
  782. break;
  783. case icSigColorSpaceClass:
  784. theClass = CLASS_COLORSPACECONVERSION;
  785. break;
  786. case icSigAbstractClass:
  787. theClass = CLASS_ABSTRACT;
  788. break;
  789. case icSigNamedColorClass:
  790. theClass = CLASS_NAMEDCOLOR;
  791. break;
  792. default:
  793. throw new IllegalArgumentException("Unknown profile class");
  794. }
  795. return theClass;
  796. }
  797. /**
  798. * Returns the color space type. Returns one of the color space type
  799. * constants defined by the ColorSpace class. This is the
  800. * "input" color space of the profile. The type defines the
  801. * number of components of the color space and the interpretation,
  802. * e.g. TYPE_RGB identifies a color space with three components - red,
  803. * green, and blue. It does not define the particular color
  804. * characteristics of the space, e.g. the chromaticities of the
  805. * primaries.
  806. */
  807. public int getColorSpaceType() {
  808. if (deferralInfo != null) {
  809. return deferralInfo.colorSpaceType; /* Need to have this info for
  810. ICC_ColorSpace without
  811. causing a deferred profile
  812. to be loaded */
  813. }
  814. return getColorSpaceType(ID);
  815. }
  816. static int getColorSpaceType(long profileID) {
  817. byte[] theHeader;
  818. int theColorSpaceSig, theColorSpace;
  819. theHeader = getData(profileID, icSigHead);
  820. theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
  821. theColorSpace = iccCStoJCS (theColorSpaceSig);
  822. return theColorSpace;
  823. }
  824. /**
  825. * Returns the color space type of the Profile Connection Space (PCS).
  826. * Returns one of the color space type constants defined by the
  827. * ColorSpace class. This is the "output" color space of the
  828. * profile. For an input, display, or output profile useful
  829. * for tagging colors or images, this will be either TYPE_XYZ or
  830. * TYPE_Lab and should be interpreted as the corresponding specific
  831. * color space defined in the ICC specification. For a device
  832. * link profile, this could be any of the color space type constants.
  833. */
  834. public int getPCSType() {
  835. if (ProfileDeferralMgr.deferring) {
  836. ProfileDeferralMgr.activateProfiles();
  837. }
  838. return getPCSType(ID);
  839. }
  840. static int getPCSType(long profileID) {
  841. byte[] theHeader;
  842. int thePCSSig, thePCS;
  843. theHeader = getData(profileID, icSigHead);
  844. thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
  845. thePCS = iccCStoJCS(thePCSSig);
  846. return thePCS;
  847. }
  848. /**
  849. * Write this ICC_Profile to a file. Throws an IOException if the
  850. * file cannot be opened for writing or if an I/O error occurs while
  851. * writing the file.
  852. */
  853. public void write(String fileName) throws IOException {
  854. FileOutputStream outputFile;
  855. byte profileData[];
  856. profileData = getData(); /* this will activate deferred
  857. profiles if necessary */
  858. outputFile = new FileOutputStream(fileName);
  859. outputFile.write(profileData);
  860. outputFile.close ();
  861. }
  862. /**
  863. * Write this ICC_Profile to an OutputStream. Throws an IOException
  864. * an I/O error occurs while writing the stream.
  865. */
  866. public void write(OutputStream s) throws IOException {
  867. byte profileData[];
  868. profileData = getData(); /* this will activate deferred
  869. profiles if necessary */
  870. s.write(profileData);
  871. }
  872. /**
  873. * Returns a byte array corresponding to the data of this ICC_Profile.
  874. */
  875. public byte[] getData() {
  876. int[] profileSize = new int [1];
  877. byte[] profileData;
  878. if (ProfileDeferralMgr.deferring) {
  879. ProfileDeferralMgr.activateProfiles();
  880. }
  881. /* get the number of bytes needed for this profile */
  882. CMM.checkStatus(CMM.cmmGetProfileSize(ID, profileSize));
  883. profileData = new byte [profileSize[0]];
  884. /* get the data for the profile */
  885. CMM.checkStatus(CMM.cmmGetProfileData(ID, profileData));
  886. return profileData;
  887. }
  888. /**
  889. * Returns a particular tagged data element from the profile as
  890. * a byte array. Elements are identified by signatures
  891. * as defined in the ICC specification. The signature
  892. * icSigHead can be used to get the header. This method is useful
  893. * for advanced applets or applications which need to access
  894. * profile data directly. Returns null if no such tag exists.
  895. */
  896. public byte[] getData(int tagSignature) {
  897. if (ProfileDeferralMgr.deferring) {
  898. ProfileDeferralMgr.activateProfiles();
  899. }
  900. return getData(ID, tagSignature);
  901. }
  902. static byte[] getData(long profileID, int tagSignature) {
  903. int[] tagSize = new int [1];
  904. byte[] tagData;
  905. try {
  906. /* get the number of bytes needed for this tag */
  907. CMM.checkStatus(CMM.cmmGetTagSize(profileID, tagSignature,
  908. tagSize));
  909. tagData = new byte[tagSize[0]]; /* get an array for the tag */
  910. /* get the tag's data */
  911. CMM.checkStatus(CMM.cmmGetTagData(profileID, tagSignature,
  912. tagData));
  913. } catch(CMMException c) {
  914. tagData = null;
  915. }
  916. return tagData;
  917. }
  918. /**
  919. * Sets a particular tagged data element in the profile from
  920. * a byte array. This method is useful
  921. * for advanced applets or applications which need to access
  922. * profile data directly.
  923. */
  924. public void setData(int tagSignature, byte[] tagData) {
  925. if (ProfileDeferralMgr.deferring) {
  926. ProfileDeferralMgr.activateProfiles();
  927. }
  928. CMM.checkStatus(CMM.cmmSetTagData(ID, tagSignature, tagData));
  929. }
  930. /**
  931. * Sets the rendering intent of the profile.
  932. * This is used to select the proper transform from a profile that
  933. * has multiple transforms.
  934. */
  935. void setRenderingIntent(int renderingIntent) {
  936. byte[] theHeader = getData(icSigHead);/* getData will activate deferred
  937. profiles if necessary */
  938. intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent);
  939. /* set the rendering intent */
  940. setData (icSigHead, theHeader);
  941. }
  942. /**
  943. * Returns the rendering intent of the profile.
  944. * This is used to select the proper transform from a profile that
  945. * has multiple transforms. It is typically set in a source profile
  946. * to select a transform from an output profile.
  947. */
  948. int getRenderingIntent() {
  949. byte[] theHeader = getData(icSigHead);/* getData will activate deferred
  950. profiles if necessary */
  951. int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent);
  952. /* set the rendering intent */
  953. return renderingIntent;
  954. }
  955. /**
  956. * Returns the number of color components in the "input" color
  957. * space of this profile. For example if the color space type
  958. * of this profile is TYPE_RGB, then this method will return 3.
  959. */
  960. public int getNumComponents() {
  961. byte[] theHeader;
  962. int theColorSpaceSig, theNumComponents;
  963. if (deferralInfo != null) {
  964. return deferralInfo.numComponents; /* Need to have this info for
  965. ICC_ColorSpace without
  966. causing a deferred profile
  967. to be loaded */
  968. }
  969. theHeader = getData(icSigHead);
  970. theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace);
  971. switch (theColorSpaceSig) {
  972. case icSigGrayData:
  973. theNumComponents = 1;
  974. break;
  975. case icSigSpace2CLR:
  976. theNumComponents = 2;
  977. break;
  978. case icSigXYZData:
  979. case icSigLabData:
  980. case icSigLuvData:
  981. case icSigYCbCrData:
  982. case icSigYxyData:
  983. case icSigRgbData:
  984. case icSigHsvData:
  985. case icSigHlsData:
  986. case icSigCmyData:
  987. case icSigSpace3CLR:
  988. theNumComponents = 3;
  989. break;
  990. case icSigCmykData:
  991. case icSigSpace4CLR:
  992. theNumComponents = 4;
  993. break;
  994. case icSigSpace5CLR:
  995. theNumComponents = 5;
  996. break;
  997. case icSigSpace6CLR:
  998. theNumComponents = 6;
  999. break;
  1000. case icSigSpace7CLR:
  1001. theNumComponents = 7;
  1002. break;
  1003. case icSigSpace8CLR:
  1004. theNumComponents = 8;
  1005. break;
  1006. case icSigSpace9CLR:
  1007. theNumComponents = 9;
  1008. break;
  1009. case icSigSpaceACLR:
  1010. theNumComponents = 10;
  1011. break;
  1012. case icSigSpaceBCLR:
  1013. theNumComponents = 11;
  1014. break;
  1015. case icSigSpaceCCLR:
  1016. theNumComponents = 12;
  1017. break;
  1018. case icSigSpaceDCLR:
  1019. theNumComponents = 13;
  1020. break;
  1021. case icSigSpaceECLR:
  1022. theNumComponents = 14;
  1023. break;
  1024. case icSigSpaceFCLR:
  1025. theNumComponents = 15;
  1026. break;
  1027. default:
  1028. throw new ProfileDataException ("invalid ICC color space");
  1029. }
  1030. return theNumComponents;
  1031. }
  1032. /**
  1033. * Returns a float array of length 3 containing the X, Y, and Z
  1034. * components of the mediaWhitePointTag in the ICC profile.
  1035. */
  1036. float[] getMediaWhitePoint() {
  1037. return getXYZTag(icSigMediaWhitePointTag);
  1038. /* get the media white point tag */
  1039. }
  1040. /**
  1041. * Returns a float array of length 3 containing the X, Y, and Z
  1042. * components encoded in an XYZType tag.
  1043. */
  1044. float[] getXYZTag(int theTagSignature) {
  1045. byte[] theData;
  1046. float[] theXYZNumber;
  1047. int i1, i2, theS15Fixed16;
  1048. theData = getData(theTagSignature); /* get the tag data */
  1049. /* getData will activate deferred
  1050. profiles if necessary */
  1051. theXYZNumber = new float [3]; /* array to return */
  1052. /* convert s15Fixed16Number to float */
  1053. for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) {
  1054. theS15Fixed16 = intFromBigEndian(theData, i2);
  1055. theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f;
  1056. }
  1057. return theXYZNumber;
  1058. }
  1059. /**
  1060. * Returns a gamma value representing a tone reproduction
  1061. * curve (TRC). If the profile represents the TRC as a table rather
  1062. * than a single gamma value, then an exception is thrown. In this
  1063. * case the actual table can be obtained via getTRC().
  1064. * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag,
  1065. * icSigGreenTRCTag, or icSigBlueTRCTag.
  1066. * @return the gamma value as a float.
  1067. * @exception ProfileDataException if the profile does not specify
  1068. * the TRC as a single gamma value.
  1069. */
  1070. float getGamma(int theTagSignature) {
  1071. byte[] theTRCData;
  1072. float theGamma;
  1073. int theU8Fixed8;
  1074. theTRCData = getData(theTagSignature); /* get the TRC */
  1075. /* getData will activate deferred
  1076. profiles if necessary */
  1077. if (intFromBigEndian (theTRCData, icCurveCount) != 1) {
  1078. throw new ProfileDataException ("TRC is not a gamma");
  1079. }
  1080. /* convert u8Fixed8 to float */
  1081. theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff;
  1082. theGamma = ((float) theU8Fixed8) / 256.0f;
  1083. return theGamma;
  1084. }
  1085. /**
  1086. * Returns the TRC as an array of shorts. If the profile has
  1087. * specified the TRC as linear (gamma = 1.0) or as a simple gamma
  1088. * value, this method throws an exception, and the getGamma() method
  1089. * should be used to get the gamma value. Otherwise the short array
  1090. * returned here represents a lookup table where the input Gray value
  1091. * is conceptually in the range [0.0, 1.0]. Value 0.0 maps
  1092. * to array index 0 and value 1.0 maps to array index length-1.
  1093. * Interpolation may be used to generate output values for
  1094. * input values which do not map exactly to an index in the
  1095. * array. Output values also map linearly to the range [0.0, 1.0].
  1096. * Value 0.0 is represented by an array value of 0x0000 and
  1097. * value 1.0 by 0xFFFF, i.e. the values are really unsigned
  1098. * short values, although they are returned in a short array.
  1099. * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag,
  1100. * icSigGreenTRCTag, or icSigBlueTRCTag.
  1101. * @return a short array representing the TRC.
  1102. * @exception ProfileDataException if the profile does not specify
  1103. * the TRC as a table.
  1104. */
  1105. short[] getTRC(int theTagSignature) {
  1106. byte[] theTRCData;
  1107. short[] theTRC;
  1108. int i1, i2, nElements, theU8Fixed8;
  1109. theTRCData = getData(theTagSignature); /* get the TRC */
  1110. /* getData will activate deferred
  1111. profiles if necessary */
  1112. nElements = intFromBigEndian(theTRCData, icCurveCount);
  1113. if (nElements == 1) {
  1114. throw new ProfileDataException("TRC is not a table");
  1115. }
  1116. /* make the short array */
  1117. theTRC = new short [nElements];
  1118. for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) {
  1119. theTRC[i1] = shortFromBigEndian(theTRCData, i2);
  1120. }
  1121. return theTRC;
  1122. }
  1123. /* convert an ICC color space signature into a Java color space type */
  1124. static int iccCStoJCS(int theColorSpaceSig) {
  1125. int theColorSpace;
  1126. switch (theColorSpaceSig) {
  1127. case icSigXYZData:
  1128. theColorSpace = ColorSpace.TYPE_XYZ;
  1129. break;
  1130. case icSigLabData:
  1131. theColorSpace = ColorSpace.TYPE_Lab;
  1132. break;
  1133. case icSigLuvData:
  1134. theColorSpace = ColorSpace.TYPE_Luv;
  1135. break;
  1136. case icSigYCbCrData:
  1137. theColorSpace = ColorSpace.TYPE_YCbCr;
  1138. break;
  1139. case icSigYxyData:
  1140. theColorSpace = ColorSpace.TYPE_Yxy;
  1141. break;
  1142. case icSigRgbData:
  1143. theColorSpace = ColorSpace.TYPE_RGB;
  1144. break;
  1145. case icSigGrayData:
  1146. theColorSpace = ColorSpace.TYPE_GRAY;
  1147. break;
  1148. case icSigHsvData:
  1149. theColorSpace = ColorSpace.TYPE_HSV;
  1150. break;
  1151. case icSigHlsData:
  1152. theColorSpace = ColorSpace.TYPE_HLS;
  1153. break;
  1154. case icSigCmykData:
  1155. theColorSpace = ColorSpace.TYPE_CMYK;
  1156. break;
  1157. case icSigCmyData:
  1158. theColorSpace = ColorSpace.TYPE_CMY;
  1159. break;
  1160. case icSigSpace2CLR:
  1161. theColorSpace = ColorSpace.TYPE_2CLR;
  1162. break;
  1163. case icSigSpace3CLR:
  1164. theColorSpace = ColorSpace.TYPE_3CLR;
  1165. break;
  1166. case icSigSpace4CLR:
  1167. theColorSpace = ColorSpace.TYPE_4CLR;
  1168. break;
  1169. case icSigSpace5CLR:
  1170. theColorSpace = ColorSpace.TYPE_5CLR;
  1171. break;
  1172. case icSigSpace6CLR:
  1173. theColorSpace = ColorSpace.TYPE_6CLR;
  1174. break;
  1175. case icSigSpace7CLR:
  1176. theColorSpace = ColorSpace.TYPE_7CLR;
  1177. break;
  1178. case icSigSpace8CLR:
  1179. theColorSpace = ColorSpace.TYPE_8CLR;
  1180. break;
  1181. case icSigSpace9CLR:
  1182. theColorSpace = ColorSpace.TYPE_9CLR;
  1183. break;
  1184. case icSigSpaceACLR:
  1185. theColorSpace = ColorSpace.TYPE_ACLR;
  1186. break;
  1187. case icSigSpaceBCLR:
  1188. theColorSpace = ColorSpace.TYPE_BCLR;
  1189. break;
  1190. case icSigSpaceCCLR:
  1191. theColorSpace = ColorSpace.TYPE_CCLR;
  1192. break;
  1193. case icSigSpaceDCLR:
  1194. theColorSpace = ColorSpace.TYPE_DCLR;
  1195. break;
  1196. case icSigSpaceECLR:
  1197. theColorSpace = ColorSpace.TYPE_ECLR;
  1198. break;
  1199. case icSigSpaceFCLR:
  1200. theColorSpace = ColorSpace.TYPE_FCLR;
  1201. break;
  1202. default:
  1203. throw new IllegalArgumentException ("Unknown color space");
  1204. }
  1205. return theColorSpace;
  1206. }
  1207. static int intFromBigEndian(byte[] array, int index) {
  1208. return (((array[index] & 0xff) << 24) |
  1209. ((array[index+1] & 0xff) << 16) |
  1210. ((array[index+2] & 0xff) << 8) |
  1211. (array[index+3] & 0xff));
  1212. }
  1213. static void intToBigEndian(int value, byte[] array, int index) {
  1214. array[index] = (byte) (value >> 24);
  1215. array[index+1] = (byte) (value >> 16);
  1216. array[index+2] = (byte) (value >> 8);
  1217. array[index+3] = (byte) (value);
  1218. }
  1219. static short shortFromBigEndian(byte[] array, int index) {
  1220. return (short) (((array[index] & 0xff) << 8) |
  1221. (array[index+1] & 0xff));
  1222. }
  1223. static void shortToBigEndian(short value, byte[] array, int index) {
  1224. array[index] = (byte) (value >> 8);
  1225. array[index+1] = (byte) (value);
  1226. }
  1227. /*
  1228. * fileName may be an absolute or a relative file specification.
  1229. * Relative file names are looked for in several places: first, relative
  1230. * to any directories specified by the java.iccprofile.path property;
  1231. * second, relative to any directories specified by the java.class.path
  1232. * property; finally, in a directory used to store profiles always
  1233. * available, such as a profile for sRGB. Built-in profiles use .pf as
  1234. * the file name extension for profiles, e.g. sRGB.pf.
  1235. */
  1236. private static FileInputStream openProfile(final String fileName) {
  1237. return (FileInputStream)java.security.AccessController.doPrivileged(
  1238. new java.security.PrivilegedAction() {
  1239. public Object run() {
  1240. return privilegedOpenProfile(fileName);
  1241. }
  1242. });
  1243. }
  1244. /*
  1245. * this version is called from doPrivileged in privilegedOpenProfile.
  1246. * the whole method is privileged!
  1247. */
  1248. private static FileInputStream privilegedOpenProfile(String fileName) {
  1249. FileInputStream fis = null;
  1250. String path, dir, fullPath;
  1251. try {
  1252. fis = new FileInputStream(fileName); /* absolute file name */
  1253. }
  1254. catch (FileNotFoundException e) {
  1255. }
  1256. if ((fis == null) &&
  1257. ((path = System.getProperty("java.iccprofile.path")) != null)){
  1258. /* try relative to java.iccprofile.path */
  1259. StringTokenizer st =
  1260. new StringTokenizer(path, File.pathSeparator);
  1261. while (st.hasMoreTokens() && (fis == null)) {
  1262. dir = st.nextToken();
  1263. try {
  1264. fullPath = dir + File.separatorChar + fileName;
  1265. fis = new FileInputStream(fullPath);
  1266. }
  1267. catch (FileNotFoundException e) {
  1268. }
  1269. }
  1270. }
  1271. if ((fis == null) &&
  1272. ((path = System.getProperty("java.class.path")) != null)) {
  1273. /* try relative to java.class.path */
  1274. StringTokenizer st =
  1275. new StringTokenizer(path, File.pathSeparator);
  1276. while (st.hasMoreTokens() && (fis == null)) {
  1277. dir = st.nextToken();
  1278. try {
  1279. fullPath = dir + File.separatorChar + fileName;
  1280. fis = new FileInputStream(fullPath);
  1281. }
  1282. catch (FileNotFoundException e) {
  1283. }
  1284. }
  1285. }
  1286. if (fis == null) { /* try the directory of built-in profiles */
  1287. dir = System.getProperty("java.home") +
  1288. File.separatorChar + "lib" + File.separatorChar + "cmm";
  1289. fullPath = dir + File.separatorChar + fileName;
  1290. try {
  1291. fis = new FileInputStream(fullPath);
  1292. }
  1293. catch (FileNotFoundException e) {
  1294. }
  1295. }
  1296. return fis;
  1297. }
  1298. }