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