提交 a3cc0ef8 编写于 作者: B bae

6523398: OSS CMM: Need to implement writing ICC profile tags in new lcms library

Reviewed-by: igor, prr
上级 be87c2b9
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
FILES_c = \ FILES_c = \
cmscam02.c \ cmscam02.c \
cmscam97.c \
cmscgats.c \ cmscgats.c \
cmscnvrt.c \ cmscnvrt.c \
cmserr.c \ cmserr.c \
...@@ -35,13 +34,17 @@ FILES_c = \ ...@@ -35,13 +34,17 @@ FILES_c = \
cmsio0.c \ cmsio0.c \
cmsio1.c \ cmsio1.c \
cmslut.c \ cmslut.c \
cmsmatsh.c \ cmsmd5.c \
cmsmtrx.c \ cmsmtrx.c \
cmsnamed.c \ cmsnamed.c \
cmsopt.c \
cmspack.c \ cmspack.c \
cmspcs.c \ cmspcs.c \
cmsplugin.c \
cmsps2.c \ cmsps2.c \
cmssamp.c \ cmssamp.c \
cmssm.c \
cmstypes.c \
cmsvirt.c \ cmsvirt.c \
cmswtpnt.c \ cmswtpnt.c \
cmsxform.c \ cmsxform.c \
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
FILES_c = \ FILES_c = \
cmscam02.c \ cmscam02.c \
cmscam97.c \
cmscgats.c \ cmscgats.c \
cmscnvrt.c \ cmscnvrt.c \
cmserr.c \ cmserr.c \
...@@ -35,13 +34,17 @@ FILES_c = \ ...@@ -35,13 +34,17 @@ FILES_c = \
cmsio0.c \ cmsio0.c \
cmsio1.c \ cmsio1.c \
cmslut.c \ cmslut.c \
cmsmatsh.c \ cmsmd5.c \
cmsmtrx.c \ cmsmtrx.c \
cmsnamed.c \ cmsnamed.c \
cmsopt.c \
cmspack.c \ cmspack.c \
cmspcs.c \ cmspcs.c \
cmsplugin.c \
cmsps2.c \ cmsps2.c \
cmssamp.c \ cmssamp.c \
cmssm.c \
cmstypes.c \
cmsvirt.c \ cmsvirt.c \
cmswtpnt.c \ cmswtpnt.c \
cmsxform.c \ cmsxform.c \
......
...@@ -80,8 +80,8 @@ vpath %.c $(SHARE_SRC)/native/$(PKGDIR) ...@@ -80,8 +80,8 @@ vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
vpath %.c $(SHARE_SRC)/native/sun/java2d vpath %.c $(SHARE_SRC)/native/sun/java2d
ifeq ($(PLATFORM), windows) ifeq ($(PLATFORM), windows)
OTHER_CFLAGS += -DCMS_IS_WINDOWS_ -Dsqrtf=sqrt
OTHER_LDLIBS = user32.lib version.lib $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib OTHER_LDLIBS = $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \ OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \
-I$(SHARE_SRC)/native/sun/awt/debug -I$(SHARE_SRC)/native/sun/awt/debug
......
...@@ -100,12 +100,12 @@ public class CMSManager { ...@@ -100,12 +100,12 @@ public class CMSManager {
public long loadProfile(byte[] data) { public long loadProfile(byte[] data) {
System.err.print(cName + ".loadProfile"); System.err.print(cName + ".loadProfile");
long profileID = tcmm.loadProfile(data); long profileID = tcmm.loadProfile(data);
System.err.println("(ID=" + profileID + ")"); System.err.printf("(ID=%x)\n", profileID);
return profileID; return profileID;
} }
public void freeProfile(long profileID) { public void freeProfile(long profileID) {
System.err.println(cName + ".freeProfile(ID=" + profileID + ")"); System.err.printf(cName + ".freeProfile(ID=%x)\n", profileID);
tcmm.freeProfile(profileID); tcmm.freeProfile(profileID);
} }
...@@ -123,8 +123,8 @@ public class CMSManager { ...@@ -123,8 +123,8 @@ public class CMSManager {
} }
public int getTagSize(long profileID, int tagSignature) { public int getTagSize(long profileID, int tagSignature) {
System.err.print(cName + ".getTagSize(ID=" + profileID + System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
", TagSig=" + tagSignature + ")"); profileID, signatureToString(tagSignature));
int size = tcmm.getTagSize(profileID, tagSignature); int size = tcmm.getTagSize(profileID, tagSignature);
System.err.println("=" + size); System.err.println("=" + size);
return size; return size;
...@@ -132,8 +132,8 @@ public class CMSManager { ...@@ -132,8 +132,8 @@ public class CMSManager {
public void getTagData(long profileID, int tagSignature, public void getTagData(long profileID, int tagSignature,
byte[] data) { byte[] data) {
System.err.print(cName + ".getTagData(ID=" + profileID + System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
", TagSig=" + tagSignature + ")"); profileID, signatureToString(tagSignature));
System.err.println(" requested " + data.length + " byte(s)"); System.err.println(" requested " + data.length + " byte(s)");
tcmm.getTagData(profileID, tagSignature, data); tcmm.getTagData(profileID, tagSignature, data);
} }
...@@ -158,5 +158,13 @@ public class CMSManager { ...@@ -158,5 +158,13 @@ public class CMSManager {
System.err.println(cName + ".createTransform(ColorTransform[])"); System.err.println(cName + ".createTransform(ColorTransform[])");
return tcmm.createTransform(transforms); return tcmm.createTransform(transforms);
} }
private static String signatureToString(int sig) {
return String.format("%c%c%c%c",
(char)(0xff & (sig >> 24)),
(char)(0xff & (sig >> 16)),
(char)(0xff & (sig >> 8)),
(char)(0xff & (sig )));
}
} }
} }
...@@ -53,7 +53,8 @@ public class LCMS implements PCMM { ...@@ -53,7 +53,8 @@ public class LCMS implements PCMM {
public static native long getProfileID(ICC_Profile profile); public static native long getProfileID(ICC_Profile profile);
public static native long createNativeTransform( public static native long createNativeTransform(
long[] profileIDs, int renderType, Object disposerRef); long[] profileIDs, int renderType, int inFormatter, int outFormatter,
Object disposerRef);
/** /**
* Constructs ColorTransform object corresponding to an ICC_profile * Constructs ColorTransform object corresponding to an ICC_profile
......
...@@ -55,11 +55,17 @@ import sun.java2d.cmm.lcms.*; ...@@ -55,11 +55,17 @@ import sun.java2d.cmm.lcms.*;
public class LCMSTransform implements ColorTransform { public class LCMSTransform implements ColorTransform {
long ID; long ID;
private int inFormatter;
private int outFormatter;
ICC_Profile[] profiles; ICC_Profile[] profiles;
long [] profileIDs; long [] profileIDs;
int renderType; int renderType;
int transformType; int transformType;
private int numInComponents = -1;
private int numOutComponents = -1;
private Object disposerReferent = new Object(); private Object disposerReferent = new Object();
/* the class initializer */ /* the class initializer */
...@@ -80,6 +86,14 @@ public class LCMSTransform implements ColorTransform { ...@@ -80,6 +86,14 @@ public class LCMSTransform implements ColorTransform {
this.renderType = (renderType == ColorTransform.Any)? this.renderType = (renderType == ColorTransform.Any)?
ICC_Profile.icPerceptual : renderType; ICC_Profile.icPerceptual : renderType;
this.transformType = transformType; this.transformType = transformType;
/* Note that ICC_Profile.getNumComponents() is quite expensive
* (it may results in a reading of the profile header).
* So, here we cache the number of components of input and
* output profiles for further usage.
*/
numInComponents = profiles[0].getNumComponents();
numOutComponents = profiles[profiles.length - 1].getNumComponents();
} }
public LCMSTransform (ColorTransform[] transforms) { public LCMSTransform (ColorTransform[] transforms) {
...@@ -99,26 +113,51 @@ public class LCMSTransform implements ColorTransform { ...@@ -99,26 +113,51 @@ public class LCMSTransform implements ColorTransform {
j += curTrans.profiles.length; j += curTrans.profiles.length;
} }
renderType = ((LCMSTransform)transforms[0]).renderType; renderType = ((LCMSTransform)transforms[0]).renderType;
ID = LCMS.createNativeTransform(profileIDs, renderType,
disposerReferent); /* Note that ICC_Profile.getNumComponents() is quite expensive
* (it may results in a reading of the profile header).
* So, here we cache the number of components of input and
* output profiles for further usage.
*/
numInComponents = profiles[0].getNumComponents();
numOutComponents = profiles[profiles.length - 1].getNumComponents();
} }
public int getNumInComponents() { public int getNumInComponents() {
return profiles[0].getNumComponents(); return numInComponents;
} }
public int getNumOutComponents() { public int getNumOutComponents() {
return profiles[profiles.length - 1].getNumComponents(); return numOutComponents;
}
private synchronized void doTransform(LCMSImageLayout in,
LCMSImageLayout out) {
// update native transfrom if needed
if (ID == 0L ||
inFormatter != in.pixelType ||
outFormatter != out.pixelType) {
if (ID != 0L) {
// Disposer will destroy forgotten transform
disposerReferent = new Object();
}
inFormatter = in.pixelType;
outFormatter = out.pixelType;
ID = LCMS.createNativeTransform(profileIDs, renderType,
inFormatter, outFormatter,
disposerReferent);
}
LCMS.colorConvert(this, in, out);
} }
public void colorConvert(BufferedImage src, BufferedImage dst) { public void colorConvert(BufferedImage src, BufferedImage dst) {
if (LCMSImageLayout.isSupported(src) && if (LCMSImageLayout.isSupported(src) &&
LCMSImageLayout.isSupported(dst)) LCMSImageLayout.isSupported(dst))
{ {
synchronized(this) { doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
LCMS.colorConvert(this, new LCMSImageLayout(src),
new LCMSImageLayout(dst));
}
return; return;
} }
LCMSImageLayout srcIL, dstIL; LCMSImageLayout srcIL, dstIL;
...@@ -204,9 +243,8 @@ public class LCMSTransform implements ColorTransform { ...@@ -204,9 +243,8 @@ public class LCMSTransform implements ColorTransform {
} }
} }
// color convert srcLine to dstLine // color convert srcLine to dstLine
synchronized (this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
// convert dst scanline // convert dst scanline
pixel = null; pixel = null;
idx = 0; idx = 0;
...@@ -263,9 +301,8 @@ public class LCMSTransform implements ColorTransform { ...@@ -263,9 +301,8 @@ public class LCMSTransform implements ColorTransform {
} }
} }
// color convert srcLine to dstLine // color convert srcLine to dstLine
synchronized(this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
// convert dst scanline // convert dst scanline
pixel = null; pixel = null;
idx = 0; idx = 0;
...@@ -377,9 +414,7 @@ public class LCMSTransform implements ColorTransform { ...@@ -377,9 +414,7 @@ public class LCMSTransform implements ColorTransform {
} }
// color convert srcLine to dstLine // color convert srcLine to dstLine
synchronized(this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
// store dst scanline // store dst scanline
xd = dst.getMinX(); xd = dst.getMinX();
...@@ -470,9 +505,7 @@ public class LCMSTransform implements ColorTransform { ...@@ -470,9 +505,7 @@ public class LCMSTransform implements ColorTransform {
} }
// color convert srcLine to dstLine // color convert srcLine to dstLine
synchronized(this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
// store dst scanline // store dst scanline
xd = dst.getMinX(); xd = dst.getMinX();
...@@ -513,9 +546,8 @@ public class LCMSTransform implements ColorTransform { ...@@ -513,9 +546,8 @@ public class LCMSTransform implements ColorTransform {
} }
// color convert srcLine to dstLine // color convert srcLine to dstLine
synchronized(this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
// store dst scanline // store dst scanline
xd = dst.getMinX(); xd = dst.getMinX();
idx = 0; idx = 0;
...@@ -550,9 +582,7 @@ public class LCMSTransform implements ColorTransform { ...@@ -550,9 +582,7 @@ public class LCMSTransform implements ColorTransform {
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
synchronized(this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
return dst; return dst;
} }
...@@ -572,9 +602,7 @@ public class LCMSTransform implements ColorTransform { ...@@ -572,9 +602,7 @@ public class LCMSTransform implements ColorTransform {
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
synchronized(this) { doTransform(srcIL, dstIL);
LCMS.colorConvert(this, srcIL, dstIL);
}
return dst; return dst;
} }
......
...@@ -27,9 +27,10 @@ ...@@ -27,9 +27,10 @@
// However, the following notice accompanied the original version of this // However, the following notice accompanied the original version of this
// file: // file:
// //
//---------------------------------------------------------------------------------
// //
// Little cms // Little Color Management System
// Copyright (C) 1998-2007 Marti Maria // Copyright (c) 1998-2010 Marti Maria Saguer
// //
// Permission is hereby granted, free of charge, to any person obtaining // Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"), // a copy of this software and associated documentation files (the "Software"),
...@@ -48,69 +49,65 @@ ...@@ -48,69 +49,65 @@
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
//
#include "lcms2_internal.h"
// CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging. // CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging.
#include "lcms.h"
LCMSAPI LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC);
LCMSAPI void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel);
LCMSAPI void LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut);
LCMSAPI void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ pOut);
// ---------- Implementation -------------------------------------------- // ---------- Implementation --------------------------------------------
typedef struct { typedef struct {
double XYZ[3]; cmsFloat64Number XYZ[3];
double RGB[3]; cmsFloat64Number RGB[3];
double RGBc[3]; cmsFloat64Number RGBc[3];
double RGBp[3]; cmsFloat64Number RGBp[3];
double RGBpa[3]; cmsFloat64Number RGBpa[3];
double a, b, h, e, H, A, J, Q, s, t, C, M; cmsFloat64Number a, b, h, e, H, A, J, Q, s, t, C, M;
double abC[2]; cmsFloat64Number abC[2];
double abs[2]; cmsFloat64Number abs[2];
double abM[2]; cmsFloat64Number abM[2];
} CAM02COLOR, *LPCAM02COLOR; } CAM02COLOR;
typedef struct { typedef struct {
CAM02COLOR adoptedWhite; CAM02COLOR adoptedWhite;
double LA, Yb; cmsFloat64Number LA, Yb;
double F, c, Nc; cmsFloat64Number F, c, Nc;
int surround; cmsUInt32Number surround;
double n, Nbb, Ncb, z, FL, D; cmsFloat64Number n, Nbb, Ncb, z, FL, D;
cmsContext ContextID;
} cmsCIECAM02, *LPcmsCIECAM02; } cmsCIECAM02;
static static
double compute_n(LPcmsCIECAM02 pMod) cmsFloat64Number compute_n(cmsCIECAM02* pMod)
{ {
return(pMod -> Yb / pMod -> adoptedWhite.XYZ[1]); return (pMod -> Yb / pMod -> adoptedWhite.XYZ[1]);
} }
static static
double compute_z(LPcmsCIECAM02 pMod) cmsFloat64Number compute_z(cmsCIECAM02* pMod)
{ {
return(1.48 + pow(pMod -> n, 0.5)); return (1.48 + pow(pMod -> n, 0.5));
} }
static static
double computeNbb(LPcmsCIECAM02 pMod) cmsFloat64Number computeNbb(cmsCIECAM02* pMod)
{ {
return(0.725 * pow((1.0 / pMod -> n), 0.2)); return (0.725 * pow((1.0 / pMod -> n), 0.2));
} }
static static
double computeFL(LPcmsCIECAM02 pMod) cmsFloat64Number computeFL(cmsCIECAM02* pMod)
{ {
double k, FL; cmsFloat64Number k, FL;
k = 1.0 / ((5.0 * pMod->LA) + 1.0); k = 1.0 / ((5.0 * pMod->LA) + 1.0);
FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 * FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 *
...@@ -121,9 +118,9 @@ double computeFL(LPcmsCIECAM02 pMod) ...@@ -121,9 +118,9 @@ double computeFL(LPcmsCIECAM02 pMod)
} }
static static
double computeD(LPcmsCIECAM02 pMod) cmsFloat64Number computeD(cmsCIECAM02* pMod)
{ {
double D; cmsFloat64Number D;
D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0))); D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0)));
...@@ -142,9 +139,10 @@ CAM02COLOR XYZtoCAT02(CAM02COLOR clr) ...@@ -142,9 +139,10 @@ CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
} }
static static
CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod) CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
{ {
int i; cmsUInt32Number i;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
clr.RGBc[i] = ((pMod -> adoptedWhite.XYZ[1] * clr.RGBc[i] = ((pMod -> adoptedWhite.XYZ[1] *
(pMod->D / pMod -> adoptedWhite.RGB[i])) + (pMod->D / pMod -> adoptedWhite.RGB[i])) +
...@@ -156,11 +154,9 @@ CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod) ...@@ -156,11 +154,9 @@ CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod)
static static
CAM02COLOR CAT02toHPE (CAM02COLOR clr) CAM02COLOR CAT02toHPE(CAM02COLOR clr)
{ {
cmsFloat64Number M[9];
double M[9];
M[0] =(( 0.38971 * 1.096124) + (0.68898 * 0.454369) + (-0.07868 * -0.009628)); M[0] =(( 0.38971 * 1.096124) + (0.68898 * 0.454369) + (-0.07868 * -0.009628));
M[1] =(( 0.38971 * -0.278869) + (0.68898 * 0.473533) + (-0.07868 * -0.005698)); M[1] =(( 0.38971 * -0.278869) + (0.68898 * 0.473533) + (-0.07868 * -0.005698));
...@@ -180,10 +176,10 @@ CAM02COLOR CAT02toHPE (CAM02COLOR clr) ...@@ -180,10 +176,10 @@ CAM02COLOR CAT02toHPE (CAM02COLOR clr)
} }
static static
CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod) CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
{ {
int i; cmsUInt32Number i;
double temp; cmsFloat64Number temp;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (clr.RGBp[i] < 0) { if (clr.RGBp[i] < 0) {
...@@ -204,9 +200,9 @@ CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod) ...@@ -204,9 +200,9 @@ CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod)
} }
static static
CAM02COLOR ComputeCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod) CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
{ {
double a, b, temp, e, t, r2d, d2r; cmsFloat64Number a, b, temp, e, t, r2d, d2r;
a = clr.RGBpa[0] - (12.0 * clr.RGBpa[1] / 11.0) + (clr.RGBpa[2] / 11.0); a = clr.RGBpa[0] - (12.0 * clr.RGBpa[1] / 11.0) + (clr.RGBpa[2] / 11.0);
b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0; b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0;
...@@ -274,10 +270,10 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod) ...@@ -274,10 +270,10 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
static static
CAM02COLOR InverseCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod) CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
{ {
double t, e, p1, p2, p3, p4, p5, hr, d2r; cmsFloat64Number t, e, p1, p2, p3, p4, p5, hr, d2r;
d2r = 3.141592654 / 180.0; d2r = 3.141592654 / 180.0;
t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) * t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) *
...@@ -327,10 +323,10 @@ CAM02COLOR InverseCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod) ...@@ -327,10 +323,10 @@ CAM02COLOR InverseCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
} }
static static
CAM02COLOR InverseNonlinearity(CAM02COLOR clr, LPcmsCIECAM02 pMod) CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod)
{ {
int i; cmsUInt32Number i;
double c1; cmsFloat64Number c1;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1; if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1;
...@@ -347,7 +343,7 @@ CAM02COLOR InverseNonlinearity(CAM02COLOR clr, LPcmsCIECAM02 pMod) ...@@ -347,7 +343,7 @@ CAM02COLOR InverseNonlinearity(CAM02COLOR clr, LPcmsCIECAM02 pMod)
static static
CAM02COLOR HPEtoCAT02(CAM02COLOR clr) CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
{ {
double M[9]; cmsFloat64Number M[9];
M[0] = (( 0.7328 * 1.910197) + (0.4296 * 0.370950)); M[0] = (( 0.7328 * 1.910197) + (0.4296 * 0.370950));
M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054)); M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054));
...@@ -362,19 +358,19 @@ CAM02COLOR HPEtoCAT02(CAM02COLOR clr) ...@@ -362,19 +358,19 @@ CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
clr.RGBc[0] = (clr.RGBp[0] * M[0]) + (clr.RGBp[1] * M[1]) + (clr.RGBp[2] * M[2]); clr.RGBc[0] = (clr.RGBp[0] * M[0]) + (clr.RGBp[1] * M[1]) + (clr.RGBp[2] * M[2]);
clr.RGBc[1] = (clr.RGBp[0] * M[3]) + (clr.RGBp[1] * M[4]) + (clr.RGBp[2] * M[5]); clr.RGBc[1] = (clr.RGBp[0] * M[3]) + (clr.RGBp[1] * M[4]) + (clr.RGBp[2] * M[5]);
clr.RGBc[2] = (clr.RGBp[0] * M[6]) + (clr.RGBp[1] * M[7]) + (clr.RGBp[2] * M[8]); clr.RGBc[2] = (clr.RGBp[0] * M[6]) + (clr.RGBp[1] * M[7]) + (clr.RGBp[2] * M[8]);
return (clr); return clr;
} }
static static
CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod) CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
{ {
int i; cmsUInt32Number i;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
clr.RGB[i] = clr.RGBc[i] / clr.RGB[i] = clr.RGBc[i] /
((pMod->adoptedWhite.XYZ[1] * pMod->D / pMod->adoptedWhite.RGB[i]) + 1.0 - pMod->D); ((pMod->adoptedWhite.XYZ[1] * pMod->D / pMod->adoptedWhite.RGB[i]) + 1.0 - pMod->D);
} }
return(clr); return clr;
} }
...@@ -385,23 +381,21 @@ CAM02COLOR CAT02toXYZ(CAM02COLOR clr) ...@@ -385,23 +381,21 @@ CAM02COLOR CAT02toXYZ(CAM02COLOR clr)
clr.XYZ[1] = (clr.RGB[0] * 0.454369) + (clr.RGB[1] * 0.473533) + (clr.RGB[2] * 0.072098); clr.XYZ[1] = (clr.RGB[0] * 0.454369) + (clr.RGB[1] * 0.473533) + (clr.RGB[2] * 0.072098);
clr.XYZ[2] = (clr.RGB[0] * -0.009628) + (clr.RGB[1] * -0.005698) + (clr.RGB[2] * 1.015326); clr.XYZ[2] = (clr.RGB[0] * -0.009628) + (clr.RGB[1] * -0.005698) + (clr.RGB[2] * 1.015326);
return(clr); return clr;
} }
cmsHANDLE CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC)
LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
{ {
LPcmsCIECAM02 lpMod; cmsCIECAM02* lpMod;
_cmsAssert(pVC != NULL);
if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) { if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) {
return (LCMSHANDLE) NULL; return NULL;
} }
lpMod ->ContextID = ContextID;
ZeroMemory(lpMod, sizeof(cmsCIECAM02));
lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X; lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X;
lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y; lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y;
...@@ -414,36 +408,30 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC) ...@@ -414,36 +408,30 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
switch (lpMod -> surround) { switch (lpMod -> surround) {
case AVG_SURROUND_4:
lpMod->F = 1.0; // Not included in CAM02 case CUTSHEET_SURROUND:
lpMod->c = 0.69; lpMod->F = 0.8;
lpMod->Nc = 1.0; lpMod->c = 0.41;
break; lpMod->Nc = 0.8;
break;
case CUTSHEET_SURROUND:
lpMod->F = 0.8; case DARK_SURROUND:
lpMod->c = 0.41; lpMod -> F = 0.8;
lpMod->Nc = 0.8; lpMod -> c = 0.525;
break; lpMod -> Nc = 0.8;
break;
case DARK_SURROUND:
lpMod -> F = 0.8; case DIM_SURROUND:
lpMod -> c = 0.525; lpMod -> F = 0.9;
lpMod -> Nc = 0.8; lpMod -> c = 0.59;
break; lpMod -> Nc = 0.95;
break;
case DIM_SURROUND: default:
lpMod -> F = 0.9; // Average surround
lpMod -> c = 0.59; lpMod -> F = 1.0;
lpMod -> Nc = 0.95; lpMod -> c = 0.69;
break; lpMod -> Nc = 1.0;
default:
// Average surround
lpMod -> F = 1.0;
lpMod -> c = 0.69;
lpMod -> Nc = 1.0;
} }
lpMod -> n = compute_n(lpMod); lpMod -> n = compute_n(lpMod);
...@@ -451,10 +439,8 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC) ...@@ -451,10 +439,8 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
lpMod -> Nbb = computeNbb(lpMod); lpMod -> Nbb = computeNbb(lpMod);
lpMod -> FL = computeFL(lpMod); lpMod -> FL = computeFL(lpMod);
if (lpMod -> D == D_CALCULATE || if (lpMod -> D == D_CALCULATE) {
lpMod -> D == D_CALCULATE_DISCOUNT) { lpMod -> D = computeD(lpMod);
lpMod -> D = computeD(lpMod);
} }
lpMod -> Ncb = lpMod -> Nbb; lpMod -> Ncb = lpMod -> Nbb;
...@@ -464,21 +450,26 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC) ...@@ -464,21 +450,26 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite); lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod); lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
return (LCMSHANDLE) lpMod; return (cmsHANDLE) lpMod;
} }
void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel) void CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel)
{ {
LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
if (lpMod) _cmsFree(lpMod);
if (lpMod) _cmsFree(lpMod ->ContextID, lpMod);
} }
void LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut) void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut)
{ {
CAM02COLOR clr; CAM02COLOR clr;
LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
clr.XYZ[0] = pIn ->X; clr.XYZ[0] = pIn ->X;
clr.XYZ[1] = pIn ->Y; clr.XYZ[1] = pIn ->Y;
...@@ -495,11 +486,14 @@ void LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh ...@@ -495,11 +486,14 @@ void LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh
pOut ->h = clr.h; pOut ->h = clr.h;
} }
void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ pOut) void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut)
{ {
CAM02COLOR clr; CAM02COLOR clr;
LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel; cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
clr.J = pIn -> J; clr.J = pIn -> J;
clr.C = pIn -> C; clr.C = pIn -> C;
...@@ -514,6 +508,5 @@ void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ ...@@ -514,6 +508,5 @@ void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ
pOut ->X = clr.XYZ[0]; pOut ->X = clr.XYZ[0];
pOut ->Y = clr.XYZ[1]; pOut ->Y = clr.XYZ[1];
pOut ->Z = clr.XYZ[2]; pOut ->Z = clr.XYZ[2];
} }
...@@ -27,9 +27,10 @@ ...@@ -27,9 +27,10 @@
// However, the following notice accompanied the original version of this // However, the following notice accompanied the original version of this
// file: // file:
// //
//---------------------------------------------------------------------------------
// //
// Little cms // Little Color Management System
// Copyright (C) 1998-2007 Marti Maria // Copyright (c) 1998-2010 Marti Maria Saguer
// //
// Permission is hereby granted, free of charge, to any person obtaining // Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"), // a copy of this software and associated documentation files (the "Software"),
...@@ -48,92 +49,399 @@ ...@@ -48,92 +49,399 @@
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
#include "lcms2_internal.h"
#include "lcms.h" // I am so tired about incompatibilities on those functions that here are some replacements
// that hopefully would be fully portable.
// compare two strings ignoring case
int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2)
{
register const unsigned char *us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
// As a rule, only the functions visible from API can signal while (toupper(*us1) == toupper(*us2++))
// errors. if (*us1++ == '\0')
return (0);
return (toupper(*us1) - toupper(*--us2));
}
void cdecl cmsSignalError(int ErrorCode, const char *ErrorText, ...); // long int because C99 specifies ftell in such way (7.19.9.2)
long int CMSEXPORT cmsfilelength(FILE* f)
{
long int n;
int LCMSEXPORT cmsErrorAction(int lAbort); if (fseek(f, 0, SEEK_END) != 0) {
void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn); return -1;
}
n = ftell(f);
fseek(f, 0, SEEK_SET);
return n;
}
// Memory handling ------------------------------------------------------------------
//
// This is the interface to low-level memory management routines. By default a simple
// wrapping to malloc/free/realloc is provided, although there is a limit on the max
// amount of memoy that can be reclaimed. This is mostly as a safety feature to
// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms
// would never need.
// ****************************************************************** #define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U))
static int nDoAbort = LCMS_ERROR_ABORT; // User may override this behaviour by using a memory plug-in, which basically replaces
static cmsErrorHandlerFunction UserErrorHandler = (cmsErrorHandlerFunction) NULL; // the default memory management functions. In this case, no check is performed and it
// is up to the plug-in writter to keep in the safe side. There are only three functions
// required to be implemented: malloc, realloc and free, although the user may want to
// replace the optional mallocZero, calloc and dup as well.
cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
int LCMSEXPORT cmsErrorAction(int nAction) // *********************************************************************************
// This is the default memory allocation function. It does a very coarse
// check of amout of memory, just to prevent exploits
static
void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size)
{ {
int nOld = nDoAbort; if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never allow over maximum
nDoAbort = nAction;
return (void*) malloc(size);
return nOld; cmsUNUSED_PARAMETER(ContextID);
} }
void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn) // Generic allocate & zero
static
void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size)
{ {
UserErrorHandler = Fn; void *pt = _cmsMalloc(ContextID, size);
if (pt == NULL) return NULL;
memset(pt, 0, size);
return pt;
} }
// Default error handler // The default free function. The only check proformed is against NULL pointers
static
void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr)
{
// free(NULL) is defined a no-op by C99, therefore it is safe to
// avoid the check, but it is here just in case...
if (Ptr) free(Ptr);
cmsUNUSED_PARAMETER(ContextID);
}
void cmsSignalError(int ErrorCode, const char *ErrorText, ...) // The default realloc function. Again it check for exploits. If Ptr is NULL,
// realloc behaves the same way as malloc and allocates a new block of size bytes.
static
void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
{ {
va_list args;
if (nDoAbort == LCMS_ERROR_IGNORE) return; if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never realloc over 512Mb
va_start(args, ErrorText); return realloc(Ptr, size);
if (UserErrorHandler != NULL) { cmsUNUSED_PARAMETER(ContextID);
}
char Buffer[1024];
vsnprintf(Buffer, 1023, ErrorText, args); // The default calloc function. Allocates an array of num elements, each one of size bytes
va_end(args); // all memory is initialized to zero.
static
void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
{
cmsUInt32Number Total = num * size;
if (UserErrorHandler(ErrorCode, Buffer)) { // Check for overflow
if (Total < num || Total < size) {
return NULL;
}
return; if (Total > MAX_MEMORY_FOR_ALLOC) return NULL; // Never alloc over 512Mb
}
}
#if defined( __CONSOLE__ ) || defined( NON_WINDOWS ) return _cmsMallocZero(ContextID, Total);
}
fprintf(stderr, "lcms: Error #%d; ", ErrorCode); // Generic block duplication
vfprintf(stderr, ErrorText, args); static
fprintf(stderr, "\n"); void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size)
va_end(args); {
void* mem;
if (nDoAbort == LCMS_ERROR_ABORT) exit(1); if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb
#else
{
char Buffer1[1024];
char Buffer2[256];
snprintf(Buffer1, 767, "Error #%x; ", ErrorCode); mem = _cmsMalloc(ContextID, size);
vsnprintf(Buffer2, 255, ErrorText, args);
strcat(Buffer1, Buffer2);
MessageBox(NULL, Buffer1, "Little cms",
MB_OK|MB_ICONSTOP|MB_TASKMODAL);
va_end(args);
if (nDoAbort == LCMS_ERROR_ABORT) { if (mem != NULL && Org != NULL)
memmove(mem, Org, size);
#ifdef __BORLANDC__ return mem;
_cexit(); }
#endif
// Pointers to malloc and _cmsFree functions in current environment
static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn;
static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn;
static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn;
static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn;
static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn;
static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn;
FatalAppExit(0, "lcms is terminating application"); // Plug-in replacement entry
} cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
} {
#endif cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
// NULL forces to reset to defaults
if (Data == NULL) {
MallocPtr = _cmsMallocDefaultFn;
MallocZeroPtr= _cmsMallocZeroDefaultFn;
FreePtr = _cmsFreeDefaultFn;
ReallocPtr = _cmsReallocDefaultFn;
CallocPtr = _cmsCallocDefaultFn;
DupPtr = _cmsDupDefaultFn;
return TRUE;
}
// Check for required callbacks
if (Plugin -> MallocPtr == NULL ||
Plugin -> FreePtr == NULL ||
Plugin -> ReallocPtr == NULL) return FALSE;
// Set replacement functions
MallocPtr = Plugin -> MallocPtr;
FreePtr = Plugin -> FreePtr;
ReallocPtr = Plugin -> ReallocPtr;
if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr;
if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr;
if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr;
return TRUE;
}
// Generic allocate
void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size)
{
return MallocPtr(ContextID, size);
}
// Generic allocate & zero
void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size)
{
return MallocZeroPtr(ContextID, size);
} }
// Generic calloc
void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
{
return CallocPtr(ContextID, num, size);
}
// Generic reallocate
void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
{
return ReallocPtr(ContextID, Ptr, size);
}
// Generic free memory
void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr)
{
if (Ptr != NULL) FreePtr(ContextID, Ptr);
}
// Generic block duplication
void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size)
{
return DupPtr(ContextID, Org, size);
}
// ********************************************************************************************
// Sub allocation takes care of many pointers of small size. The memory allocated in
// this way have be freed at once. Next function allocates a single chunk for linked list
// I prefer this method over realloc due to the big inpact on xput realloc may have if
// memory is being swapped to disk. This approach is safer (although thats not true on any platform)
static
_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial)
{
_cmsSubAllocator_chunk* chunk;
// Create the container
chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk));
if (chunk == NULL) return NULL;
// Initialize values
chunk ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial);
if (chunk ->Block == NULL) {
// Something went wrong
_cmsFree(ContextID, chunk);
return NULL;
}
// 20K by default
if (Initial == 0)
Initial = 20*1024;
chunk ->BlockSize = Initial;
chunk ->Used = 0;
chunk ->next = NULL;
return chunk;
}
// The suballocated is nothing but a pointer to the first element in the list. We also keep
// the thread ID in this structure.
_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial)
{
_cmsSubAllocator* sub;
// Create the container
sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator));
if (sub == NULL) return NULL;
sub ->ContextID = ContextID;
sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial);
if (sub ->h == NULL) {
_cmsFree(ContextID, sub);
return NULL;
}
return sub;
}
// Get rid of whole linked list
void _cmsSubAllocDestroy(_cmsSubAllocator* sub)
{
_cmsSubAllocator_chunk *chunk, *n;
for (chunk = sub ->h; chunk != NULL; chunk = n) {
n = chunk->next;
if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block);
_cmsFree(sub ->ContextID, chunk);
}
// Free the header
_cmsFree(sub ->ContextID, sub);
}
// Get a pointer to small memory block.
void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
{
cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used;
cmsUInt8Number* ptr;
size = _cmsALIGNLONG(size);
// Check for memory. If there is no room, allocate a new chunk of double memory size.
if (size > Free) {
_cmsSubAllocator_chunk* chunk;
cmsUInt32Number newSize;
newSize = sub -> h ->BlockSize * 2;
if (newSize < size) newSize = size;
chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize);
if (chunk == NULL) return NULL;
// Link list
chunk ->next = sub ->h;
sub ->h = chunk;
}
ptr = sub -> h ->Block + sub -> h ->Used;
sub -> h -> Used += size;
return (void*) ptr;
}
// Error logging ******************************************************************
// There is no error handling at all. When a funtion fails, it returns proper value.
// For example, all create functions does return NULL on failure. Other return FALSE
// It may be interesting, for the developer, to know why the function is failing.
// for that reason, lcms2 does offer a logging function. This function does recive
// a ENGLISH string with some clues on what is going wrong. You can show this
// info to the end user, or just create some sort of log.
// The logging function should NOT terminate the program, as this obviously can leave
// resources. It is the programmer's responsability to check each function return code
// to make sure it didn't fail.
// Error messages are limited to MAX_ERROR_MESSAGE_LEN
#define MAX_ERROR_MESSAGE_LEN 1024
// ---------------------------------------------------------------------------------------------------------
// This is our default log error
static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
// The current handler in actual environment
static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction;
// The default error logger does nothing.
static
void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
{
// fprintf(stderr, "[lcms]: %s\n", Text);
// fflush(stderr);
cmsUNUSED_PARAMETER(ContextID);
cmsUNUSED_PARAMETER(ErrorCode);
cmsUNUSED_PARAMETER(Text);
}
// Change log error
void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn)
{
if (Fn == NULL)
LogErrorHandler = DefaultLogErrorHandlerFunction;
else
LogErrorHandler = Fn;
}
// Log an error
// ErrorText is a text holding an english description of error.
void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...)
{
va_list args;
char Buffer[MAX_ERROR_MESSAGE_LEN];
va_start(args, ErrorText);
vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args);
va_end(args);
// Call handler
LogErrorHandler(ContextID, ErrorCode, Buffer);
}
// Utility function to print signatures
void _cmsTagSignature2String(char String[5], cmsTagSignature sig)
{
cmsUInt32Number be;
// Convert to big endian
be = _cmsAdjustEndianess32((cmsUInt32Number) sig);
// Move chars
memmove(String, &be, 4);
// Make sure of terminator
String[4] = 0;
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册