提交 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 @@
FILES_c = \
cmscam02.c \
cmscam97.c \
cmscgats.c \
cmscnvrt.c \
cmserr.c \
......@@ -35,13 +34,17 @@ FILES_c = \
cmsio0.c \
cmsio1.c \
cmslut.c \
cmsmatsh.c \
cmsmd5.c \
cmsmtrx.c \
cmsnamed.c \
cmsopt.c \
cmspack.c \
cmspcs.c \
cmsplugin.c \
cmsps2.c \
cmssamp.c \
cmssm.c \
cmstypes.c \
cmsvirt.c \
cmswtpnt.c \
cmsxform.c \
......
......@@ -25,7 +25,6 @@
FILES_c = \
cmscam02.c \
cmscam97.c \
cmscgats.c \
cmscnvrt.c \
cmserr.c \
......@@ -35,13 +34,17 @@ FILES_c = \
cmsio0.c \
cmsio1.c \
cmslut.c \
cmsmatsh.c \
cmsmd5.c \
cmsmtrx.c \
cmsnamed.c \
cmsopt.c \
cmspack.c \
cmspcs.c \
cmsplugin.c \
cmsps2.c \
cmssamp.c \
cmssm.c \
cmstypes.c \
cmsvirt.c \
cmswtpnt.c \
cmsxform.c \
......
......@@ -80,8 +80,8 @@ vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
vpath %.c $(SHARE_SRC)/native/sun/java2d
ifeq ($(PLATFORM), windows)
OTHER_LDLIBS = user32.lib version.lib $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
OTHER_CFLAGS += -DCMS_IS_WINDOWS_ -Dsqrtf=sqrt
OTHER_LDLIBS = $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \
-I$(SHARE_SRC)/native/sun/awt/debug
......
......@@ -100,12 +100,12 @@ public class CMSManager {
public long loadProfile(byte[] data) {
System.err.print(cName + ".loadProfile");
long profileID = tcmm.loadProfile(data);
System.err.println("(ID=" + profileID + ")");
System.err.printf("(ID=%x)\n", profileID);
return 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);
}
......@@ -123,8 +123,8 @@ public class CMSManager {
}
public int getTagSize(long profileID, int tagSignature) {
System.err.print(cName + ".getTagSize(ID=" + profileID +
", TagSig=" + tagSignature + ")");
System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
profileID, signatureToString(tagSignature));
int size = tcmm.getTagSize(profileID, tagSignature);
System.err.println("=" + size);
return size;
......@@ -132,8 +132,8 @@ public class CMSManager {
public void getTagData(long profileID, int tagSignature,
byte[] data) {
System.err.print(cName + ".getTagData(ID=" + profileID +
", TagSig=" + tagSignature + ")");
System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
profileID, signatureToString(tagSignature));
System.err.println(" requested " + data.length + " byte(s)");
tcmm.getTagData(profileID, tagSignature, data);
}
......@@ -158,5 +158,13 @@ public class CMSManager {
System.err.println(cName + ".createTransform(ColorTransform[])");
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 {
public static native long getProfileID(ICC_Profile profile);
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
......
......@@ -55,11 +55,17 @@ import sun.java2d.cmm.lcms.*;
public class LCMSTransform implements ColorTransform {
long ID;
private int inFormatter;
private int outFormatter;
ICC_Profile[] profiles;
long [] profileIDs;
int renderType;
int transformType;
private int numInComponents = -1;
private int numOutComponents = -1;
private Object disposerReferent = new Object();
/* the class initializer */
......@@ -80,6 +86,14 @@ public class LCMSTransform implements ColorTransform {
this.renderType = (renderType == ColorTransform.Any)?
ICC_Profile.icPerceptual : renderType;
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) {
......@@ -99,26 +113,51 @@ public class LCMSTransform implements ColorTransform {
j += curTrans.profiles.length;
}
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() {
return profiles[0].getNumComponents();
return numInComponents;
}
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) {
if (LCMSImageLayout.isSupported(src) &&
LCMSImageLayout.isSupported(dst))
{
synchronized(this) {
LCMS.colorConvert(this, new LCMSImageLayout(src),
new LCMSImageLayout(dst));
}
doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
return;
}
LCMSImageLayout srcIL, dstIL;
......@@ -204,9 +243,8 @@ public class LCMSTransform implements ColorTransform {
}
}
// color convert srcLine to dstLine
synchronized (this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
// convert dst scanline
pixel = null;
idx = 0;
......@@ -263,9 +301,8 @@ public class LCMSTransform implements ColorTransform {
}
}
// color convert srcLine to dstLine
synchronized(this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
// convert dst scanline
pixel = null;
idx = 0;
......@@ -377,9 +414,7 @@ public class LCMSTransform implements ColorTransform {
}
// color convert srcLine to dstLine
synchronized(this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
// store dst scanline
xd = dst.getMinX();
......@@ -470,9 +505,7 @@ public class LCMSTransform implements ColorTransform {
}
// color convert srcLine to dstLine
synchronized(this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
// store dst scanline
xd = dst.getMinX();
......@@ -513,9 +546,8 @@ public class LCMSTransform implements ColorTransform {
}
// color convert srcLine to dstLine
synchronized(this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
// store dst scanline
xd = dst.getMinX();
idx = 0;
......@@ -550,9 +582,7 @@ public class LCMSTransform implements ColorTransform {
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
synchronized(this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
return dst;
}
......@@ -572,9 +602,7 @@ public class LCMSTransform implements ColorTransform {
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
synchronized(this) {
LCMS.colorConvert(this, srcIL, dstIL);
}
doTransform(srcIL, dstIL);
return dst;
}
......
......@@ -27,9 +27,10 @@
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
// Little cms
// Copyright (C) 1998-2007 Marti Maria
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -48,69 +49,65 @@
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// 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.
#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 --------------------------------------------
typedef struct {
double XYZ[3];
double RGB[3];
double RGBc[3];
double RGBp[3];
double RGBpa[3];
double a, b, h, e, H, A, J, Q, s, t, C, M;
double abC[2];
double abs[2];
double abM[2];
cmsFloat64Number XYZ[3];
cmsFloat64Number RGB[3];
cmsFloat64Number RGBc[3];
cmsFloat64Number RGBp[3];
cmsFloat64Number RGBpa[3];
cmsFloat64Number a, b, h, e, H, A, J, Q, s, t, C, M;
cmsFloat64Number abC[2];
cmsFloat64Number abs[2];
cmsFloat64Number abM[2];
} CAM02COLOR, *LPCAM02COLOR;
} CAM02COLOR;
typedef struct {
CAM02COLOR adoptedWhite;
double LA, Yb;
double F, c, Nc;
int surround;
double n, Nbb, Ncb, z, FL, D;
cmsFloat64Number LA, Yb;
cmsFloat64Number F, c, Nc;
cmsUInt32Number surround;
cmsFloat64Number n, Nbb, Ncb, z, FL, D;
cmsContext ContextID;
} cmsCIECAM02, *LPcmsCIECAM02;
} cmsCIECAM02;
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
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
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
double computeFL(LPcmsCIECAM02 pMod)
cmsFloat64Number computeFL(cmsCIECAM02* pMod)
{
double k, FL;
cmsFloat64Number k, FL;
k = 1.0 / ((5.0 * pMod->LA) + 1.0);
FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 *
......@@ -121,9 +118,9 @@ double computeFL(LPcmsCIECAM02 pMod)
}
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)));
......@@ -142,9 +139,10 @@ CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
}
static
CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod)
CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
{
int i;
cmsUInt32Number i;
for (i = 0; i < 3; i++) {
clr.RGBc[i] = ((pMod -> adoptedWhite.XYZ[1] *
(pMod->D / pMod -> adoptedWhite.RGB[i])) +
......@@ -156,11 +154,9 @@ CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod)
static
CAM02COLOR CAT02toHPE (CAM02COLOR clr)
CAM02COLOR CAT02toHPE(CAM02COLOR clr)
{
double M[9];
cmsFloat64Number M[9];
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));
......@@ -180,10 +176,10 @@ CAM02COLOR CAT02toHPE (CAM02COLOR clr)
}
static
CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod)
CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
{
int i;
double temp;
cmsUInt32Number i;
cmsFloat64Number temp;
for (i = 0; i < 3; i++) {
if (clr.RGBp[i] < 0) {
......@@ -204,9 +200,9 @@ CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod)
}
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);
b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0;
......@@ -274,10 +270,10 @@ CAM02COLOR ComputeCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
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;
t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) *
......@@ -327,10 +323,10 @@ CAM02COLOR InverseCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
}
static
CAM02COLOR InverseNonlinearity(CAM02COLOR clr, LPcmsCIECAM02 pMod)
CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod)
{
int i;
double c1;
cmsUInt32Number i;
cmsFloat64Number c1;
for (i = 0; i < 3; i++) {
if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1;
......@@ -347,7 +343,7 @@ CAM02COLOR InverseNonlinearity(CAM02COLOR clr, LPcmsCIECAM02 pMod)
static
CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
{
double M[9];
cmsFloat64Number M[9];
M[0] = (( 0.7328 * 1.910197) + (0.4296 * 0.370950));
M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054));
......@@ -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[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]);
return (clr);
return clr;
}
static
CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod)
CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
{
int i;
cmsUInt32Number i;
for (i = 0; i < 3; i++) {
clr.RGB[i] = clr.RGBc[i] /
((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)
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);
return(clr);
return clr;
}
LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
cmsHANDLE CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC)
{
LPcmsCIECAM02 lpMod;
cmsCIECAM02* lpMod;
_cmsAssert(pVC != NULL);
if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) {
return (LCMSHANDLE) NULL;
if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) {
return NULL;
}
ZeroMemory(lpMod, sizeof(cmsCIECAM02));
lpMod ->ContextID = ContextID;
lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X;
lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y;
......@@ -414,36 +408,30 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
switch (lpMod -> surround) {
case AVG_SURROUND_4:
lpMod->F = 1.0; // Not included in CAM02
lpMod->c = 0.69;
lpMod->Nc = 1.0;
break;
case CUTSHEET_SURROUND:
lpMod->F = 0.8;
lpMod->c = 0.41;
lpMod->Nc = 0.8;
break;
case DARK_SURROUND:
lpMod -> F = 0.8;
lpMod -> c = 0.525;
lpMod -> Nc = 0.8;
break;
case DIM_SURROUND:
lpMod -> F = 0.9;
lpMod -> c = 0.59;
lpMod -> Nc = 0.95;
break;
default:
// Average surround
lpMod -> F = 1.0;
lpMod -> c = 0.69;
lpMod -> Nc = 1.0;
case CUTSHEET_SURROUND:
lpMod->F = 0.8;
lpMod->c = 0.41;
lpMod->Nc = 0.8;
break;
case DARK_SURROUND:
lpMod -> F = 0.8;
lpMod -> c = 0.525;
lpMod -> Nc = 0.8;
break;
case DIM_SURROUND:
lpMod -> F = 0.9;
lpMod -> c = 0.59;
lpMod -> Nc = 0.95;
break;
default:
// Average surround
lpMod -> F = 1.0;
lpMod -> c = 0.69;
lpMod -> Nc = 1.0;
}
lpMod -> n = compute_n(lpMod);
......@@ -451,10 +439,8 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
lpMod -> Nbb = computeNbb(lpMod);
lpMod -> FL = computeFL(lpMod);
if (lpMod -> D == D_CALCULATE ||
lpMod -> D == D_CALCULATE_DISCOUNT) {
lpMod -> D = computeD(lpMod);
if (lpMod -> D == D_CALCULATE) {
lpMod -> D = computeD(lpMod);
}
lpMod -> Ncb = lpMod -> Nbb;
......@@ -464,21 +450,26 @@ LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
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;
if (lpMod) _cmsFree(lpMod);
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
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;
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[1] = pIn ->Y;
......@@ -495,11 +486,14 @@ void LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh
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;
LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
clr.J = pIn -> J;
clr.C = pIn -> C;
......@@ -514,6 +508,5 @@ void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ
pOut ->X = clr.XYZ[0];
pOut ->Y = clr.XYZ[1];
pOut ->Z = clr.XYZ[2];
}
......@@ -27,9 +27,10 @@
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
// Little cms
// Copyright (C) 1998-2007 Marti Maria
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
......@@ -48,92 +49,399 @@
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// 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
// errors.
while (toupper(*us1) == toupper(*us2++))
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);
void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn);
if (fseek(f, 0, SEEK_END) != 0) {
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;
static cmsErrorHandlerFunction UserErrorHandler = (cmsErrorHandlerFunction) NULL;
// User may override this behaviour by using a memory plug-in, which basically replaces
// 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;
nDoAbort = nAction;
if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never allow over maximum
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);
va_end(args);
// The default calloc function. Allocates an array of num elements, each one of size bytes
// 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);
vfprintf(stderr, ErrorText, args);
fprintf(stderr, "\n");
va_end(args);
// Generic block duplication
static
void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size)
{
void* mem;
if (nDoAbort == LCMS_ERROR_ABORT) exit(1);
#else
{
char Buffer1[1024];
char Buffer2[256];
if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never dup over 512Mb
snprintf(Buffer1, 767, "Error #%x; ", ErrorCode);
vsnprintf(Buffer2, 255, ErrorText, args);
strcat(Buffer1, Buffer2);
MessageBox(NULL, Buffer1, "Little cms",
MB_OK|MB_ICONSTOP|MB_TASKMODAL);
va_end(args);
mem = _cmsMalloc(ContextID, size);
if (nDoAbort == LCMS_ERROR_ABORT) {
if (mem != NULL && Org != NULL)
memmove(mem, Org, size);
#ifdef __BORLANDC__
_cexit();
#endif
return mem;
}
// 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");
}
}
#endif
// Plug-in replacement entry
cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
{
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.
先完成此消息的编辑!
想要评论请 注册