Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 73 additions & 130 deletions jdk/src/share/classes/java/awt/color/ICC_Profile.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -40,9 +40,7 @@
import sun.java2d.cmm.CMSManager;
import sun.java2d.cmm.Profile;
import sun.java2d.cmm.ProfileDataVerifier;
import sun.java2d.cmm.ProfileDeferralMgr;
import sun.java2d.cmm.ProfileDeferralInfo;
import sun.java2d.cmm.ProfileActivator;
import sun.misc.IOUtils;

import java.io.BufferedInputStream;
Expand All @@ -57,6 +55,7 @@
import java.io.ObjectStreamException;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.FilePermission;

import java.util.StringTokenizer;

Expand Down Expand Up @@ -97,10 +96,8 @@ public class ICC_Profile implements Serializable {

private static final long serialVersionUID = -3938515861990936766L;

private transient Profile cmmProfile;

private transient ProfileDeferralInfo deferralInfo;
private transient ProfileActivator profileActivator;
private transient volatile Profile cmmProfile;
private transient volatile ProfileDeferralInfo deferralInfo;

// Registry of singleton profile objects for specific color spaces
// defined in the ColorSpace class (e.g. CS_sRGB), see
Expand Down Expand Up @@ -740,13 +737,7 @@ public class ICC_Profile implements Serializable {
* The ID will be 0 until the profile is loaded.
*/
ICC_Profile(ProfileDeferralInfo pdi) {
this.deferralInfo = pdi;
this.profileActivator = new ProfileActivator() {
public void activate() throws ProfileDataException {
activateDeferredProfile();
}
};
ProfileDeferralMgr.registerDeferral(this.profileActivator);
deferralInfo = pdi;
}


Expand All @@ -756,8 +747,6 @@ public void activate() throws ProfileDataException {
protected void finalize () {
if (cmmProfile != null) {
CMSManager.getModule().freeProfile(cmmProfile);
} else if (profileActivator != null) {
ProfileDeferralMgr.unregisterDeferral(profileActivator);
}
}

Expand All @@ -775,10 +764,6 @@ public static ICC_Profile getInstance(byte[] data) {

Profile p = null;

if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles();
}

ProfileDataVerifier.verify(data);

try {
Expand Down Expand Up @@ -842,11 +827,11 @@ public static ICC_Profile getInstance (int cspace) {
* Enabling the appropriate access privileges is handled
* at a lower level.
*/
ProfileDeferralInfo pInfo =
ProfileDeferralInfo pdi =
new ProfileDeferralInfo("sRGB.pf",
ColorSpace.TYPE_RGB, 3,
CLASS_DISPLAY);
sRGBprofile = getDeferredInstance(pInfo);
sRGBprofile = new ICC_ProfileRGB(pdi);
}
thisProfile = sRGBprofile;
}
Expand All @@ -856,11 +841,11 @@ public static ICC_Profile getInstance (int cspace) {
case ColorSpace.CS_CIEXYZ:
synchronized(ICC_Profile.class) {
if (XYZprofile == null) {
ProfileDeferralInfo pInfo =
ProfileDeferralInfo pdi =
new ProfileDeferralInfo("CIEXYZ.pf",
ColorSpace.TYPE_XYZ, 3,
CLASS_DISPLAY);
XYZprofile = getDeferredInstance(pInfo);
CLASS_ABSTRACT);
XYZprofile = new ICC_Profile(pdi);
}
thisProfile = XYZprofile;
}
Expand All @@ -872,11 +857,11 @@ public static ICC_Profile getInstance (int cspace) {
if (PYCCprofile == null) {
if (standardProfileExists("PYCC.pf"))
{
ProfileDeferralInfo pInfo =
ProfileDeferralInfo pdi =
new ProfileDeferralInfo("PYCC.pf",
ColorSpace.TYPE_3CLR, 3,
CLASS_DISPLAY);
PYCCprofile = getDeferredInstance(pInfo);
CLASS_COLORSPACECONVERSION);
PYCCprofile = new ICC_Profile(pdi);
} else {
throw new IllegalArgumentException(
"Can't load standard profile: PYCC.pf");
Expand All @@ -890,11 +875,11 @@ public static ICC_Profile getInstance (int cspace) {
case ColorSpace.CS_GRAY:
synchronized(ICC_Profile.class) {
if (GRAYprofile == null) {
ProfileDeferralInfo pInfo =
ProfileDeferralInfo pdi =
new ProfileDeferralInfo("GRAY.pf",
ColorSpace.TYPE_GRAY, 1,
CLASS_DISPLAY);
GRAYprofile = getDeferredInstance(pInfo);
GRAYprofile = new ICC_ProfileGray(pdi);
}
thisProfile = GRAYprofile;
}
Expand All @@ -904,11 +889,11 @@ public static ICC_Profile getInstance (int cspace) {
case ColorSpace.CS_LINEAR_RGB:
synchronized(ICC_Profile.class) {
if (LINEAR_RGBprofile == null) {
ProfileDeferralInfo pInfo =
ProfileDeferralInfo pdi =
new ProfileDeferralInfo("LINEAR_RGB.pf",
ColorSpace.TYPE_RGB, 3,
CLASS_DISPLAY);
LINEAR_RGBprofile = getDeferredInstance(pInfo);
LINEAR_RGBprofile = new ICC_ProfileRGB(pdi);
}
thisProfile = LINEAR_RGBprofile;
}
Expand Down Expand Up @@ -1005,13 +990,7 @@ public static ICC_Profile getInstance(String fileName) throws IOException {
* contain valid ICC Profile data.
*/
public static ICC_Profile getInstance(InputStream s) throws IOException {
byte profileData[];

if (s instanceof ProfileDeferralInfo) {
/* hack to detect profiles whose loading can be deferred */
return getDeferredInstance((ProfileDeferralInfo) s);
}

byte[] profileData;
if ((profileData = getProfileDataFromStream(s)) == null) {
throw new IllegalArgumentException("Invalid ICC Profile Data");
}
Expand Down Expand Up @@ -1044,73 +1023,32 @@ static byte[] getProfileDataFromStream(InputStream s) throws IOException {


/**
* Constructs an ICC_Profile for which the actual loading of the
* profile data from a file and the initialization of the CMM should
* be deferred as long as possible.
* Deferral is only used for standard profiles.
* If deferring is disabled, then getStandardProfile() ensures
* that all of the appropriate access privileges are granted
* when loading this profile.
* If deferring is enabled, then the deferred activation
* code will take care of access privileges.
* @see activateDeferredProfile()
* Activates the deferred standard profiles. Implementation of this method
* mimics the old behaviour when the CMMException and IOException were
* wrapped by the ProfileDataException, and the ProfileDataException itself
* was ignored during activation.
*/
static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) {
if (!ProfileDeferralMgr.deferring) {
return getStandardProfile(pdi.filename);
}
if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
return new ICC_ProfileRGB(pdi);
} else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
return new ICC_ProfileGray(pdi);
} else {
return new ICC_Profile(pdi);
}
}


void activateDeferredProfile() throws ProfileDataException {
byte profileData[];
FileInputStream fis;
final String fileName = deferralInfo.filename;

profileActivator = null;
deferralInfo = null;
PrivilegedAction<FileInputStream> pa = new PrivilegedAction<FileInputStream>() {
public FileInputStream run() {
File f = getStandardProfileFile(fileName);
if (f != null) {
try {
return new FileInputStream(f);
} catch (FileNotFoundException e) {}
private void activate() {
if (cmmProfile == null) {
synchronized (this) {
if (cmmProfile != null) {
return;
}
InputStream is = getStandardProfileInputStream(deferralInfo.filename);
if (is == null) {
return;
}
try {
byte[] data = getProfileDataFromStream(is);
if (data != null) {
cmmProfile = CMSManager.getModule().loadProfile(data);
// from now we cannot use the deferred value, drop it
deferralInfo = null;
}
is.close(); /* close the stream */
} catch (CMMException | IOException ignore) {
}
return null;
}
};
if ((fis = AccessController.doPrivileged(pa)) == null) {
throw new ProfileDataException("Cannot open file " + fileName);
}
try {
profileData = getProfileDataFromStream(fis);
fis.close(); /* close the file */
}
catch (IOException e) {
ProfileDataException pde = new
ProfileDataException("Invalid ICC Profile Data" + fileName);
pde.initCause(e);
throw pde;
}
if (profileData == null) {
throw new ProfileDataException("Invalid ICC Profile Data" +
fileName);
}
try {
cmmProfile = CMSManager.getModule().loadProfile(profileData);
} catch (CMMException c) {
ProfileDataException pde = new
ProfileDataException("Invalid ICC Profile Data" + fileName);
pde.initCause(c);
throw pde;
}
}

Expand Down Expand Up @@ -1149,11 +1087,9 @@ public int getProfileClass() {
byte[] theHeader;
int theClassSig, theClass;

if (deferralInfo != null) {
return deferralInfo.profileClass; /* Need to have this info for
ICC_ColorSpace without
causing a deferred profile
to be loaded */
ProfileDeferralInfo info = deferralInfo;
if (info != null) {
return info.profileClass;
}

theHeader = getData(icSigHead);
Expand Down Expand Up @@ -1209,12 +1145,11 @@ public int getProfileClass() {
* <CODE>ColorSpace</CODE> class.
*/
public int getColorSpaceType() {
if (deferralInfo != null) {
return deferralInfo.colorSpaceType; /* Need to have this info for
ICC_ColorSpace without
causing a deferred profile
to be loaded */
ProfileDeferralInfo info = deferralInfo;
if (info != null) {
return info.colorSpaceType;
}
activate();
return getColorSpaceType(cmmProfile);
}

Expand All @@ -1241,9 +1176,7 @@ static int getColorSpaceType(Profile p) {
* <CODE>ColorSpace</CODE> class.
*/
public int getPCSType() {
if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles();
}
activate();
return getPCSType(cmmProfile);
}

Expand Down Expand Up @@ -1305,9 +1238,7 @@ public byte[] getData() {
int profileSize;
byte[] profileData;

if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles();
}
activate();

PCMM mdl = CMSManager.getModule();

Expand Down Expand Up @@ -1340,9 +1271,7 @@ public byte[] getData() {
*/
public byte[] getData(int tagSignature) {

if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles();
}
activate();

return getData(cmmProfile, tagSignature);
}
Expand Down Expand Up @@ -1388,9 +1317,7 @@ static byte[] getData(Profile p, int tagSignature) {
*/
public void setData(int tagSignature, byte[] tagData) {

if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles();
}
activate();

CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
}
Expand Down Expand Up @@ -1448,11 +1375,9 @@ public int getNumComponents() {
byte[] theHeader;
int theColorSpaceSig, theNumComponents;

if (deferralInfo != null) {
return deferralInfo.numComponents; /* Need to have this info for
ICC_ColorSpace without
causing a deferred profile
to be loaded */
ProfileDeferralInfo info = deferralInfo;
if (info != null) {
return info.numComponents;
}
theHeader = getData(icSigHead);

Expand Down Expand Up @@ -1536,6 +1461,24 @@ public int getNumComponents() {
return theNumComponents;
}

/**
* Returns a stream corresponding to a built-in profile
* specified by fileName.
* If there is no built-in profile with such name, then the method
* returns null.
*/
private static InputStream getStandardProfileInputStream(String fileName) {
return AccessController.doPrivileged(
new PrivilegedAction<InputStream>() {
public InputStream run () {
try {
return
new FileInputStream(getStandardProfileFile(fileName));
} catch(IOException ex) {return null;}
}
});
}


/**
* Returns a float array of length 3 containing the X, Y, and Z
Expand Down
Loading