# HG changeset patch # User prr # Date 1237911242 25200 # Node ID 404cbe399601fd2313926a21d23a45876335ffc4 # Parent ea28f24e1708cde0538e93e78ee8a8403c3eedfd 6821031: Upgrade OpenJDK's LittleCMS version to 1.18 Reviewed-by: bae, igor diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c Tue Mar 24 09:14:02 2009 -0700 @@ -374,6 +374,10 @@ return; } +// Modify data for a tag in a profile +LCMSBOOL LCMSEXPORT _cmsModifyTagData(cmsHPROFILE hProfile, + icTagSignature sig, void *data, size_t size); + /* * Class: sun_java2d_cmm_lcms_LCMS * Method: setTagData @@ -561,10 +565,10 @@ PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J"); } -BOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig, +LCMSBOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig, void *data, size_t size) { - BOOL isNew; + LCMSBOOL isNew; int i, idx, delta, count; LPBYTE padChars[3] = {0, 0, 0}; LPBYTE beforeBuf, afterBuf, ptr; diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam02.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -51,7 +51,7 @@ -// CIECAM 02 appearance model +// CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging. #include "lcms.h" @@ -196,6 +196,10 @@ clr.RGBpa[i] = (400.0 * temp) / (temp + 27.13) + 0.1; } } + + clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] + + (clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb; + return clr; } @@ -249,9 +253,6 @@ clr.H = 300 + ((100*((clr.h - 237.53)/1.2)) / temp); } - clr.A = (((2.0 * clr.RGBpa[0]) + clr.RGBpa[1] + - (clr.RGBpa[2] / 20.0)) - 0.305) * pMod->Nbb; - clr.J = 100.0 * pow((clr.A / pMod->adoptedWhite.A), (pMod->c * pMod->z)); @@ -395,7 +396,7 @@ LPcmsCIECAM02 lpMod; - if((lpMod = (LPcmsCIECAM02) malloc(sizeof(cmsCIECAM02))) == NULL) { + if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) { return (LCMSHANDLE) NULL; } @@ -449,14 +450,19 @@ lpMod -> z = compute_z(lpMod); lpMod -> Nbb = computeNbb(lpMod); lpMod -> FL = computeFL(lpMod); + + if (lpMod -> D == D_CALCULATE || + lpMod -> D == D_CALCULATE_DISCOUNT) { + lpMod -> D = computeD(lpMod); + } + lpMod -> Ncb = lpMod -> Nbb; lpMod -> adoptedWhite = XYZtoCAT02(lpMod -> adoptedWhite); lpMod -> adoptedWhite = ChromaticAdaptation(lpMod -> adoptedWhite, lpMod); lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite); lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod); - lpMod -> adoptedWhite = ComputeCorrelates(lpMod -> adoptedWhite, lpMod); return (LCMSHANDLE) lpMod; @@ -465,7 +471,7 @@ void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel) { LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel; - if (lpMod) free(lpMod); + if (lpMod) _cmsFree(lpMod); } @@ -510,3 +516,4 @@ pOut ->Z = clr.XYZ[2]; } + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmscam97.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam97.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscam97.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -174,7 +174,7 @@ LCMSAPI void LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel) { LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel; - if (lpMod) free(lpMod); + if (lpMod) _cmsFree(lpMod); } // Partial discounting for adaptation degree computation @@ -331,7 +331,7 @@ LPcmsCIECAM97s lpMod; VEC3 tmp; - if((lpMod = (LPcmsCIECAM97s) malloc(sizeof(cmsCIECAM97s))) == NULL) { + if((lpMod = (LPcmsCIECAM97s) _cmsMalloc(sizeof(cmsCIECAM97s))) == NULL) { return (LCMSHANDLE) NULL; } @@ -449,7 +449,7 @@ // RGB_subw = [MlamRigg][WP/YWp] #ifdef USE_CIECAM97s2 - MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, (LPVEC3) &lpMod -> WP); + MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &lpMod -> WP); #else VEC3divK(&tmp, (LPVEC3) &lpMod -> WP, lpMod->WP.Y); MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &tmp); diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscgats.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -65,22 +65,25 @@ // Persistence LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName); LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len); -LCMSAPI BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName); // Properties LCMSAPI const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type); - -LCMSAPI BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment); - -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type); + +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment); + +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer); LCMSAPI const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp); LCMSAPI double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp); -LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames); +LCMSAPI const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp); +LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, const char ***PropertyNames); +LCMSAPI int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames); // Datasets @@ -89,10 +92,10 @@ LCMSAPI const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col); LCMSAPI double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int col, int row); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val); LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample); @@ -100,15 +103,15 @@ LCMSAPI double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample, const char *Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, const char* cSample, double Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample); LCMSAPI int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames); LCMSAPI void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter); @@ -126,7 +129,7 @@ // #define STRICT_CGATS 1 #define MAXID 128 // Max lenght of identifier -#define MAXSTR 255 // Max lenght of string +#define MAXSTR 1024 // Max lenght of string #define MAXTABLES 255 // Max Number of tables in a single stream #define MAXINCLUDE 20 // Max number of nested includes @@ -137,6 +140,9 @@ #ifndef NON_WINDOWS #include +#define DIR_CHAR '\\' +#else +#define DIR_CHAR '/' #endif // Symbols @@ -160,6 +166,7 @@ SEND_DATA, SEND_DATA_FORMAT, SKEYWORD, + SDATA_FORMAT_ID, SINCLUDE } SYMBOL; @@ -171,7 +178,8 @@ WRITE_UNCOOKED, WRITE_STRINGIFY, WRITE_HEXADECIMAL, - WRITE_BINARY + WRITE_BINARY, + WRITE_PAIR } WRITEMODE; @@ -181,6 +189,8 @@ struct _KeyVal* Next; char* Keyword; // Name of variable + struct _KeyVal* NextSubkey; // If key is a dictionary, points to the next item + char* Subkey; // If key is a dictionary, points to the subkey name char* Value; // Points to value WRITEMODE WriteAs; // How to write the value @@ -220,7 +230,12 @@ } TABLE, *LPTABLE; - +// File stream being parsed + +typedef struct _FileContext { + char FileName[MAX_PATH]; // File name if being readed from file + FILE* Stream; // File stream or NULL if holded in memory + } FILECTX, *LPFILECTX; // This struct hold all information about an openened // IT8 handler. Only one dataset is allowed. @@ -257,9 +272,9 @@ char* Source; // Points to loc. being parsed int lineno; // line counter for error reporting - char FileName[MAX_PATH]; // File name if being readed from file - FILE* Stream[MAXINCLUDE]; // File stream or NULL if holded in memory + LPFILECTX FileStack[MAXINCLUDE]; // Stack of files being parsed int IncludeSP; // Include Stack Pointer + char* MemoryBlock; // The stream if holded in memory char DoubleFormatter[MAXID]; // Printf-like 'double' formatter @@ -270,14 +285,14 @@ typedef struct { - FILE* stream; // For save-to-file behaviour - - LPBYTE Base; - LPBYTE Ptr; // For save-to-mem behaviour - size_t Used; - size_t Max; - - } SAVESTREAM, FAR* LPSAVESTREAM; + FILE* stream; // For save-to-file behaviour + + LPBYTE Base; + LPBYTE Ptr; // For save-to-mem behaviour + size_t Used; + size_t Max; + + } SAVESTREAM, FAR* LPSAVESTREAM; // ------------------------------------------------------ IT8 parsing routines @@ -298,59 +313,104 @@ {".INCLUDE", SINCLUDE}, {"BEGIN_DATA", SBEGIN_DATA }, {"BEGIN_DATA_FORMAT", SBEGIN_DATA_FORMAT }, + {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID}, {"END_DATA", SEND_DATA}, {"END_DATA_FORMAT", SEND_DATA_FORMAT}, {"KEYWORD", SKEYWORD} - }; #define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD)) // Predefined properties -static const char* PredefinedProperties[] = { - - "NUMBER_OF_FIELDS", // Required - NUMBER OF FIELDS - "NUMBER_OF_SETS", // Required - NUMBER OF SETS - "ORIGINATOR", // Required - Identifies the specific system, organization or individual that created the data file. - "FILE_DESCRIPTOR", // Required - Describes the purpose or contents of the data file. - "CREATED", // Required - Indicates date of creation of the data file. - "DESCRIPTOR", // Required - Describes the purpose or contents of the data file. - "DIFFUSE_GEOMETRY", // The diffuse geometry used. Allowed values are "sphere" or "opal". - "MANUFACTURER", - "MANUFACTURE", // Some broken Fuji targets does store this value - "PROD_DATE", // Identifies year and month of production of the target in the form yyyy:mm. - "SERIAL", // Uniquely identifies individual physical target. - - "MATERIAL", // Identifies the material on which the target was produced using a code +// A property +typedef struct { + const char *id; + WRITEMODE as; + } PROPERTY; + +static PROPERTY PredefinedProperties[] = { + + {"NUMBER_OF_FIELDS", WRITE_UNCOOKED}, // Required - NUMBER OF FIELDS + {"NUMBER_OF_SETS", WRITE_UNCOOKED}, // Required - NUMBER OF SETS + {"ORIGINATOR", WRITE_STRINGIFY}, // Required - Identifies the specific system, organization or individual that created the data file. + {"FILE_DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file. + {"CREATED", WRITE_STRINGIFY}, // Required - Indicates date of creation of the data file. + {"DESCRIPTOR", WRITE_STRINGIFY}, // Required - Describes the purpose or contents of the data file. + {"DIFFUSE_GEOMETRY", WRITE_STRINGIFY}, // The diffuse geometry used. Allowed values are "sphere" or "opal". + {"MANUFACTURER", WRITE_STRINGIFY}, + {"MANUFACTURE", WRITE_STRINGIFY}, // Some broken Fuji targets does store this value + {"PROD_DATE", WRITE_STRINGIFY}, // Identifies year and month of production of the target in the form yyyy:mm. + {"SERIAL", WRITE_STRINGIFY}, // Uniquely identifies individual physical target. + + {"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code // uniquely identifying th e material. This is intend ed to be used for IT8.7 // physical targets only (i.e . IT8.7/1 a nd IT8.7/2). - "INSTRUMENTATION", // Used to report the specific instrumentation used (manufacturer and + {"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and // model number) to generate the data reported. This data will often // provide more information about the particular data collected than an // extensive list of specific details. This is particularly important for // spectral data or data derived from spectrophotometry. - "MEASUREMENT_SOURCE", // Illumination used for spectral measurements. This data helps provide + {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide // a guide to the potential for issues of paper fluorescence, etc. - "PRINT_CONDITIONS", // Used to define the characteristics of the printed sheet being reported. + {"PRINT_CONDITIONS", WRITE_STRINGIFY}, // Used to define the characteristics of the printed sheet being reported. // Where standard conditions have been defined (e.g., SWOP at nominal) // named conditions may suffice. Otherwise, detailed information is // needed. - "SAMPLE_BACKING", // Identifies the backing material used behind the sample during - // measurement. Allowed values are “black”, “white”, or "na". - - "CHISQ_DOF" // Degrees of freedom associated with the Chi squared statistic + {"SAMPLE_BACKING", WRITE_STRINGIFY}, // Identifies the backing material used behind the sample during + // measurement. Allowed values are “black”, “white”, or {"na". + + {"CHISQ_DOF", WRITE_STRINGIFY}, // Degrees of freedom associated with the Chi squared statistic + +// new in recent specs: + {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated + // along with details of the geometry and the aperture size and shape. For example, + // for transmission measurements it is important to identify 0/diffuse, diffuse/0, + // opal or integrating sphere, etc. For reflection it is important to identify 0/45, + // 45/0, sphere (specular included or excluded), etc. + + {"FILTER", WRITE_STRINGIFY}, // Identifies the use of physical filter(s) during measurement. Typically used to + // denote the use of filters such as none, D65, Red, Green or Blue. + + {"POLARIZATION", WRITE_STRINGIFY}, // Identifies the use of a physical polarization filter during measurement. Allowed + // values are {"yes”, “white”, “none” or “na”. + + {"WEIGHTING_FUNCTION", WRITE_PAIR}, // Indicates such functions as: the CIE standard observer functions used in the + // calculation of various data parameters (2 degree and 10 degree), CIE standard + // illuminant functions used in the calculation of various data parameters (e.g., D50, + // D65, etc.), density status response, etc. If used there shall be at least one + // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute + // in the set shall be {"name" and shall identify the particular parameter used. + // The second shall be {"value" and shall provide the value associated with that name. + // For ASCII data, a string containing the Name and Value attribute pairs shall follow + // the weighting function keyword. A semi-colon separates attribute pairs from each + // other and within the attribute the name and value are separated by a comma. + + {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name + // of the calculation, parameter is the name of the parameter used in the calculation + // and value is the value of the parameter. + + {"TARGET_TYPE", WRITE_STRINGIFY}, // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc. + + {"COLORANT", WRITE_STRINGIFY}, // Identifies the colorant(s) used in creating the target. + + {"TABLE_DESCRIPTOR", WRITE_STRINGIFY}, // Describes the purpose or contents of a data table. + + {"TABLE_NAME", WRITE_STRINGIFY} // Provides a short name for a data table. }; -#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(char *)) +#define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY)) // Predefined sample types on dataset static const char* PredefinedSampleID[] = { + "SAMPLE_ID", // Identifies sample that data represents + "STRING", // Identifies label, or other non-machine readable value. + // Value must begin and end with a " symbol "CMYK_C", // Cyan component of CMYK data expressed as a percentage "CMYK_M", // Magenta component of CMYK data expressed as a percentage @@ -378,7 +438,7 @@ "LAB_B", // b* component of Lab data "LAB_C", // C*ab component of Lab data "LAB_H", // hab component of Lab data - "LAB_DE" // CIE dE + "LAB_DE", // CIE dE "LAB_DE_94", // CIE dE using CIE 94 "LAB_DE_CMC", // dE using CMC "LAB_DE_2000", // CIE dE using CIE DE 2000 @@ -388,7 +448,7 @@ "STDEV_Y", // Standard deviation of Y (tristimulus data) "STDEV_Z", // Standard deviation of Z (tristimulus data) "STDEV_L", // Standard deviation of L* - "STDEV_A" // Standard deviation of a* + "STDEV_A", // Standard deviation of a* "STDEV_B", // Standard deviation of b* "STDEV_DE", // Standard deviation of CIE dE "CHI_SQD_PAR"}; // The average of the standard deviations of L*, a* and b*. It is @@ -397,57 +457,120 @@ #define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *)) +//Forward declaration of some internal functions +static +void* AllocChunk(LPIT8 it8, size_t size); + // Checks if c is a separator static -BOOL isseparator(int c) +LCMSBOOL isseparator(int c) { return (c == ' ') || (c == '\t') || (c == '\r'); } // Checks whatever if c is a valid identifier char - static -BOOL ismiddle(int c) +LCMSBOOL ismiddle(int c) { return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127)); } // Checks whatsever if c is a valid identifier middle char. static -BOOL isidchar(int c) +LCMSBOOL isidchar(int c) { return isalnum(c) || ismiddle(c); } // Checks whatsever if c is a valid identifier first char. static -BOOL isfirstidchar(int c) +LCMSBOOL isfirstidchar(int c) { return !isdigit(c) && ismiddle(c); } +// checks whether the supplied path looks like an absolute path +// NOTE: this function doesn't checks if the path exists or even if it's legal +static +LCMSBOOL isabsolutepath(const char *path) +{ + if(path == NULL) + return FALSE; + + if(path[0] == DIR_CHAR) + return TRUE; + +#ifndef NON_WINDOWS + if(isalpha(path[0]) && path[1] == ':') + return TRUE; +#endif + return FALSE; +} + +// Makes a file path based on a given reference path +// NOTE: buffer is assumed to point to at least MAX_PATH bytes +// NOTE: both relPath and basePath are assumed to be no more than MAX_PATH characters long (including the null terminator!) +// NOTE: this function doesn't check if the path exists or even if it's legal +static +LCMSBOOL _cmsMakePath(const char *relPath, const char *basePath, char *buffer) +{ + if (!isabsolutepath(relPath)) { + + char *tail; + + strncpy(buffer, basePath, MAX_PATH-1); + tail = strrchr(buffer, DIR_CHAR); + if (tail != NULL) { + + size_t len = tail - buffer; + strncpy(tail + 1, relPath, MAX_PATH - len -1); + // TODO: if combined path is longer than MAX_PATH, this should return FALSE! + return TRUE; + } + } + strncpy(buffer, relPath, MAX_PATH - 1); + buffer[MAX_PATH-1] = 0; + return TRUE; +} + + +// Make sure no exploit is being even tried static -BOOL SynError(LPIT8 it8, const char *Txt, ...) +const char* NoMeta(const char* str) +{ + if (strchr(str, '%') != NULL) + return "**** CORRUPTED FORMAT STRING ***"; + + return str; +} + + +// Syntax error +static +LCMSBOOL SynError(LPIT8 it8, const char *Txt, ...) { char Buffer[256], ErrMsg[1024]; va_list args; va_start(args, Txt); - vsprintf(Buffer, Txt, args); + vsnprintf(Buffer, 255, Txt, args); + Buffer[255] = 0; va_end(args); - sprintf(ErrMsg, "%s: Line %d, %s", it8->FileName, it8->lineno, Buffer); + snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer); + ErrMsg[1023] = 0; it8->sy = SSYNERROR; - cmsSignalError(LCMS_ERRC_ABORTED, ErrMsg); + cmsSignalError(LCMS_ERRC_ABORTED, "%s", ErrMsg); return FALSE; } +// Check if current symbol is same as specified. issue an error else. static -BOOL Check(LPIT8 it8, SYMBOL sy, const char* Err) +LCMSBOOL Check(LPIT8 it8, SYMBOL sy, const char* Err) { if (it8 -> sy != sy) - return SynError(it8, Err); + return SynError(it8, NoMeta(Err)); return TRUE; } @@ -457,15 +580,15 @@ static void NextCh(LPIT8 it8) { - if (it8 -> Stream[it8 ->IncludeSP]) { - - it8 ->ch = fgetc(it8 ->Stream[it8 ->IncludeSP]); - - if (feof(it8 -> Stream[it8 ->IncludeSP])) { + if (it8 -> FileStack[it8 ->IncludeSP]->Stream) { + + it8 ->ch = fgetc(it8 ->FileStack[it8 ->IncludeSP]->Stream); + + if (feof(it8 -> FileStack[it8 ->IncludeSP]->Stream)) { if (it8 ->IncludeSP > 0) { - fclose(it8 ->Stream[it8->IncludeSP--]); + fclose(it8 ->FileStack[it8->IncludeSP--]->Stream); it8 -> ch = ' '; // Whitespace to be ignored } else @@ -476,7 +599,6 @@ } else { - it8->ch = *it8->Source; if (it8->ch) it8->Source++; } @@ -799,18 +921,39 @@ if (it8 -> sy == SINCLUDE) { - FILE* IncludeFile; + LPFILECTX FileNest; + + if(it8 -> IncludeSP >= (MAXINCLUDE-1)) + { + SynError(it8, "Too many recursion levels"); + return; + } InSymbol(it8); if (!Check(it8, SSTRING, "Filename expected")) return; - IncludeFile = fopen(it8 -> str, "rt"); - if (IncludeFile == NULL) { - - SynError(it8, "File %s not found", it8 ->str); + + FileNest = it8 -> FileStack[it8 -> IncludeSP + 1]; + if(FileNest == NULL) + { + FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX)); + //if(FileNest == NULL) + // TODO: how to manage out-of-memory conditions? + } + + if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE) + { + SynError(it8, "File path too long"); + return; + } + + FileNest->Stream = fopen(FileNest->FileName, "rt"); + if (FileNest->Stream == NULL) { + + SynError(it8, "File %s not found", FileNest->FileName); return; } - - it8 -> Stream[++it8 -> IncludeSP] = IncludeFile; + it8->IncludeSP++; + it8 ->ch = ' '; InSymbol(it8); } @@ -819,7 +962,7 @@ // Checks end of line separator static -BOOL CheckEOLN(LPIT8 it8) +LCMSBOOL CheckEOLN(LPIT8 it8) { if (!Check(it8, SEOLN, "Expected separator")) return FALSE; while (it8 -> sy == SEOLN) @@ -850,21 +993,26 @@ // Returns a string holding current value static -BOOL GetVal(LPIT8 it8, char* Buffer, const char* ErrorTitle) +LCMSBOOL GetVal(LPIT8 it8, char* Buffer, size_t max, const char* ErrorTitle) { switch (it8->sy) { - case SIDENT: strncpy(Buffer, it8->id, MAXID-1); break; - case SINUM: sprintf(Buffer, "%d", it8 -> inum); break; - case SDNUM: sprintf(Buffer, it8->DoubleFormatter, it8 -> dnum); break; - case SSTRING: strncpy(Buffer, it8->str, MAXSTR-1); break; + case SIDENT: strncpy(Buffer, it8->id, max); + Buffer[max-1]=0; + break; + case SINUM: snprintf(Buffer, max, "%d", it8 -> inum); break; + case SDNUM: snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break; + case SSTRING: strncpy(Buffer, it8->str, max); + Buffer[max-1] = 0; + break; default: - return SynError(it8, ErrorTitle); + return SynError(it8, "%s", ErrorTitle); } - return TRUE; + Buffer[max] = 0; + return TRUE; } // ---------------------------------------------------------- Table @@ -872,7 +1020,13 @@ static LPTABLE GetTable(LPIT8 it8) { - return it8 ->Tab + it8 ->nTable; + if ((it8 -> nTable >= it8 ->TablesCount) || (it8 -> nTable < 0)) { + + SynError(it8, "Table %d out of sequence", it8 -> nTable); + return it8 -> Tab; + } + + return it8 ->Tab + it8 ->nTable; } // ---------------------------------------------------------- Memory management @@ -896,15 +1050,15 @@ for (p = it8->MemorySink; p != NULL; p = n) { n = p->Next; - if (p->Ptr) free(p->Ptr); - free(p); + if (p->Ptr) _cmsFree(p->Ptr); + _cmsFree(p); } } if (it8->MemoryBlock) - free(it8->MemoryBlock); - - free(it8); + _cmsFree(it8->MemoryBlock); + + _cmsFree(it8); } @@ -913,16 +1067,16 @@ void* AllocBigBlock(LPIT8 it8, size_t size) { LPOWNEDMEM ptr1; - void* ptr = malloc(size); + void* ptr = _cmsMalloc(size); if (ptr) { ZeroMemory(ptr, size); - ptr1 = (LPOWNEDMEM) malloc(sizeof(OWNEDMEM)); + ptr1 = (LPOWNEDMEM) _cmsMalloc(sizeof(OWNEDMEM)); if (ptr1 == NULL) { - free(ptr); + _cmsFree(ptr); return NULL; } @@ -986,8 +1140,9 @@ // Searches through linked list static -BOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, LPKEYVALUE* LastPtr) +LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, const char* Subkey, LPKEYVALUE* LastPtr) { + if (LastPtr) *LastPtr = p; for (; p != NULL; p = p->Next) { @@ -996,8 +1151,22 @@ if (*Key != '#') { // Comments are ignored if (stricmp(Key, p->Keyword) == 0) - return TRUE; + break; + } } + + if (p == NULL) + return FALSE; + + if (Subkey == 0) + return TRUE; + + for (; p != NULL; p = p->NextSubkey) { + + if (LastPtr) *LastPtr = p; + + if (stricmp(Subkey, p->Subkey) == 0) + return TRUE; } return FALSE; @@ -1007,35 +1176,55 @@ // Add a property into a linked list static -BOOL AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char* xValue, WRITEMODE WriteAs) +LPKEYVALUE AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs) { LPKEYVALUE p; - LPKEYVALUE last; - // Check if property is already in list (this is an error) - if (IsAvailableOnList(*Head, Key, &last)) { - - // This may work for editing properties - - last->Value = AllocString(it8, xValue); - last->WriteAs = WriteAs; - return TRUE; - - // return SynError(it8, "duplicate key <%s>", Key); + if (IsAvailableOnList(*Head, Key, Subkey, &p)) { + + // This may work for editing properties + + // return SynError(it8, "duplicate key <%s>", Key); } - - // Allocate the container + else { + LPKEYVALUE last = p; + + // Allocate the container p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE)); if (p == NULL) { - return SynError(it8, "AddToList: out of memory"); + SynError(it8, "AddToList: out of memory"); + return NULL; } // Store name and value p->Keyword = AllocString(it8, Key); - + p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey); + + // Keep the container in our list + if (*Head == NULL) + *Head = p; + else + { + if(Subkey != 0 && last != 0) { + last->NextSubkey = p; + + // If Subkey is not null, then last is the last property with the same key, + // but not necessarily is the last property in the list, so we need to move + // to the actual list end + while(last->Next != 0) + last = last->Next; + } + last->Next = p; + } + + p->Next = NULL; + p->NextSubkey = NULL; + } + + p->WriteAs = WriteAs; if (xValue != NULL) { p->Value = AllocString(it8, xValue); @@ -1044,29 +1233,20 @@ p->Value = NULL; } - p->Next = NULL; - p->WriteAs = WriteAs; - - // Keep the container in our list - if (*Head == NULL) - *Head = p; - else - last->Next = p; - - return TRUE; + return p; } static -BOOL AddAvailableProperty(LPIT8 it8, const char* Key) +LPKEYVALUE AddAvailableProperty(LPIT8 it8, const char* Key, WRITEMODE as) { - return AddToList(it8, &it8->ValidKeywords, Key, NULL, WRITE_UNCOOKED); + return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as); } static -BOOL AddAvailableSampleID(LPIT8 it8, const char* Key) +LPKEYVALUE AddAvailableSampleID(LPIT8 it8, const char* Key) { - return AddToList(it8, &it8->ValidSampleID, Key, NULL, WRITE_UNCOOKED); + return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED); } @@ -1122,8 +1302,6 @@ AllocTable(it8); it8->MemoryBlock = NULL; - it8->Stream[0] = NULL; - it8->IncludeSP = 0; it8->MemorySink = NULL; it8 ->nTable = 0; @@ -1141,6 +1319,8 @@ it8 -> inum = 0; it8 -> dnum = 0.0; + it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX)); + it8->IncludeSP = 0; it8 -> lineno = 1; strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT); @@ -1149,7 +1329,7 @@ // Initialize predefined properties & data for (i=0; i < NUMPREDEFINEDPROPS; i++) - AddAvailableProperty(it8, PredefinedProperties[i]); + AddAvailableProperty(it8, PredefinedProperties[i].id, PredefinedProperties[i].as); for (i=0; i < NUMPREDEFINEDSAMPLEID; i++) AddAvailableSampleID(it8, PredefinedSampleID[i]); @@ -1167,65 +1347,72 @@ } -BOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type) +LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type) { LPIT8 it8 = (LPIT8) hIT8; strncpy(it8 ->SheetType, Type, MAXSTR-1); + it8 ->SheetType[MAXSTR-1] = 0; return TRUE; } -BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val) +LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val) { LPIT8 it8 = (LPIT8) hIT8; if (!Val) return FALSE; if (!*Val) return FALSE; - return AddToList(it8, &GetTable(it8)->HeaderList, "# ", Val, WRITE_UNCOOKED); + return AddToList(it8, &GetTable(it8)->HeaderList, "# ", NULL, Val, WRITE_UNCOOKED) != NULL; } // Sets a property -BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val) +LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val) { LPIT8 it8 = (LPIT8) hIT8; if (!Val) return FALSE; if (!*Val) return FALSE; - return AddToList(it8, &GetTable(it8)->HeaderList, Key, Val, WRITE_STRINGIFY); + return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Val, WRITE_STRINGIFY) != NULL; } -BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val) +LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val) { LPIT8 it8 = (LPIT8) hIT8; char Buffer[1024]; sprintf(Buffer, it8->DoubleFormatter, Val); - return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_UNCOOKED); + return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; } -BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val) +LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val) { LPIT8 it8 = (LPIT8) hIT8; char Buffer[1024]; sprintf(Buffer, "%d", Val); - return AddToList(it8, &GetTable(it8)->HeaderList, cProp, Buffer, WRITE_HEXADECIMAL); + return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; } -BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer) +LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer) { LPIT8 it8 = (LPIT8) hIT8; - return AddToList(it8, &GetTable(it8)->HeaderList, Key, Buffer, WRITE_UNCOOKED); + return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL; } +LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer) +{ + LPIT8 it8 = (LPIT8) hIT8; + + return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL; +} // Gets a property const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key) @@ -1233,7 +1420,7 @@ LPIT8 it8 = (LPIT8) hIT8; LPKEYVALUE p; - if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, &p)) + if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p)) { return p -> Value; } @@ -1249,6 +1436,18 @@ else return 0.0; } +const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char *SubKey) +{ + LPIT8 it8 = (LPIT8) hIT8; + LPKEYVALUE p; + + if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) + { + return p -> Value; + } + return NULL; +} + // ----------------------------------------------------------------- Datasets @@ -1287,10 +1486,17 @@ } static -BOOL SetDataFormat(LPIT8 it8, int n, const char *label) +LCMSBOOL SetDataFormat(LPIT8 it8, int n, const char *label) { LPTABLE t = GetTable(it8); +#ifdef STRICT_CGATS + if (!IsAvailableOnList(it8-> ValidSampleID, label, NULL, NULL)) { + SynError(it8, "Invalid data format '%s'.", label); + return FALSE; + } +#endif + if (!t->DataFormat) AllocateDataFormat(it8); @@ -1308,7 +1514,7 @@ } -BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample) +LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample) { LPIT8 it8 = (LPIT8) h; return SetDataFormat(it8, n, Sample); @@ -1348,7 +1554,7 @@ } static -BOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val) +LCMSBOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val) { LPTABLE t = GetTable(it8); @@ -1383,42 +1589,43 @@ void WriteStr(LPSAVESTREAM f, const char *str) { - size_t len; - - if (str == NULL) - str = " "; - - // Lenghth to write - len = strlen(str); + size_t len; + + if (str == NULL) + str = " "; + + // Lenghth to write + len = strlen(str); f ->Used += len; - if (f ->stream) { // Should I write it to a file? - - fwrite(str, 1, len, f->stream); + if (f ->stream) { // Should I write it to a file? + + fwrite(str, 1, len, f->stream); + + } + else { // Or to a memory block? + + + if (f ->Base) { // Am I just counting the bytes? + + if (f ->Used > f ->Max) { + + cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser"); + return; + } + + CopyMemory(f ->Ptr, str, len); + f->Ptr += len; } - else { // Or to a memory block? - - - if (f ->Base) { // Am I just counting the bytes? - - if (f ->Used > f ->Max) { - - cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser"); - return; - } - - CopyMemory(f ->Ptr, str, len); - f->Ptr += len; - - } - - } + + } } -// +// Write formatted + static void Writef(LPSAVESTREAM f, const char* frm, ...) { @@ -1426,7 +1633,8 @@ va_list args; va_start(args, frm); - vsprintf(Buffer, frm, args); + vsnprintf(Buffer, 4095, frm, args); + Buffer[4095] = 0; WriteStr(f, Buffer); va_end(args); @@ -1450,7 +1658,7 @@ for (Pt = p ->Value; *Pt; Pt++) { - Writef(fp, "%c", *Pt); + Writef(fp, "%c", *Pt); if (*Pt == '\n') { WriteStr(fp, "# "); @@ -1462,7 +1670,7 @@ } - if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL)) { + if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) { #ifdef STRICT_CGATS WriteStr(fp, "KEYWORD\t\""); @@ -1470,7 +1678,7 @@ WriteStr(fp, "\"\n"); #endif - AddAvailableProperty(it8, p->Keyword); + AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED); } @@ -1495,6 +1703,10 @@ Writef(fp, "\t0x%B", atoi(p ->Value)); break; + case WRITE_PAIR: + Writef(fp, "\t\"%s,%s\"", p->Subkey, p->Value); + break; + default: SynError(it8, "Unknown write mode %d", p ->WriteAs); return; } @@ -1573,13 +1785,13 @@ // Saves whole file -BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName) +LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName) { SAVESTREAM sd; int i; LPIT8 it8 = (LPIT8) hIT8; - ZeroMemory(&sd, sizeof(SAVESTREAM)); + ZeroMemory(&sd, sizeof(SAVESTREAM)); sd.stream = fopen(cFileName, "wt"); if (!sd.stream) return FALSE; @@ -1594,31 +1806,31 @@ WriteData(&sd, it8); } - fclose(sd.stream); + fclose(sd.stream); return TRUE; } // Saves to memory -BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded) +LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded) { SAVESTREAM sd; int i; LPIT8 it8 = (LPIT8) hIT8; - ZeroMemory(&sd, sizeof(SAVESTREAM)); + ZeroMemory(&sd, sizeof(SAVESTREAM)); sd.stream = NULL; - sd.Base = (LPBYTE) MemPtr; - sd.Ptr = sd.Base; - - sd.Used = 0; - - if (sd.Base) - sd.Max = *BytesNeeded; // Write to memory? - else - sd.Max = 0; // Just counting the needed bytes + sd.Base = (LPBYTE) MemPtr; + sd.Ptr = sd.Base; + + sd.Used = 0; + + if (sd.Base) + sd.Max = *BytesNeeded; // Write to memory? + else + sd.Max = 0; // Just counting the needed bytes WriteStr(&sd, it8->SheetType); WriteStr(&sd, "\n"); @@ -1630,12 +1842,12 @@ WriteData(&sd, it8); } - sd.Used++; // The \0 at the very end - - if (sd.Base) - sd.Ptr = 0; - - *BytesNeeded = sd.Used; + sd.Used++; // The \0 at the very end + + if (sd.Base) + sd.Ptr = 0; + + *BytesNeeded = sd.Used; return TRUE; } @@ -1644,7 +1856,7 @@ // -------------------------------------------------------------- Higer level parsing static -BOOL DataFormatSection(LPIT8 it8) +LCMSBOOL DataFormatSection(LPIT8 it8) { int iField = 0; LPTABLE t = GetTable(it8); @@ -1685,16 +1897,19 @@ static -BOOL DataSection (LPIT8 it8) +LCMSBOOL DataSection (LPIT8 it8) { int iField = 0; int iSet = 0; - char Buffer[256]; + char Buffer[MAXSTR]; LPTABLE t = GetTable(it8); InSymbol(it8); // Eats "BEGIN_DATA" CheckEOLN(it8); + if (!t->Data) + AllocateDataSet(it8); + while (it8->sy != SEND_DATA && it8->sy != SEOF) { if (iField >= t -> nSamples) { @@ -1705,7 +1920,7 @@ if (it8->sy != SEND_DATA && it8->sy != SEOF) { - if (!GetVal(it8, Buffer, "Sample data expected")) + if (!GetVal(it8, Buffer, 255, "Sample data expected")) return FALSE; if (!SetData(it8, iSet, iField, Buffer)) @@ -1734,10 +1949,11 @@ static -BOOL HeaderSection(LPIT8 it8) +LCMSBOOL HeaderSection(LPIT8 it8) { char VarName[MAXID]; char Buffer[MAXSTR]; + LPKEYVALUE Key; while (it8->sy != SEOF && it8->sy != SSYNERROR && @@ -1749,30 +1965,79 @@ case SKEYWORD: InSymbol(it8); - if (!GetVal(it8, Buffer, "Keyword expected")) return FALSE; - if (!AddAvailableProperty(it8, Buffer)) return FALSE; + if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE; + if (!AddAvailableProperty(it8, Buffer, WRITE_UNCOOKED)) return FALSE; + InSymbol(it8); + break; + + + case SDATA_FORMAT_ID: + InSymbol(it8); + if (!GetVal(it8, Buffer, MAXSTR-1, "Keyword expected")) return FALSE; + if (!AddAvailableSampleID(it8, Buffer)) return FALSE; InSymbol(it8); break; case SIDENT: strncpy(VarName, it8->id, MAXID-1); - - if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL)) { + VarName[MAXID-1] = 0; + + if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) { #ifdef STRICT_CGATS return SynError(it8, "Undefined keyword '%s'", VarName); #else - if (!AddAvailableProperty(it8, VarName)) return FALSE; + Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED); + if (Key == NULL) return FALSE; #endif } InSymbol(it8); - if (!GetVal(it8, Buffer, "Property data expected")) return FALSE; - - - AddToList(it8, &GetTable(it8)->HeaderList, VarName, Buffer, - (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); + if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE; + + if(Key->WriteAs != WRITE_PAIR) { + AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer, + (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED); + } + else { + const char *Subkey; + char *Nextkey; + if (it8->sy != SSTRING) + return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName); + + // chop the string as a list of "subkey, value" pairs, using ';' as a separator + for(Subkey = Buffer; Subkey != NULL; Subkey = Nextkey) + { + char *Value, *temp; + + // identify token pair boundary + Nextkey = (char*) strchr(Subkey, ';'); + if(Nextkey) + *Nextkey++ = '\0'; + + // for each pair, split the subkey and the value + Value = (char*) strrchr(Subkey, ','); + if(Value == NULL) + return SynError(it8, "Invalid value for property '%s'.", VarName); + + // gobble the spaces before the coma, and the coma itself + temp = Value++; + do *temp-- = '\0'; while(temp >= Subkey && *temp == ' '); + + // gobble any space at the right + temp = Value + strlen(Value) - 1; + while(*temp == ' ') *temp-- = '\0'; + + // trim the strings from the left + Subkey += strspn(Subkey, " "); + Value += strspn(Value, " "); + + if(Subkey[0] == 0 || Value[0] == 0) + return SynError(it8, "Invalid value for property '%s'.", VarName); + AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR); + } + } InSymbol(it8); break; @@ -1793,22 +2058,23 @@ static -BOOL ParseIT8(LPIT8 it8) +LCMSBOOL ParseIT8(LPIT8 it8, LCMSBOOL nosheet) { - char* SheetTypePtr; + char* SheetTypePtr = it8 ->SheetType; + + if (nosheet == 0) { // First line is a very special case. while (isseparator(it8->ch)) NextCh(it8); - SheetTypePtr = it8 ->SheetType; - while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) { *SheetTypePtr++= (char) it8 ->ch; NextCh(it8); } + } *SheetTypePtr = 0; InSymbol(it8); @@ -1869,6 +2135,12 @@ for (idField = 0; idField < t -> nSamples; idField++) { + if (t ->DataFormat == NULL) { + SynError(it8, "Undefined DATA_FORMAT"); + return; + + } + Fld = t->DataFormat[idField]; if (!Fld) continue; @@ -1884,6 +2156,7 @@ char Buffer[256]; strncpy(Buffer, Data, 255); + Buffer[255] = 0; if (strlen(Buffer) <= strlen(Data)) strcpy(Data, Buffer); @@ -1916,7 +2189,7 @@ LPTABLE Table = it8 ->Tab + k; LPKEYVALUE p; - if (IsAvailableOnList(Table->HeaderList, Label, &p)) { + if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) { // Available, keep type and table char Buffer[256]; @@ -1924,7 +2197,7 @@ char *Type = p ->Value; int nTable = k; - sprintf(Buffer, "%s %d %s", Label, nTable, Type ); + snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type ); SetData(it8, i, idField, Buffer); } @@ -1948,8 +2221,9 @@ // that should be something like some printable characters plus a \n static -BOOL IsMyBlock(LPBYTE Buffer, size_t n) +int IsMyBlock(LPBYTE Buffer, size_t n) { + int cols = 1, space = 0, quot = 0; size_t i; if (n < 10) return FALSE; // Too small @@ -1959,9 +2233,26 @@ for (i = 1; i < n; i++) { - if (Buffer[i] == '\n' || Buffer[i] == '\r' || Buffer[i] == '\t') return TRUE; - if (Buffer[i] < 32) return FALSE; - + switch(Buffer[i]) + { + case '\n': + case '\r': + return quot == 1 || cols > 2 ? 0 : cols; + case '\t': + case ' ': + if(!quot && !space) + space = 1; + break; + case '\"': + quot = !quot; + break; + default: + if (Buffer[i] < 32) return 0; + if (Buffer[i] > 127) return 0; + cols += space; + space = 0; + break; + } } return FALSE; @@ -1970,7 +2261,7 @@ static -BOOL IsMyFile(const char* FileName) +int IsMyFile(const char* FileName) { FILE *fp; size_t Size; @@ -1998,21 +2289,22 @@ LCMSHANDLE hIT8; LPIT8 it8; - if (!IsMyBlock((LPBYTE) Ptr, len)) return NULL; + int type = IsMyBlock((LPBYTE) Ptr, len); + if (type == 0) return NULL; hIT8 = cmsIT8Alloc(); if (!hIT8) return NULL; it8 = (LPIT8) hIT8; - it8 ->MemoryBlock = (char*) malloc(len + 1); + it8 ->MemoryBlock = (char*) _cmsMalloc(len + 1); strncpy(it8 ->MemoryBlock, (const char*) Ptr, len); it8 ->MemoryBlock[len] = 0; - strncpy(it8->FileName, "", MAX_PATH-1); + strncpy(it8->FileStack[0]->FileName, "", MAX_PATH-1); it8-> Source = it8 -> MemoryBlock; - if (!ParseIT8(it8)) { + if (!ParseIT8(it8, type-1)) { cmsIT8Free(hIT8); return FALSE; @@ -2021,7 +2313,7 @@ CookPointers(it8); it8 ->nTable = 0; - free(it8->MemoryBlock); + _cmsFree(it8->MemoryBlock); it8 -> MemoryBlock = NULL; return hIT8; @@ -2036,26 +2328,28 @@ LCMSHANDLE hIT8; LPIT8 it8; - if (!IsMyFile(cFileName)) return NULL; + int type = IsMyFile(cFileName); + if (type == 0) return NULL; hIT8 = cmsIT8Alloc(); it8 = (LPIT8) hIT8; if (!hIT8) return NULL; - it8 ->Stream[0] = fopen(cFileName, "rt"); - - if (!it8 ->Stream[0]) { + it8 ->FileStack[0]->Stream = fopen(cFileName, "rt"); + + if (!it8 ->FileStack[0]->Stream) { cmsIT8Free(hIT8); return NULL; } - strncpy(it8->FileName, cFileName, MAX_PATH-1); - - if (!ParseIT8(it8)) { - - fclose(it8 ->Stream[0]); + strncpy(it8->FileStack[0]->FileName, cFileName, MAX_PATH-1); + it8->FileStack[0]->FileName[MAX_PATH-1] = 0; + + if (!ParseIT8(it8, type-1)) { + + fclose(it8 ->FileStack[0]->Stream); cmsIT8Free(hIT8); return NULL; } @@ -2063,7 +2357,7 @@ CookPointers(it8); it8 ->nTable = 0; - fclose(it8 ->Stream[0]); + fclose(it8 ->FileStack[0]->Stream); return hIT8; } @@ -2078,12 +2372,12 @@ } -int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, char ***PropertyNames) +int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames) { LPIT8 it8 = (LPIT8) hIT8; LPKEYVALUE p; int n; - char **Props; + const char **Props; LPTABLE t = GetTable(it8); // Pass#1 - count properties @@ -2094,7 +2388,7 @@ } - Props = (char **) AllocChunk(it8, sizeof(char *) * n); + Props = (const char **) AllocChunk(it8, sizeof(char *) * n); // Pass#2 - Fill pointers n = 0; @@ -2106,6 +2400,41 @@ return n; } +int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char ***SubpropertyNames) +{ + LPIT8 it8 = (LPIT8) hIT8; + LPKEYVALUE p, tmp; + int n; + const char **Props; + LPTABLE t = GetTable(it8); + + if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) { + *SubpropertyNames = 0; + return 0; + } + + // Pass#1 - count properties + + n = 0; + for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) { + if(tmp->Subkey != NULL) + n++; + } + + + Props = (const char **) AllocChunk(it8, sizeof(char *) * n); + + // Pass#2 - Fill pointers + n = 0; + for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) { + if(tmp->Subkey != NULL) + Props[n++] = p ->Subkey; + } + + *SubpropertyNames = Props; + return n; +} + static int LocatePatch(LPIT8 it8, const char* cPatch) { @@ -2201,7 +2530,7 @@ } -BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val) +LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val) { LPIT8 it8 = (LPIT8) hIT8; @@ -2209,7 +2538,7 @@ } -BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val) +LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val) { LPIT8 it8 = (LPIT8) hIT8; char Buff[256]; @@ -2260,7 +2589,7 @@ -BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch, +LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val) { @@ -2305,18 +2634,19 @@ } -BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, +LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, const char* cSample, double Val) { LPIT8 it8 = (LPIT8) hIT8; char Buff[256]; - sprintf(Buff, it8->DoubleFormatter, Val); + snprintf(Buff, 255, it8->DoubleFormatter, Val); return cmsIT8SetData(hIT8, cPatch, cSample, Buff); } +// Buffer should get MAXSTR at least const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer) { @@ -2327,10 +2657,16 @@ if (!Data) return NULL; if (!buffer) return Data; - strcpy(buffer, Data); + strncpy(buffer, Data, MAXSTR-1); + buffer[MAXSTR-1] = 0; return buffer; } +int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cPatch) +{ + return LocatePatch((LPIT8)hIT8, cPatch); +} + int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE hIT8) { LPIT8 it8 = (LPIT8) hIT8; @@ -2356,7 +2692,7 @@ cLabelFld = cmsIT8GetData(hIT8, cSet, cField); if (!cLabelFld) return -1; - if (sscanf(cLabelFld, "%s %d %s", Label, &nTable, Type) != 3) + if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3) return -1; if (ExpectedType != NULL && *ExpectedType == 0) @@ -2371,6 +2707,19 @@ } +LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample) +{ + LPIT8 it8 = (LPIT8) hIT8; + + int pos = LocateSample(it8, cSample); + if(pos == -1) + return FALSE; + + it8->Tab[it8->nTable].SampleID = pos; + return TRUE; +} + + void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter) { LPIT8 it8 = (LPIT8) hIT8; @@ -2380,3 +2729,4 @@ else strcpy(it8->DoubleFormatter, Formatter); } + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -256,7 +256,7 @@ // Return TRUE if both m and of are empy -- "m" being identity and "of" being 0 static -BOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of) +LCMSBOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of) { WVEC3 wv0; @@ -661,3 +661,6 @@ return rc; } + + + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmserr.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -57,6 +57,7 @@ // errors. void cdecl cmsSignalError(int ErrorCode, const char *ErrorText, ...); + int LCMSEXPORT cmsErrorAction(int lAbort); void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn); @@ -96,7 +97,7 @@ char Buffer[1024]; - vsprintf(Buffer, ErrorText, args); + vsnprintf(Buffer, 1023, ErrorText, args); va_end(args); if (UserErrorHandler(ErrorCode, Buffer)) { @@ -118,8 +119,8 @@ char Buffer1[1024]; char Buffer2[256]; - sprintf(Buffer1, "Error #%x; ", ErrorCode); - vsprintf(Buffer2, ErrorText, args); + 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); diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -63,9 +63,9 @@ LPGAMMATABLE LCMSEXPORT cmsBuildParametricGamma(int nEntries, int Type, double Params[]); LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma); LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma, int nPoints); -BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda); +LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda); -BOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints); +LCMSBOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints); // Sampled curves @@ -74,7 +74,7 @@ void cdecl cmsFreeSampledCurve(LPSAMPLEDCURVE p); void cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max); void cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max); -BOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda); +LCMSBOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda); void cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints); LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints); @@ -84,7 +84,6 @@ // ---------------------------------------------------------------------------------------- -// #define DEBUG 1 #define MAX_KNOTS 4096 typedef float vec[MAX_KNOTS+1]; @@ -144,14 +143,14 @@ LPGAMMATABLE p; size_t size; - if (nEntries > 65530) { - cmsSignalError(LCMS_ERRC_WARNING, "Couldn't create gammatable of more than 65530 entries; 65530 assumed"); - nEntries = 65530; + if (nEntries > 65530 || nEntries <= 0) { + cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't create gammatable of more than 65530 entries"); + return NULL; } size = sizeof(GAMMATABLE) + (sizeof(WORD) * (nEntries-1)); - p = (LPGAMMATABLE) malloc(size); + p = (LPGAMMATABLE) _cmsMalloc(size); if (!p) return NULL; ZeroMemory(p, size); @@ -164,7 +163,7 @@ void LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma) { - if (Gamma) free(Gamma); + if (Gamma) _cmsFree(Gamma); } @@ -278,6 +277,15 @@ LPWORD InPtr; LPGAMMATABLE p; + // Try to reverse it analytically whatever possible + if (InGamma -> Seed.Type > 0 && InGamma -> Seed.Type <= 5 && + _cmsCrc32OfGammaTable(InGamma) == InGamma -> Seed.Crc32) { + + return cmsBuildParametricGamma(nResultSamples, -(InGamma -> Seed.Type), InGamma ->Seed.Params); + } + + + // Nope, reverse the table p = cmsAllocGamma(nResultSamples); if (!p) return NULL; @@ -528,7 +536,7 @@ // Smooths a curve sampled at regular intervals -BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda) +LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda) { vec w, y, z; @@ -640,13 +648,13 @@ { LPSAMPLEDCURVE pOut; - pOut = (LPSAMPLEDCURVE) malloc(sizeof(SAMPLEDCURVE)); + pOut = (LPSAMPLEDCURVE) _cmsMalloc(sizeof(SAMPLEDCURVE)); if (pOut == NULL) return NULL; - if((pOut->Values = (double *) malloc(nItems * sizeof(double))) == NULL) + if((pOut->Values = (double *) _cmsMalloc(nItems * sizeof(double))) == NULL) { - free(pOut); + _cmsFree(pOut); return NULL; } @@ -659,8 +667,8 @@ void cmsFreeSampledCurve(LPSAMPLEDCURVE p) { - free((LPVOID) p -> Values); - free((LPVOID) p); + _cmsFree((LPVOID) p -> Values); + _cmsFree((LPVOID) p); } @@ -731,7 +739,7 @@ // Smooths a curve sampled at regular intervals -BOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda) +LCMSBOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda) { vec w, y, z; int i, nItems; @@ -915,14 +923,11 @@ // Smooth endpoints (used in Black/White compensation) -BOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries) +LCMSBOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries) { vec w, y, z; int i, Zeros, Poles; -#ifdef DEBUG - ASAVE(Table, nEntries, "nonsmt.txt"); -#endif if (cmsIsLinear(Table, nEntries)) return FALSE; // Nothing to do diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -66,7 +66,7 @@ */ -BOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black, +LCMSBOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black, int *nOutputs) { // Only most common spaces @@ -376,7 +376,6 @@ double bs = Lab2 ->b; double Cs = sqrt( Sqr(as) + Sqr(bs) ); - double G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) )); double a_p = (1 + G ) * a1; @@ -390,15 +389,21 @@ double C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps)); double h_ps = atan2deg(a_ps, b_ps); - - double meanC_p =(C_p + C_ps) / 2; - double meanh_p = fabs(h_ps-h_p) <= 180 ? (h_ps + h_p)/2 : (h_ps+h_p-360)/2; + double hps_plus_hp = h_ps + h_p; + double hps_minus_hp = h_ps - h_p; + + double meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 : + (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 : + (hps_plus_hp - 360)/2; - double delta_h = fabs(h_p - h_ps) <= 180 ? fabs(h_p - h_ps) : 360 - fabs(h_p - h_ps); - double delta_L = fabs(L1 - Ls); - double delta_C = fabs(C_p - C_ps); + double delta_h = (hps_minus_hp) <= -180.000001 ? (hps_minus_hp + 360) : + (hps_minus_hp) > 180 ? (hps_minus_hp - 360) : + (hps_minus_hp); + double delta_L = (Ls - L1); + double delta_C = (C_ps - C_p ); + double delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANES(delta_h) / 2); @@ -1065,7 +1070,7 @@ // Check for monotonicity. static -BOOL IsMonotonic(LPGAMMATABLE t) +LCMSBOOL IsMonotonic(LPGAMMATABLE t) { int n = t -> nEntries; int i, last; @@ -1088,7 +1093,7 @@ // Check for endpoints static -BOOL HasProperEndpoints(LPGAMMATABLE t) +LCMSBOOL HasProperEndpoints(LPGAMMATABLE t) { if (t ->GammaTable[0] != 0) return FALSE; if (t ->GammaTable[t ->nEntries-1] != 0xFFFF) return FALSE; @@ -1109,7 +1114,7 @@ unsigned int t, i, v; int j; WORD In[MAXCHANNELS], Out[MAXCHANNELS]; - BOOL lIsSuitable; + LCMSBOOL lIsSuitable; _LPcmsTRANSFORM InputXForm = (_LPcmsTRANSFORM) h[0]; _LPcmsTRANSFORM OutputXForm = (_LPcmsTRANSFORM) h[nTransforms-1]; @@ -1126,10 +1131,10 @@ } - // Do nothing on all but RGB to RGB transforms + // Do nothing on all but Gray/RGB to Gray/RGB transforms - if ((InputXForm ->EntryColorSpace != icSigRgbData) || - (OutputXForm->ExitColorSpace != icSigRgbData)) return; + if (((InputXForm ->EntryColorSpace != icSigRgbData) && (InputXForm ->EntryColorSpace != icSigGrayData)) || + ((OutputXForm->ExitColorSpace != icSigRgbData) && (OutputXForm->ExitColorSpace != icSigGrayData))) return; for (t = 0; t < Grid -> InputChan; t++) @@ -1169,10 +1174,13 @@ if (!HasProperEndpoints(Trans[t])) lIsSuitable = FALSE; + /* // Exclude if transfer function is not smooth enough // to be modelled as a gamma function, or the gamma is reversed + if (cmsEstimateGamma(Trans[t]) < 1.0) lIsSuitable = FALSE; + */ } diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -282,7 +282,7 @@ // Fills optimization parameters void cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan, - BOOL lUseTetrahedral, LPL16PARAMS p) + LCMSBOOL lUseTetrahedral, LPL16PARAMS p) { int clutPoints; @@ -579,7 +579,7 @@ // Identify if value fall downto 0 or FFFF zone if (Value == 0) return 0; - if (Value == 0xFFFF) return 0xFFFF; + // if (Value == 0xFFFF) return 0xFFFF; // else restrict to valid zone @@ -631,7 +631,7 @@ a = (y1 - y0) / (x1 - x0); b = y0 - a * x0; - if (a == 0) return (WORD) x; + if (fabs(a) < 0.01) return (WORD) x; f = ((Value - b) / a); @@ -763,7 +763,7 @@ X0 = p -> opta3 * x0; X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3); - Y0 = p -> opta2 * y0; + Y0 = p -> opta2 * y0; Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2); Z0 = p -> opta1 * z0; @@ -942,7 +942,7 @@ X0 = p -> opta3 * x0; X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3); - Y0 = p -> opta2 * y0; + Y0 = p -> opta2 * y0; Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2); Z0 = p -> opta1 * z0; @@ -1009,11 +1009,11 @@ Rest = c1 * rx + c2 * ry + c3 * rz; - // There is a lot of math hidden in this expression. The rest is in fixed domain - // and the result in 0..ffff domain. So the complete expression should be - // ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF + // There is a lot of math hidden in this expression. The rest is in fixed domain + // and the result in 0..ffff domain. So the complete expression should be + // ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF - Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF)); + Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF)); } @@ -1131,3 +1131,4 @@ } #undef DENS + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -62,7 +62,7 @@ typedef struct { LPBYTE Block; // Points to allocated memory size_t Size; // Size of allocated memory - int Pointer; // Points to current location + size_t Pointer; // Points to current location int FreeBlockOnClose; // As title } FILEMEM; @@ -70,18 +70,19 @@ static LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode) { - FILEMEM* fm = (FILEMEM*) malloc(sizeof(FILEMEM)); + FILEMEM* fm = (FILEMEM*) _cmsMalloc(sizeof(FILEMEM)); + if (fm == NULL) return NULL; + ZeroMemory(fm, sizeof(FILEMEM)); if (Mode == 'r') { - fm ->Block = (LPBYTE) malloc(Size); + fm ->Block = (LPBYTE) _cmsMalloc(Size); if (fm ->Block == NULL) { - free(fm); + _cmsFree(fm); return NULL; } - CopyMemory(fm->Block, Block, Size); fm ->FreeBlockOnClose = TRUE; } @@ -103,13 +104,27 @@ FILEMEM* ResData = (FILEMEM*) Icc ->stream; LPBYTE Ptr; size_t len = size * count; + size_t extent = ResData -> Pointer + len; + if (len == 0) { + return 0; + } - if (ResData -> Pointer + len > ResData -> Size){ + if (len / size != count) { + cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with count / size."); + return 0; + } + + if (extent < len || extent < ResData -> Pointer) { + cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with len."); + return 0; + } + + if (ResData -> Pointer + len > ResData -> Size) { len = (ResData -> Size - ResData -> Pointer); - cmsSignalError(LCMS_ERRC_WARNING, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size); - + cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size); + return 0; } Ptr = ResData -> Block; @@ -123,7 +138,7 @@ // SEEK_CUR is assumed static -BOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset) +LCMSBOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset) { FILEMEM* ResData = (FILEMEM*) Icc ->stream; @@ -147,10 +162,10 @@ } -// Writes data to memory, also keeps used space for further reference +// Writes data to memory, also keeps used space for further reference. NO CHECK IS PERFORMED static -BOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr) +LCMSBOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr) { FILEMEM* ResData = (FILEMEM*) Icc ->stream; @@ -167,11 +182,17 @@ static -BOOL MemoryGrow(struct _lcms_iccprofile_struct* Icc, size_t size) +LCMSBOOL MemoryGrow(struct _lcms_iccprofile_struct* Icc, size_t size) { FILEMEM* ResData = (FILEMEM*) Icc->stream; - void* newBlock = realloc(ResData->Block, ResData->Size + size); + void* newBlock = NULL; + + /* Follow same policies as functions in lcms.h */ + if (ResData->Size + size < 0) return NULL; + if (ResData->Size + size > (size_t)1024*1024*500))) return NULL; + + newBlock = realloc(ResData->Block, ResData->Size + size); if (!newBlock) { return FALSE; @@ -183,15 +204,15 @@ static -BOOL MemoryClose(struct _lcms_iccprofile_struct* Icc) +LCMSBOOL MemoryClose(struct _lcms_iccprofile_struct* Icc) { FILEMEM* ResData = (FILEMEM*) Icc ->stream; if (ResData ->FreeBlockOnClose) { - if (ResData ->Block) free(ResData ->Block); + if (ResData ->Block) _cmsFree(ResData ->Block); } - free(ResData); + _cmsFree(ResData); return 0; } @@ -209,7 +230,7 @@ { size_t nReaded = fread(buffer, size, count, (FILE*) Icc->stream); if (nReaded != count) { - cmsSignalError(LCMS_ERRC_WARNING, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size); + cmsSignalError(LCMS_ERRC_ABORTED, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size); return 0; } @@ -218,7 +239,7 @@ static -BOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset) +LCMSBOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset) { if (fseek((FILE*) Icc ->stream, (long) offset, SEEK_SET) != 0) { @@ -240,7 +261,7 @@ static -BOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr) +LCMSBOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr) { if (size == 0) return TRUE; @@ -256,14 +277,14 @@ static -BOOL FileGrow(struct _lcms_iccprofile_struct* Icc, size_t size) +LCMSBOOL FileGrow(struct _lcms_iccprofile_struct* Icc, size_t size) { return TRUE; } static -BOOL FileClose(struct _lcms_iccprofile_struct* Icc) +LCMSBOOL FileClose(struct _lcms_iccprofile_struct* Icc) { return fclose((FILE*) Icc ->stream); } @@ -276,7 +297,7 @@ cmsHPROFILE _cmsCreateProfilePlaceholder(void) { - LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) malloc(sizeof(LCMSICCPROFILE)); + LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) _cmsMalloc(sizeof(LCMSICCPROFILE)); if (Icc == NULL) return NULL; // Empty values @@ -314,7 +335,7 @@ // Search for a specific tag in tag dictionary // Returns position or -1 if tag not found -icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL lSignalError) +icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError) { icInt32Number i; @@ -335,7 +356,7 @@ // Check existance -BOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig) +LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; return _cmsSearchTag(Icc, sig, FALSE) >= 0; @@ -354,7 +375,7 @@ if (i >=0) { - if (Icc -> TagPtrs[i]) free(Icc -> TagPtrs[i]); + if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]); } else { @@ -365,11 +386,14 @@ cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG); Icc ->TagCount = MAX_TABLE_TAG-1; + return NULL; } } - Ptr = malloc(size); + Ptr = _cmsMalloc(size); + if (Ptr == NULL) return NULL; + CopyMemory(Ptr, Init, size); Icc ->TagNames[i] = sig; @@ -400,6 +424,8 @@ if (NewIcc == NULL) return NULL; strncpy(NewIcc -> PhysicalFile, FileName, MAX_PATH-1); + NewIcc -> PhysicalFile[MAX_PATH-1] = 0; + NewIcc ->stream = ICCfile; NewIcc ->Read = FileRead; @@ -502,7 +528,7 @@ -BOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; *Dest = Icc -> MediaWhitePoint; @@ -510,14 +536,14 @@ } -BOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; *Dest = Icc -> MediaBlackPoint; return TRUE; } -BOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; *Dest = Icc -> Illuminant; @@ -575,7 +601,7 @@ } -BOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; CopyMemory(Dest, &Icc ->Created, sizeof(struct tm)); @@ -596,23 +622,18 @@ Icc -> PCS = pcs; } - - icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; return Icc -> ColorSpace; } - - void LCMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, icColorSpaceSignature sig) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; Icc -> ColorSpace = sig; } - icProfileClassSignature LCMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; @@ -625,7 +646,6 @@ return (DWORD) Icc -> Version; } - void LCMSEXPORT cmsSetProfileICCversion(cmsHPROFILE hProfile, DWORD Version) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile; @@ -664,7 +684,7 @@ // This is tricky, since LUT structs does have pointers -BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut) +LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; LPLUT Orig, Stored; @@ -692,7 +712,7 @@ } -BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ) +LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -701,7 +721,7 @@ } -BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text) +LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -709,7 +729,7 @@ return TRUE; } -BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction) +LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -718,7 +738,7 @@ } -BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm) +LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -727,7 +747,7 @@ } -BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq) +LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -737,28 +757,40 @@ } -BOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc) +LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc); - return FALSE; + return TRUE; } -BOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime) +LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; _cmsInitTag(Icc, sig, sizeof(struct tm), DateTime); - return FALSE; + return TRUE; } -BOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc) +LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc); - return FALSE; + return TRUE; } + + +LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat) +{ + LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; + + _cmsInitTag(Icc, sig, 3*sizeof(cmsCIEXYZ), mat); + return TRUE; + +} + + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio1.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -149,6 +149,7 @@ #endif + // Transports to properly encoded values - note that icc profiles does use // big endian notation. @@ -216,7 +217,8 @@ { icTagBase Base; - Icc -> Read(&Base, sizeof(icTagBase), 1, Icc); + if (Icc -> Read(&Base, sizeof(icTagBase), 1, Icc) != 1) + return (icTagTypeSignature) 0; AdjustEndianess32((LPBYTE) &Base.sig); return Base.sig; @@ -288,13 +290,15 @@ // Read profile header and validate it static -LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, BOOL lIsFromMemory) +LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, LCMSBOOL lIsFromMemory) { icTag Tag; icHeader Header; icInt32Number TagCount, i; - - Icc -> Read(&Header, sizeof(icHeader), 1, Icc); + icUInt32Number extent; + + if (Icc -> Read(&Header, sizeof(icHeader), 1, Icc) != 1) + goto ErrorCleanup; // Convert endian @@ -306,14 +310,13 @@ AdjustEndianess32((LPBYTE) &Header.pcs); AdjustEndianess32((LPBYTE) &Header.magic); AdjustEndianess32((LPBYTE) &Header.flags); - AdjustEndianess32((LPBYTE) &Header.attributes[0]); + AdjustEndianess32((LPBYTE) &Header.attributes[0]); AdjustEndianess32((LPBYTE) &Header.renderingIntent); // Validate it if (Header.magic != icMagicNumber) goto ErrorCleanup; - if (Icc ->Read(&TagCount, sizeof(icInt32Number), 1, Icc) != 1) goto ErrorCleanup; @@ -324,7 +327,7 @@ Icc -> PCS = Header.pcs; Icc -> RenderingIntent = (icRenderingIntent) Header.renderingIntent; Icc -> flags = Header.flags; - Icc -> attributes = Header.attributes[0]; + Icc -> attributes = Header.attributes[0]; Icc -> Illuminant.X = Convert15Fixed16(Header.illuminant.X); Icc -> Illuminant.Y = Convert15Fixed16(Header.illuminant.Y); Icc -> Illuminant.Z = Convert15Fixed16(Header.illuminant.Z); @@ -348,7 +351,7 @@ // Read tag directory - if (TagCount > MAX_TABLE_TAG) { + if (TagCount > MAX_TABLE_TAG || TagCount < 0) { cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", TagCount); goto ErrorCleanup; @@ -357,12 +360,18 @@ Icc -> TagCount = TagCount; for (i=0; i < TagCount; i++) { - Icc ->Read(&Tag, sizeof(icTag), 1, Icc); + if (Icc ->Read(&Tag, sizeof(icTag), 1, Icc) != 1) + goto ErrorCleanup; AdjustEndianess32((LPBYTE) &Tag.offset); AdjustEndianess32((LPBYTE) &Tag.size); AdjustEndianess32((LPBYTE) &Tag.sig); // Signature + // Perform some sanity check. Offset + size should fall inside file. + extent = Tag.offset + Tag.size; + if (extent > Header.size || extent < Tag.offset) + goto ErrorCleanup; + Icc -> TagNames[i] = Tag.sig; Icc -> TagOffsets[i] = Tag.offset; Icc -> TagSizes[i] = Tag.size; @@ -381,13 +390,10 @@ cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted profile: '%s'", Icc->PhysicalFile); - free(Icc); + _cmsFree(Icc); return NULL; } - - - static unsigned int uipow(unsigned int a, unsigned int b) { unsigned int rv = 1; @@ -497,7 +503,7 @@ // The infamous LUT 8 static -void ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) +LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig) { icLut8 LUT8; LPBYTE Temp; @@ -506,7 +512,7 @@ unsigned int AllLinear; LPWORD PtrW; - Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc); + if (Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return FALSE; NewLUT -> wFlags = LUT_HASTL1|LUT_HASTL2|LUT_HAS3DGRID; NewLUT -> cLutPoints = LUT8.clutPoints; @@ -515,6 +521,10 @@ NewLUT -> InputEntries = 256; NewLUT -> OutputEntries = 256; + // Do some checking + if (!_cmsValidateLUT(NewLUT)) { + return FALSE; + } AdjustEndianess32((LPBYTE) &LUT8.e00); AdjustEndianess32((LPBYTE) &LUT8.e01); @@ -550,13 +560,24 @@ // Copy input tables - Temp = (LPBYTE) malloc(256); + Temp = (LPBYTE) _cmsMalloc(256); + if (Temp == NULL) return FALSE; + AllLinear = 0; for (i=0; i < NewLUT -> InputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * 256); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256); + if (PtrW == NULL) { + _cmsFree(Temp); + return FALSE; + } + NewLUT -> L1[i] = PtrW; - Icc ->Read(Temp, 1, 256, Icc); + if (Icc ->Read(Temp, 1, 256, Icc) != 256) { + _cmsFree(Temp); + return FALSE; + } + for (j=0; j < 256; j++) PtrW[j] = TO16_TAB(Temp[j]); AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries); @@ -569,7 +590,7 @@ NewLUT -> wFlags &= ~LUT_HASTL1; } - free(Temp); + _cmsFree(Temp); // Copy 3D CLUT @@ -578,9 +599,20 @@ if (nTabSize > 0) { - PtrW = (LPWORD) malloc(sizeof(WORD) * nTabSize); - Temp = (LPBYTE) malloc(nTabSize); - Icc ->Read(Temp, 1, nTabSize, Icc); + PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize); + if (PtrW == NULL) return FALSE; + + Temp = (LPBYTE) _cmsMalloc(nTabSize); + if (Temp == NULL) { + _cmsFree(PtrW); + return FALSE; + } + + if (Icc ->Read(Temp, 1, nTabSize, Icc) != nTabSize) { + _cmsFree(Temp); + _cmsFree(PtrW); + return FALSE; + } NewLUT -> T = PtrW; NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD)); @@ -589,25 +621,37 @@ *PtrW++ = TO16_TAB(Temp[i]); } - free(Temp); + _cmsFree(Temp); } else { NewLUT ->T = NULL; NewLUT ->Tsize = 0; - NewLUT -> wFlags &= ~LUT_HAS3DGRID; + NewLUT ->wFlags &= ~LUT_HAS3DGRID; } - // Copy output tables - Temp = (LPBYTE) malloc(256); + Temp = (LPBYTE) _cmsMalloc(256); + if (Temp == NULL) { + return FALSE; + } + AllLinear = 0; for (i=0; i < NewLUT -> OutputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * 256); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256); + if (PtrW == NULL) { + _cmsFree(Temp); + return FALSE; + } + NewLUT -> L2[i] = PtrW; - Icc ->Read(Temp, 1, 256, Icc); + if (Icc ->Read(Temp, 1, 256, Icc) != 256) { + _cmsFree(Temp); + return FALSE; + } + for (j=0; j < 256; j++) PtrW[j] = TO16_TAB(Temp[j]); AllLinear += cmsIsLinear(NewLUT -> L2[i], 256); @@ -621,7 +665,7 @@ } - free(Temp); + _cmsFree(Temp); cmsCalcL16Params(NewLUT -> InputEntries, &NewLUT -> In16params); cmsCalcL16Params(NewLUT -> OutputEntries, &NewLUT -> Out16params); @@ -646,6 +690,15 @@ // some profiles does claim to do that. Poor lcms will try // to detect such condition and fix up "on the fly". + switch (sig) { + + case icSigBToA0Tag: + case icSigBToA1Tag: + case icSigBToA2Tag: + case icSigGamutTag: + case icSigPreview0Tag: + case icSigPreview1Tag: + case icSigPreview2Tag: { LPWORD WhiteLab, ExpectedWhite; WORD WhiteFixed[MAXCHANNELS], WhiteUnfixed[MAXCHANNELS]; @@ -685,9 +738,13 @@ } } - + break; + + default:; + } } + return TRUE; } @@ -696,7 +753,7 @@ // Case LUT 16 static -void ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT) +LCMSBOOL ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT) { icLut16 LUT16; size_t nTabSize; @@ -705,7 +762,8 @@ LPWORD PtrW; - Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc); + if (Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc) != 1) + return FALSE; NewLUT -> wFlags = LUT_HASTL1 | LUT_HASTL2 | LUT_HAS3DGRID; NewLUT -> cLutPoints = LUT16.clutPoints; @@ -718,6 +776,9 @@ NewLUT -> InputEntries = LUT16.inputEnt; NewLUT -> OutputEntries = LUT16.outputEnt; + if (!_cmsValidateLUT(NewLUT)) { + return FALSE; + } // Matrix handling @@ -754,9 +815,14 @@ AllLinear = 0; for (i=0; i < NewLUT -> InputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries); + if (PtrW == NULL) return FALSE; + NewLUT -> L1[i] = PtrW; - Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc); + if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc) != NewLUT -> InputEntries) { + return FALSE; + } + AdjustEndianessArray16(PtrW, NewLUT -> InputEntries); AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries); } @@ -775,12 +841,17 @@ NewLUT->InputChan)); if (nTabSize > 0) { - PtrW = (LPWORD) malloc(sizeof(WORD) * nTabSize); + PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize); + if (PtrW == NULL) + return FALSE; NewLUT -> T = PtrW; NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD)); - Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc); + if (Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc) != nTabSize) { + return FALSE; + } + AdjustEndianessArray16(NewLUT -> T, nTabSize); } else { @@ -794,9 +865,16 @@ AllLinear = 0; for (i=0; i < NewLUT -> OutputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries); + if (PtrW == NULL) { + return FALSE; + } + NewLUT -> L2[i] = PtrW; - Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc); + if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc) != NewLUT -> OutputEntries) { + return FALSE; + } + AdjustEndianessArray16(PtrW, NewLUT -> OutputEntries); AllLinear += cmsIsLinear(NewLUT -> L2[i], NewLUT -> OutputEntries); } @@ -814,6 +892,8 @@ cmsCalcCLUT16Params(NewLUT -> cLutPoints, NewLUT -> InputChan, NewLUT -> OutputChan, &NewLUT -> CLut16params); + + return TRUE; } @@ -830,17 +910,15 @@ BaseType = ReadBase(Icc); - switch (BaseType) { - case 0x9478ee00L: // Monaco 2 profiler is BROKEN! + case ((icTagTypeSignature) 0x9478ee00): // Monaco 2 profiler is BROKEN! case icSigCurveType: - Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc); + if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL; AdjustEndianess32((LPBYTE) &Count); - switch (Count) { case 0: // Linear. @@ -855,7 +933,7 @@ { WORD SingleGammaFixed; - Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc); + if (Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL; AdjustEndianess16((LPBYTE) &SingleGammaFixed); return cmsBuildGamma(4096, Convert8Fixed8(SingleGammaFixed)); } @@ -865,10 +943,9 @@ NewGamma = cmsAllocGamma(Count); if (!NewGamma) return NULL; - Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc); - + if (Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count) + return NULL; AdjustEndianessArray16(NewGamma -> GammaTable, Count); - return NewGamma; } } @@ -885,11 +962,11 @@ icUInt16Number Type; int i; - Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc); - Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc); + if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL; + if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL; AdjustEndianess16((LPBYTE) &Type); - if (Type > 5) { + if (Type > 4) { cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type); return NULL; @@ -900,7 +977,7 @@ for (i=0; i < n; i++) { Num = 0; - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); + if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL; Params[i] = Convert15Fixed16(Num); } @@ -938,7 +1015,7 @@ case 0x9478ee00L: // Monaco 2 profiler is BROKEN! case icSigCurveType: - Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc); + if (Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL; AdjustEndianess32((LPBYTE) &Count); @@ -948,6 +1025,7 @@ NewGamma = cmsAllocGamma(2); if (!NewGamma) return NULL; + NewGamma -> GammaTable[0] = 0; NewGamma -> GammaTable[1] = 0xFFFF; return NewGamma; @@ -955,7 +1033,7 @@ case 1: { WORD SingleGammaFixed; - Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc); + if (Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL; AdjustEndianess16((LPBYTE) &SingleGammaFixed); return cmsBuildGamma(4096, 1./Convert8Fixed8(SingleGammaFixed)); } @@ -965,7 +1043,8 @@ NewGamma = cmsAllocGamma(Count); if (!NewGamma) return NULL; - Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc); + if (Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count) + return NULL; AdjustEndianessArray16(NewGamma -> GammaTable, Count); @@ -992,11 +1071,11 @@ int i; - Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc); - Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc); + if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL; + if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL; AdjustEndianess16((LPBYTE) &Type); - if (Type > 5) { + if (Type > 4) { cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type); return NULL; @@ -1006,7 +1085,7 @@ n = ParamsByType[Type]; for (i=0; i < n; i++) { - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); + if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL; Params[i] = Convert15Fixed16(Num); } @@ -1028,7 +1107,7 @@ // V4 stuff. Read matrix for LutAtoB and LutBtoA static -BOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags) +LCMSBOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags) { icS15Fixed16Number All[12]; @@ -1038,7 +1117,8 @@ if (Icc -> Seek(Icc, Offset)) return FALSE; - Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc); + if (Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc) != 12) + return FALSE; for (i=0; i < 12; i++) AdjustEndianess32((LPBYTE) &All[i]); @@ -1067,17 +1147,26 @@ // V4 stuff. Read CLUT part for LutAtoB and LutBtoA static -BOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT) +LCMSBOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT) { - + unsigned int j; icCLutStruct CLUT; if (Icc -> Seek(Icc, Offset)) return FALSE; - Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc); - - - cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan, - NewLUT ->OutputChan); + if (Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc) != 1) return FALSE; + + + for (j=1; j < NewLUT ->InputChan; j++) { + if (CLUT.gridPoints[0] != CLUT.gridPoints[j]) { + cmsSignalError(LCMS_ERRC_ABORTED, "CLUT with different granulatity is currently unsupported."); + return FALSE; + } + + + } + + if (cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan, + NewLUT ->OutputChan) == NULL) return FALSE; // Precission can be 1 or 2 bytes @@ -1087,7 +1176,7 @@ unsigned int i; for (i=0; i < NewLUT->Tsize / sizeof(WORD); i++) { - Icc ->Read(&v, sizeof(BYTE), 1, Icc); + if (Icc ->Read(&v, sizeof(BYTE), 1, Icc) != 1) return FALSE; NewLUT->T[i] = TO16_TAB(v); } @@ -1095,10 +1184,10 @@ else if (CLUT.prec == 2) { - Icc ->Read(NewLUT ->T, sizeof(WORD), - NewLUT->Tsize / sizeof(WORD), Icc); - - AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD)); + size_t n = NewLUT->Tsize / sizeof(WORD); + + if (Icc ->Read(NewLUT ->T, sizeof(WORD), n, Icc) != n) return FALSE; + AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD)); } else { cmsSignalError(LCMS_ERRC_ABORTED, "Unknow precission of '%d'", CLUT.prec); @@ -1110,6 +1199,22 @@ static +void ResampleCurves(LPGAMMATABLE Curves[], int nCurves) +{ + int i; + LPSAMPLEDCURVE sc; + + for (i=0; i < nCurves; i++) { + sc = cmsConvertGammaToSampledCurve(Curves[i], 4096); + cmsFreeGamma(Curves[i]); + Curves[i] = cmsConvertSampledCurveToGamma(sc, 0xFFFF); + cmsFreeSampledCurve(sc); + } + +} + + +static void SkipAlignment(LPLCMSICCPROFILE Icc) { BYTE Buffer[4]; @@ -1121,7 +1226,7 @@ // Read a set of curves from specific offset static -BOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation) +LCMSBOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation) { LPGAMMATABLE Curves[MAXCHANNELS]; unsigned int i, nCurves; @@ -1134,20 +1239,41 @@ else nCurves = NewLUT ->OutputChan; + ZeroMemory(Curves, sizeof(Curves)); for (i=0; i < nCurves; i++) { Curves[i] = ReadCurve(Icc); + if (Curves[i] == NULL) goto Error; SkipAlignment(Icc); - + } + + // March-26'08: some V4 profiles may have different sampling + // rates, in this case resample all curves to maximum + + for (i=1; i < nCurves; i++) { + if (Curves[i]->nEntries != Curves[0]->nEntries) { + ResampleCurves(Curves, nCurves); + break; + } } NewLUT = cmsAllocLinearTable(NewLUT, Curves, nLocation); + if (NewLUT == NULL) goto Error; for (i=0; i < nCurves; i++) cmsFreeGamma(Curves[i]); return TRUE; +Error: + + for (i=0; i < nCurves; i++) + if (Curves[i]) + cmsFreeGamma(Curves[i]); + + return FALSE; + + } // V4 stuff. LutAtoB type @@ -1160,22 +1286,28 @@ // L2 = B curves static -BOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig) +LCMSBOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig) { icLutAtoB LUT16; - Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc); + if (Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc) != 1) return FALSE; NewLUT -> InputChan = LUT16.inputChan; NewLUT -> OutputChan = LUT16.outputChan; + // Validate the NewLUT here to avoid excessive number of channels + // (leading to stack-based buffer overflow in ReadSetOfCurves). + // Needs revalidation after table size is filled in. + if (!_cmsValidateLUT(NewLUT)) { + return FALSE; + } + AdjustEndianess32((LPBYTE) &LUT16.offsetB); AdjustEndianess32((LPBYTE) &LUT16.offsetMat); AdjustEndianess32((LPBYTE) &LUT16.offsetM); AdjustEndianess32((LPBYTE) &LUT16.offsetC); AdjustEndianess32((LPBYTE) &LUT16.offsetA); - if (LUT16.offsetB != 0) ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetB, NewLUT, 2); @@ -1220,15 +1352,22 @@ // V4 stuff. LutBtoA type static -BOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig) +LCMSBOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig) { icLutBtoA LUT16; - Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc); + if (Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc) != 1) return FALSE; NewLUT -> InputChan = LUT16.inputChan; NewLUT -> OutputChan = LUT16.outputChan; + // Validate the NewLUT here to avoid excessive number of channels + // (leading to stack-based buffer overflow in ReadSetOfCurves). + // Needs revalidation after table size is filled in. + if (!_cmsValidateLUT(NewLUT)) { + return FALSE; + } + AdjustEndianess32((LPBYTE) &LUT16.offsetB); AdjustEndianess32((LPBYTE) &LUT16.offsetMat); AdjustEndianess32((LPBYTE) &LUT16.offsetM); @@ -1242,7 +1381,6 @@ if (LUT16.offsetMat != 0) ReadMatrixOffset(Icc, BaseOffset + LUT16.offsetMat, NewLUT, LUT_HASMATRIX3); - if (LUT16.offsetM != 0) ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetM, NewLUT, 3); @@ -1294,7 +1432,7 @@ // If is in memory, the LUT is already there, so throw a copy - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { return cmsDupLUT((LPLUT) Icc ->TagPtrs[n]); } @@ -1308,8 +1446,8 @@ NewLUT = cmsAllocLUT(); - if (!NewLUT) - { + if (!NewLUT) { + cmsSignalError(LCMS_ERRC_ABORTED, "cmsAllocLUT() failed"); return NULL; } @@ -1317,11 +1455,29 @@ switch (BaseType) { - case icSigLut8Type: ReadLUT8(Icc, NewLUT, sig); break; - case icSigLut16Type: ReadLUT16(Icc, NewLUT); break; - - case icSiglutAtoBType: ReadLUT_A2B(Icc, NewLUT, offset, sig); break; - case icSiglutBtoAType: ReadLUT_B2A(Icc, NewLUT, offset, sig); break; + case icSigLut8Type: if (!ReadLUT8(Icc, NewLUT, sig)) { + cmsFreeLUT(NewLUT); + return NULL; + } + break; + + case icSigLut16Type: if (!ReadLUT16(Icc, NewLUT)) { + cmsFreeLUT(NewLUT); + return NULL; + } + break; + + case icSiglutAtoBType: if (!ReadLUT_A2B(Icc, NewLUT, offset, sig)) { + cmsFreeLUT(NewLUT); + return NULL; + } + break; + + case icSiglutBtoAType: if (!ReadLUT_B2A(Icc, NewLUT, offset, sig)) { + cmsFreeLUT(NewLUT); + return NULL; + } + break; default: cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType); cmsFreeLUT(NewLUT); @@ -1335,16 +1491,23 @@ // Sets the language & country preferences. Used only in ICC 4.0 profiles -void LCMSEXPORT cmsSetLanguage(int LanguageCode, int CountryCode) +void LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4]) { - GlobalLanguageCode = LanguageCode; - GlobalCountryCode = CountryCode; + + int LanguageCodeInt = *(int *) LanguageCode; + int CountryCodeInt = *(int *) CountryCode; + + AdjustEndianess32((LPBYTE) &LanguageCodeInt); + AdjustEndianess32((LPBYTE) &CountryCodeInt); + + GlobalLanguageCode = LanguageCodeInt; + GlobalCountryCode = CountryCodeInt; } // Some tags (e.g, 'pseq') can have text tags embedded. This function -// handles such special case. +// handles such special case. Returns -1 on error, or the number of bytes left on success. static int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t size_max) @@ -1353,7 +1516,6 @@ BaseType = ReadBase(Icc); - size -= sizeof(icTagBase); switch (BaseType) { @@ -1365,50 +1527,54 @@ icUInt16Number ScriptCodeCode, Dummy; icUInt8Number ScriptCodeCount; - Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc); - - if (size < sizeof(icUInt32Number)) return (int) size; + if (Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1; + + if (size < sizeof(icUInt32Number)) return (int) size; size -= sizeof(icUInt32Number); AdjustEndianess32((LPBYTE) &AsciiCount); Icc ->Read(Name, 1, (AsciiCount >= size_max) ? (size_max-1) : AsciiCount, Icc); - if (size < AsciiCount) return (int) size; + if (size < AsciiCount) return (int) size; size -= AsciiCount; // Skip Unicode code - Icc ->Read(&UnicodeCode, sizeof(icUInt32Number), 1, Icc); - if (size < sizeof(icUInt32Number)) return (int) size; + if (Icc ->Read(&UnicodeCode, sizeof(icUInt32Number), 1, Icc) != 1) return -1; + if (size < sizeof(icUInt32Number)) return (int) size; size -= sizeof(icUInt32Number); - Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc); - if (size < sizeof(icUInt32Number)) return (int) size; + if (Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1; + if (size < sizeof(icUInt32Number)) return (int) size; size -= sizeof(icUInt32Number); AdjustEndianess32((LPBYTE) &UnicodeCount); if (UnicodeCount > size) return (int) size; - for (i=0; i < UnicodeCount; i++) - Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc); - - size -= UnicodeCount * sizeof(icUInt16Number); + for (i=0; i < UnicodeCount; i++) { + size_t nread = Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc); + if (nread != 1) return (int) size; + size -= sizeof(icUInt16Number); + } // Skip ScriptCode code - Icc ->Read(&ScriptCodeCode, sizeof(icUInt16Number), 1, Icc); + if (Icc ->Read(&ScriptCodeCode, sizeof(icUInt16Number), 1, Icc) != 1) return -1; size -= sizeof(icUInt16Number); - Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc); + if (Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc) != 1) return -1; size -= sizeof(icUInt8Number); + // Should remain 67 bytes as filler + if (size < 67) return (int) size; - for (i=0; i < 67; i++) - Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc); - - size -= 67; + for (i=0; i < 67; i++) { + size_t nread = Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc); + if (nread != 1) return (int) size; + size --; + } } break; @@ -1425,7 +1591,7 @@ size = size_max - 1; } - Icc -> Read(Name, 1, size, Icc); + if (Icc -> Read(Name, 1, size, Icc) != size) return -1; for (i=0; i < Missing; i++) Icc -> Read(&Dummy, 1, 1, Icc); @@ -1445,9 +1611,9 @@ wchar_t* wchar = L""; - Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc); + if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return -1; AdjustEndianess32((LPBYTE) &Count); - Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc); + if (Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1; AdjustEndianess32((LPBYTE) &RecLen); if (RecLen != 12) { @@ -1458,15 +1624,15 @@ for (i=0; i < Count; i++) { - Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc); + if (Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc) != 1) return -1; AdjustEndianess16((LPBYTE) &Language); - Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc); + if (Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc) != 1) return -1; AdjustEndianess16((LPBYTE) &Country); - Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc); + if (Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1; AdjustEndianess32((LPBYTE) &ThisLen); - Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc); + if (Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc) != 1) return -1; AdjustEndianess32((LPBYTE) &ThisOffset); if (Language == GlobalLanguageCode || Offset == 0) { @@ -1492,14 +1658,18 @@ for (i=0; i < Offset; i++) { char Discard; - - Icc ->Read(&Discard, 1, 1, Icc); + if (Icc ->Read(&Discard, 1, 1, Icc) != 1) return -1; } - wchar = (wchar_t*) malloc(Len+2); + + // Bound len + if (Len < 0) Len = 0; + if (Len > 20*1024) Len = 20 * 1024; + + wchar = (wchar_t*) _cmsMalloc(Len*sizeof(wchar_t)+2); if (!wchar) return -1; - Icc ->Read(wchar, 1, Len, Icc); + if (Icc ->Read(wchar, 1, Len, Icc) != Len) return -1; AdjustEndianessArray16((LPWORD) wchar, Len / 2); wchar[Len / 2] = L'\0'; @@ -1509,7 +1679,7 @@ Name[0] = 0; // Error } - free((void*) wchar); + _cmsFree((void*) wchar); } break; @@ -1522,8 +1692,7 @@ } -// Take an ASCII item. Takes at most LCMS_DESC_MAX - +// Take an ASCII item. Takes at most size_max bytes int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Name, size_t size_max) { @@ -1535,19 +1704,27 @@ if (n < 0) return -1; - if (!Icc -> stream) { - - CopyMemory(Name, Icc -> TagPtrs[n], Icc -> TagSizes[n]); + size = Icc -> TagSizes[n]; + + if (Icc -> TagPtrs[n]) { + + if (size > size_max) + size = size_max; + + CopyMemory(Name, Icc -> TagPtrs[n], size); + return (int) Icc -> TagSizes[n]; } offset = Icc -> TagOffsets[n]; - size = Icc -> TagSizes[n]; + if (Icc -> Seek(Icc, offset)) return -1; - return ReadEmbeddedTextTag(Icc, size, Name, size_max); + if (ReadEmbeddedTextTag(Icc, size, Name, size_max) < 0) return -1; + + return size; } // Keep compatibility with older versions @@ -1561,7 +1738,7 @@ // Take an XYZ item static -int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, BOOL lIsFatal) +int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, LCMSBOOL lIsFatal) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; icTagTypeSignature BaseType; @@ -1573,7 +1750,7 @@ if (n < 0) return -1; - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { CopyMemory(Value, Icc -> TagPtrs[n], Icc -> TagSizes[n]); return (int) Icc -> TagSizes[n]; @@ -1628,7 +1805,7 @@ if (n < 0) return -1; // Not found - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { CopyMemory(v, Icc -> TagPtrs[n], Icc -> TagSizes[n]); return (int) Icc -> TagSizes[n]; @@ -1677,7 +1854,7 @@ // Primaries are to be in xyY notation -BOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile) { if (ReadICCXYZ(hProfile, icSigRedColorantTag, &Dest -> Red, TRUE) < 0) return FALSE; if (ReadICCXYZ(hProfile, icSigGreenColorantTag, &Dest -> Green, TRUE) < 0) return FALSE; @@ -1687,7 +1864,7 @@ } -BOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile) +LCMSBOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile) { cmsCIEXYZTRIPLE Primaries; @@ -1704,7 +1881,7 @@ // Always return a suitable matrix -BOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile) +LCMSBOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile) { if (ReadICCXYZArray(hProfile, icSigChromaticAdaptationTag, r) < 0) { @@ -1741,7 +1918,7 @@ if (n < 0) return NULL; - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { return cmsDupGamma((LPGAMMATABLE) Icc -> TagPtrs[n]); } @@ -1769,7 +1946,7 @@ if (n < 0) return NULL; - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { return cmsReverseGamma(256, (LPGAMMATABLE) Icc -> TagPtrs[n]); } @@ -1785,7 +1962,7 @@ // Check Named color header static -BOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2) +LCMSBOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2) { if (v ->Prefix[0] == 0 && v ->Suffix[0] == 0 && v ->ColorantCount == 0) return TRUE; @@ -1809,13 +1986,13 @@ if (n < 0) return 0; - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { // This replaces actual named color list. size_t size = Icc -> TagSizes[n]; if (v ->NamedColorList) cmsFreeNamedColorList(v ->NamedColorList); - v -> NamedColorList = (LPcmsNAMEDCOLORLIST) malloc(size); + v -> NamedColorList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size); CopyMemory(v -> NamedColorList, Icc ->TagPtrs[n], size); return v ->NamedColorList->nColors; } @@ -1844,7 +2021,7 @@ icNamedColor2 nc2; unsigned int i, j; - Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc); + if (Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return 0; AdjustEndianess32((LPBYTE) &nc2.vendorFlag); AdjustEndianess32((LPBYTE) &nc2.count); AdjustEndianess32((LPBYTE) &nc2.nDeviceCoords); @@ -1854,6 +2031,11 @@ return 0; } + if (nc2.nDeviceCoords > MAXCHANNELS) { + cmsSignalError(LCMS_ERRC_WARNING, "Too many device coordinates."); + return 0; + } + strncpy(v ->NamedColorList->Prefix, (const char*) nc2.prefix, 32); strncpy(v ->NamedColorList->Suffix, (const char*) nc2.suffix, 32); v ->NamedColorList->Prefix[32] = v->NamedColorList->Suffix[32] = 0; @@ -1900,7 +2082,8 @@ LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagSignature sig) { - icInt32Number n, Count, i; + icInt32Number n; + icUInt32Number Count, i; size_t offset; icTagTypeSignature BaseType; LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -1910,10 +2093,12 @@ if (n < 0) return NULL; // Not found - if (!Icc -> stream) { + if (Icc -> TagPtrs[n]) { size_t size = Icc -> TagSizes[n]; - void* v = malloc(size); + void* v = _cmsMalloc(size); + + if (v == NULL) return NULL; CopyMemory(v, Icc -> TagPtrs[n], size); return (LPcmsNAMEDCOLORLIST) v; } @@ -1932,13 +2117,17 @@ } - Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc); + if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL; AdjustEndianess32((LPBYTE) &Count); + if (Count > MAXCHANNELS) { + cmsSignalError(LCMS_ERRC_ABORTED, "Too many colorants '%lx'", Count); + return NULL; + } + List = cmsAllocNamedColorList(Count); for (i=0; i < Count; i++) { - if (!Icc ->Read(List->List[i].Name, 1, 32 , Icc)) goto Error; if (!Icc ->Read(List->List[i].PCS, sizeof(icUInt16Number), 3, Icc)) goto Error; AdjustEndianessArray16(List->List[i].PCS, 3); @@ -1965,7 +2154,7 @@ if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) { - cmsReadICCText(hProfile, icSigDeviceMfgDescTag, Manufacturer); + cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX); } return Manufacturer; @@ -1982,7 +2171,7 @@ if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) { - cmsReadICCText(hProfile, icSigDeviceModelDescTag, Model); + cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX); } return Model; @@ -1995,10 +2184,9 @@ static char Copyright[LCMS_DESC_MAX] = ""; Copyright[0] = 0; - if (cmsIsTag(hProfile, icSigCopyrightTag)) { - cmsReadICCText(hProfile, icSigCopyrightTag, Copyright); + cmsReadICCTextEx(hProfile, icSigCopyrightTag, Copyright, LCMS_DESC_MAX); } return Copyright; @@ -2009,7 +2197,7 @@ const char* LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile) { - static char Name[2048]; + static char Name[LCMS_DESC_MAX*2+4]; char Manufacturer[LCMS_DESC_MAX], Model[LCMS_DESC_MAX]; Name[0] = '\0'; @@ -2017,19 +2205,19 @@ if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) { - cmsReadICCText(hProfile, icSigDeviceMfgDescTag, Manufacturer); + cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX); } if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) { - cmsReadICCText(hProfile, icSigDeviceModelDescTag, Model); + cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX); } if (!Manufacturer[0] && !Model[0]) { if (cmsIsTag(hProfile, icSigProfileDescriptionTag)) { - cmsReadICCText(hProfile, icSigProfileDescriptionTag, Name); + cmsReadICCTextEx(hProfile, icSigProfileDescriptionTag, Name, LCMS_DESC_MAX); return Name; } else return "{no name}"; @@ -2129,7 +2317,7 @@ // Extract the target data as a big string. Does not signal if tag is not present. -BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len) +LCMSBOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; int n; @@ -2142,7 +2330,11 @@ *len = Icc -> TagSizes[n]; - *Data = (char*) malloc(*len + 1); // Plus zero marker + + // Make sure that is reasonable (600K) + if (*len > 600*1024) *len = 600*1024; + + *Data = (char*) _cmsMalloc(*len + 1); // Plus zero marker if (!*Data) { @@ -2162,7 +2354,7 @@ -BOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; int n; @@ -2170,8 +2362,8 @@ n = _cmsSearchTag(Icc, icSigCalibrationDateTimeTag, FALSE); if (n < 0) return FALSE; - if (!Icc ->stream) - { + if (Icc ->TagPtrs[n]) { + CopyMemory(Dest, Icc ->TagPtrs[n], sizeof(struct tm)); } else @@ -2212,9 +2404,10 @@ size = Icc -> TagSizes[n]; if (size < 12) return NULL; - if (!Icc -> stream) { - - OutSeq = (LPcmsSEQ) malloc(size); + if (Icc -> TagPtrs[n]) { + + OutSeq = (LPcmsSEQ) _cmsMalloc(size); + if (OutSeq == NULL) return NULL; CopyMemory(OutSeq, Icc ->TagPtrs[n], size); return OutSeq; } @@ -2231,8 +2424,13 @@ Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc); AdjustEndianess32((LPBYTE) &Count); + if (Count > 1000) { + return NULL; + } + size = sizeof(int) + Count * sizeof(cmsPSEQDESC); - OutSeq = (LPcmsSEQ) malloc(size); + OutSeq = (LPcmsSEQ) _cmsMalloc(size); + if (OutSeq == NULL) return NULL; OutSeq ->n = Count; @@ -2268,181 +2466,11 @@ void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq) { if (pseq) - free(pseq); + _cmsFree(pseq); } -// Extended gamut -- an HP extension - - -LPcmsGAMUTEX LCMSEXPORT cmsReadExtendedGamut(cmsHPROFILE hProfile, int index) -{ - LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; - size_t size, offset; - icUInt32Number off_samp, off_desc, off_vc; - int n; - icTagTypeSignature BaseType; - icColorSpaceSignature CoordSig; - icUInt16Number Method, Usage; - icUInt32Number GamutCount, SamplesCount; - LPcmsGAMUTEX gex; - size_t Offsets[256]; - size_t i, Actual, Loc; - icS15Fixed16Number Num; - icUInt16Number Surround; - - - n = _cmsSearchTag(Icc, icSigHPGamutDescTag, FALSE); - if (n < 0) return NULL; - - if (!Icc ->stream) return NULL; // In memory is not supported - - // Read the header - - offset = Icc -> TagOffsets[n]; - - if (Icc -> Seek(Icc, offset)) - return NULL; - - // Here is the beginning of tag - Actual = Icc ->Tell(Icc); - - - BaseType = ReadBase(Icc); - - if (BaseType != icSigHPGamutDescType) { - cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature '%lx' found.", BaseType); - return NULL; - } - - - // Read the gamut descriptors count - Icc ->Read(&GamutCount, sizeof(icUInt32Number), 1, Icc); - AdjustEndianess32((LPBYTE) &GamutCount); - - - if (GamutCount >= 256) { - cmsSignalError(LCMS_ERRC_ABORTED, "Too many gamut structures '%d'.", GamutCount); - return NULL; - } - - // Read the directory - - for (i=0; i < GamutCount; i++) { - - Icc ->Read(&Offsets[i], sizeof(icUInt32Number), 1, Icc); - AdjustEndianess32((LPBYTE) &Offsets[i]); - } - - - // Is there such element? - if (index >= (int) GamutCount) return NULL; - Loc = Actual + Offsets[index]; - - - // Go to specified index - if (Icc -> Seek(Icc, Loc)) - return NULL; - - - // Read all members - Icc ->Read(&CoordSig, sizeof(icColorSpaceSignature), 1, Icc); - AdjustEndianess32((LPBYTE) &CoordSig); - - Icc ->Read(&Method, sizeof(icUInt16Number), 1, Icc); - AdjustEndianess16((LPBYTE) &Method); - - Icc ->Read(&Usage, sizeof(icUInt16Number), 1, Icc); - AdjustEndianess16((LPBYTE) &Usage); - - Icc ->Read(&SamplesCount, sizeof(icUInt32Number), 1, Icc); - AdjustEndianess32((LPBYTE) &SamplesCount); - - Icc ->Read(&off_samp, sizeof(icUInt32Number), 1, Icc); - AdjustEndianess32((LPBYTE) &off_samp); - - Icc ->Read(&off_desc, sizeof(icUInt32Number), 1, Icc); - AdjustEndianess32((LPBYTE) &off_desc); - - Icc ->Read(&off_vc, sizeof(icUInt32Number), 1, Icc); - AdjustEndianess32((LPBYTE) &off_vc); - - - size = sizeof(cmsGAMUTEX) + (SamplesCount - 1) * sizeof(double); - - gex = (LPcmsGAMUTEX) malloc(size); - if (gex == NULL) return NULL; - - - gex ->CoordSig = CoordSig; - gex ->Method = Method; - gex ->Usage = Usage; - gex ->Count = SamplesCount; - - - // Read data - if (Icc -> Seek(Icc, Loc + off_samp)) - return NULL; - - for (i=0; i < SamplesCount; i++) { - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Data[i] = Convert15Fixed16(Num); - } - - - // Read mluc - if (Icc -> Seek(Icc, Loc + off_desc)) { - - free(gex); - return NULL; - } - - ReadEmbeddedTextTag(Icc, 256, gex ->Description, LCMS_DESC_MAX); - - - // Read viewing conditions - if (Icc -> Seek(Icc, Loc + off_vc)) { - free(gex); - return NULL; - } - - - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Vc.whitePoint.X = Convert15Fixed16(Num); - - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Vc.whitePoint.Y = Convert15Fixed16(Num); - - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Vc.whitePoint.Z = Convert15Fixed16(Num); - - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Vc.La = Convert15Fixed16(Num); - - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Vc.Yb = Convert15Fixed16(Num); - - Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc); - gex ->Vc.D_value = Convert15Fixed16(Num); - - Icc -> Read(&Surround, sizeof(icUInt16Number), 1, Icc); - AdjustEndianess16((LPBYTE) &Surround); - gex ->Vc.surround = Surround; - - - // All OK - return gex; - -} - - - -void LCMSEXPORT cmsFreeExtendedGamut(LPcmsGAMUTEX gex) -{ - if (gex) - free(gex); -} // Read a few tags that are hardly required @@ -2564,6 +2592,7 @@ NewIcc = (LPLCMSICCPROFILE) (LPSTR) hEmpty; NewIcc -> IsWrite = TRUE; strncpy(NewIcc ->PhysicalFile, lpFileName, MAX_PATH-1); + NewIcc ->PhysicalFile[MAX_PATH-1] = 0; // Save LUT as 8 bit @@ -2609,14 +2638,14 @@ -BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; - BOOL rc = TRUE; + LCMSBOOL rc = TRUE; + icInt32Number i; if (!Icc) return FALSE; - // Was open in write mode? if (Icc ->IsWrite) { @@ -2624,21 +2653,15 @@ rc = _cmsSaveProfile(hProfile, Icc ->PhysicalFile); } - - if (Icc -> stream == NULL) { // Was a memory (i.e. not serialized) profile? - - - icInt32Number i; // Yes, free tags - - for (i=0; i < Icc -> TagCount; i++) { + for (i=0; i < Icc -> TagCount; i++) { if (Icc -> TagPtrs[i]) free(Icc -> TagPtrs[i]); - } - } - else Icc -> Close(Icc); // No, close the stream - + + if (Icc -> stream != NULL) { // Was a memory (i.e. not serialized) profile? + Icc -> Close(Icc); // No, close the stream + } free(Icc); // Free placeholder memory @@ -2652,11 +2675,11 @@ static -BOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc) { size_t nTabSize = sizeof(WORD) * nEntries; - LPWORD PtrW = (LPWORD) malloc(nTabSize); - BOOL rc; + LPWORD PtrW = (LPWORD) _cmsMalloc(nTabSize); + LCMSBOOL rc; if (!PtrW) return FALSE; CopyMemory(PtrW, Tab, nTabSize); @@ -2672,7 +2695,7 @@ // Saves profile header static -BOOL SaveHeader(LPLCMSICCPROFILE Icc) +LCMSBOOL SaveHeader(LPLCMSICCPROFILE Icc) { icHeader Header; time_t now = time(NULL); @@ -2727,7 +2750,7 @@ // Setup base marker static -BOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc) +LCMSBOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc) { icTagBase Base; @@ -2737,10 +2760,10 @@ } -// Store an XYZ tag +// Store a XYZ tag static -BOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc) { icXYZNumber XYZ; @@ -2756,72 +2779,97 @@ } +// Store a XYZ array. + +static +LCMSBOOL SaveXYZArray(int n, LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc) +{ + int i; + icXYZNumber XYZ; + + if (!SetupBase(icSigS15Fixed16ArrayType, Icc)) return FALSE; + + for (i=0; i < n; i++) { + + XYZ.X = TransportValue32(DOUBLE_TO_FIXED(Value -> X)); + XYZ.Y = TransportValue32(DOUBLE_TO_FIXED(Value -> Y)); + XYZ.Z = TransportValue32(DOUBLE_TO_FIXED(Value -> Z)); + + if (!Icc -> Write(Icc, sizeof(icXYZNumber), &XYZ)) return FALSE; + + Value++; + } + + return TRUE; +} + + // Save a gamma structure as a table static -BOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) { - icInt32Number Count; - - if (!SetupBase(icSigCurveType, Icc)) return FALSE; - - Count = TransportValue32(Gamma->nEntries); - - if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE; - - return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc); + icInt32Number Count; + + if (!SetupBase(icSigCurveType, Icc)) return FALSE; + + Count = TransportValue32(Gamma->nEntries); + + if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE; + + return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc); } // Save a gamma structure as a one-value static -BOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) { - icInt32Number Count; - Fixed32 GammaFixed32; - WORD GammaFixed8; - - if (!SetupBase(icSigCurveType, Icc)) return FALSE; - - Count = TransportValue32(1); - if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE; - - GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]); - GammaFixed8 = (WORD) ((GammaFixed32 >> 8) & 0xFFFF); - GammaFixed8 = TransportValue16(GammaFixed8); - - return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8); + icInt32Number Count; + Fixed32 GammaFixed32; + WORD GammaFixed8; + + if (!SetupBase(icSigCurveType, Icc)) return FALSE; + + Count = TransportValue32(1); + if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE; + + GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]); + GammaFixed8 = (WORD) ((GammaFixed32 >> 8) & 0xFFFF); + GammaFixed8 = TransportValue16(GammaFixed8); + + return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8); } // Save a gamma structure as a parametric gamma static -BOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) { - icUInt16Number Type, Reserved; - int i, nParams; - int ParamsByType[] = { 1, 3, 4, 5, 7 }; - - if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE; - - nParams = ParamsByType[Gamma -> Seed.Type]; - - Type = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type); - Reserved = (icUInt16Number) TransportValue16((WORD) 0); - - Icc -> Write(Icc, sizeof(icInt16Number), &Type); - Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved); - - for (i=0; i < nParams; i++) { - - icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i])); - Icc ->Write(Icc, sizeof(icInt32Number), &val); - } - - - return TRUE; + icUInt16Number Type, Reserved; + int i, nParams; + int ParamsByType[] = { 1, 3, 4, 5, 7 }; + + if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE; + + nParams = ParamsByType[Gamma -> Seed.Type]; + + Type = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type); + Reserved = (icUInt16Number) TransportValue16((WORD) 0); + + Icc -> Write(Icc, sizeof(icInt16Number), &Type); + Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved); + + for (i=0; i < nParams; i++) { + + icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i])); + Icc ->Write(Icc, sizeof(icInt32Number), &val); + } + + + return TRUE; } @@ -2829,29 +2877,29 @@ // Save a gamma table static -BOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc) { - // Is the gamma curve type supported by ICC format? - - if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 || - - // has been modified by user? - - _cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) { - - return SaveGammaTable(Gamma, Icc); - } - - if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc); - - // Only v4 profiles are allowed to hold parametric curves - - if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000) - return SaveGammaParametric(Gamma, Icc); - - // Defaults to save as table - - return SaveGammaTable(Gamma, Icc); + // Is the gamma curve type supported by ICC format? + + if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 || + + // has been modified by user? + + _cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) { + + return SaveGammaTable(Gamma, Icc); + } + + if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc); + + // Only v4 profiles are allowed to hold parametric curves + + if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000) + return SaveGammaParametric(Gamma, Icc); + + // Defaults to save as table + + return SaveGammaTable(Gamma, Icc); } @@ -2861,7 +2909,7 @@ // Save an DESC Tag static -BOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc) { icUInt32Number len, Count, TotalSize, AlignedSize; @@ -2893,6 +2941,11 @@ if (!Icc ->Write(Icc, len, (LPVOID)Text)) return FALSE; AlignedSize -= len; + if (AlignedSize < 0) + AlignedSize = 0; + if (AlignedSize > 255) + AlignedSize = 255; + ZeroMemory(Filler, AlignedSize); if (!Icc ->Write(Icc, AlignedSize, Filler)) return FALSE; @@ -2902,7 +2955,7 @@ // Save an ASCII Tag static -BOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc) { size_t len = strlen(Text) + 1; @@ -2915,7 +2968,7 @@ // Save one of these new chromaticity values static -BOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc) { Fixed32 xf, yf; @@ -2932,7 +2985,7 @@ // New tag added in Addendum II of old spec. static -BOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc) { WORD nChans, Table; @@ -2952,7 +3005,7 @@ static -BOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc) { icUInt32Number nSeqs; icDescStruct DescStruct; @@ -2989,7 +3042,7 @@ // Saves a timestamp tag static -BOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc) { icDateTimeNumber Dest; @@ -3003,14 +3056,14 @@ // Saves a named color list into a named color profile static -BOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc) { icUInt32Number vendorFlag; // Bottom 16 bits for IC use icUInt32Number count; // Count of named colors icUInt32Number nDeviceCoords; // Num of device coordinates - icInt8Number prefix[32]; // Prefix for each color name - icInt8Number suffix[32]; // Suffix for each color name + char prefix[32]; // Prefix for each color name + char suffix[32]; // Suffix for each color name int i; if (!SetupBase(icSigNamedColor2Type, Icc)) return FALSE; @@ -3019,8 +3072,10 @@ count = TransportValue32(NamedColorList ->nColors); nDeviceCoords = TransportValue32(NamedColorList ->ColorantCount); - strncpy(prefix, (const char*) NamedColorList->Prefix, 32); - strncpy(suffix, (const char*) NamedColorList->Suffix, 32); + strncpy(prefix, (const char*) NamedColorList->Prefix, 31); + strncpy(suffix, (const char*) NamedColorList->Suffix, 31); + + suffix[31] = prefix[31] = 0; if (!Icc ->Write(Icc, sizeof(icUInt32Number), &vendorFlag)) return FALSE; if (!Icc ->Write(Icc, sizeof(icUInt32Number), &count)) return FALSE; @@ -3030,15 +3085,17 @@ for (i=0; i < NamedColorList ->nColors; i++) { - icUInt16Number PCS[3]; - icUInt16Number Colorant[MAXCHANNELS]; - icInt8Number root[32]; + icUInt16Number PCS[3]; + icUInt16Number Colorant[MAXCHANNELS]; + char root[32]; LPcmsNAMEDCOLOR Color; int j; Color = NamedColorList ->List + i; - strncpy((char*) root, Color ->Name, 32); + strncpy(root, Color ->Name, 32); + Color ->Name[32] = 0; + if (!Icc ->Write(Icc, 32 , root)) return FALSE; for (j=0; j < 3; j++) @@ -3062,7 +3119,7 @@ // Saves a colorant table. It is using the named color structure for simplicity sake static -BOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc) { icUInt32Number count; // Count of named colors int i; @@ -3076,13 +3133,15 @@ for (i=0; i < NamedColorList ->nColors; i++) { icUInt16Number PCS[3]; - icInt8Number root[32]; + icInt8Number root[33]; LPcmsNAMEDCOLOR Color; int j; Color = NamedColorList ->List + i; strncpy((char*) root, Color ->Name, 32); + root[32] = 0; + if (!Icc ->Write(Icc, 32 , root)) return FALSE; for (j=0; j < 3; j++) @@ -3099,7 +3158,7 @@ // Does serialization of LUT16 and writes it. static -BOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc) { icLut16 LUT16; unsigned int i; @@ -3189,7 +3248,7 @@ // Does serialization of LUT8 and writes it static -BOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc) +LCMSBOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc) { icLut8 LUT8; unsigned int i, j; @@ -3323,7 +3382,7 @@ // Saves Tag directory static -BOOL SaveTagDirectory(LPLCMSICCPROFILE Icc) +LCMSBOOL SaveTagDirectory(LPLCMSICCPROFILE Icc) { icInt32Number i; icTag Tag; @@ -3356,7 +3415,7 @@ // Dump tag contents static -BOOL SaveTags(LPLCMSICCPROFILE Icc) +LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc, LPLCMSICCPROFILE FileOrig) { LPBYTE Data; @@ -3384,8 +3443,31 @@ Icc -> TagOffsets[i] = Begin = Icc ->UsedSpace; Data = (LPBYTE) Icc -> TagPtrs[i]; - if (!Data) + if (!Data) { + + // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user. + // In this case a blind copy of the block data is performed + + if (Icc -> TagOffsets[i]) { + + size_t TagSize = FileOrig -> TagSizes[i]; + size_t TagOffset = FileOrig -> TagOffsets[i]; + void* Mem; + + if (FileOrig ->Seek(FileOrig, TagOffset)) return FALSE; + + Mem = _cmsMalloc(TagSize); + + if (FileOrig ->Read(Mem, TagSize, 1, FileOrig) != 1) return FALSE; + if (!Icc ->Write(Icc, TagSize, Mem)) return FALSE; + + Icc -> TagSizes[i] = (Icc ->UsedSpace - Begin); + free(Mem); + } + continue; + } + switch (Icc -> TagNames[i]) { @@ -3464,6 +3546,10 @@ break; + case icSigChromaticAdaptationTag: + if (!SaveXYZArray(3, (LPcmsCIEXYZ) Data, Icc)) return FALSE; + break; + default: return FALSE; } @@ -3480,9 +3566,9 @@ // Add tags to profile structure -BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag) +LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag) { - BOOL rc; + LCMSBOOL rc; switch (sig) { @@ -3543,6 +3629,11 @@ rc = _cmsAddColorantTableTag(hProfile, sig, (LPcmsNAMEDCOLORLIST) Tag); break; + + case icSigChromaticAdaptationTag: + rc = _cmsAddChromaticAdaptationTag(hProfile, sig, (const cmsCIEXYZ*) Tag); + break; + default: cmsSignalError(LCMS_ERRC_ABORTED, "cmsAddTag: Tag '%x' is unsupported", sig); return FALSE; @@ -3568,11 +3659,11 @@ // Low-level save to disk. It closes the profile on exit -BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName) +LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; LCMSICCPROFILE Keep; - BOOL rc; + LCMSBOOL rc; CopyMemory(&Keep, Icc, sizeof(LCMSICCPROFILE)); _cmsSetSaveToDisk(Icc, NULL); @@ -3581,7 +3672,7 @@ if (!SaveHeader(Icc)) return FALSE; if (!SaveTagDirectory(Icc)) return FALSE; - if (!SaveTags(Icc)) return FALSE; + if (!SaveTags(Icc, &Keep)) return FALSE; _cmsSetSaveToDisk(Icc, FileName); @@ -3591,7 +3682,7 @@ if (!SaveHeader(Icc)) goto CleanUp; if (!SaveTagDirectory(Icc)) goto CleanUp; - if (!SaveTags(Icc)) goto CleanUp; + if (!SaveTags(Icc, &Keep)) goto CleanUp; rc = (Icc ->Close(Icc) == 0); CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); @@ -3608,7 +3699,7 @@ // Low-level save from open stream -BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, +LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, size_t* BytesNeeded) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; @@ -3623,20 +3714,20 @@ if (!SaveHeader(Icc)) return FALSE; if (!SaveTagDirectory(Icc)) return FALSE; - if (!SaveTags(Icc)) return FALSE; + if (!SaveTags(Icc, &Keep)) return FALSE; if (!MemPtr) { // update BytesSaved so caller knows how many bytes are needed for MemPtr *BytesNeeded = Icc ->UsedSpace; - CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); + CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); return TRUE; } if (*BytesNeeded < Icc ->UsedSpace) { // need at least UsedSpace in MemPtr to continue - CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); + CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); return FALSE; } @@ -3646,7 +3737,7 @@ // Pass #2 does save to file into supplied stream if (!SaveHeader(Icc)) goto CleanUp; if (!SaveTagDirectory(Icc)) goto CleanUp; - if (!SaveTags(Icc)) goto CleanUp; + if (!SaveTags(Icc, &Keep)) goto CleanUp; // update BytesSaved so caller knows how many bytes put into stream *BytesNeeded = Icc ->UsedSpace; @@ -3661,3 +3752,4 @@ CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE)); return FALSE; } + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmslut.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -118,7 +118,7 @@ { LPLUT NewLUT; - NewLUT = (LPLUT) malloc(sizeof(LUT)); + NewLUT = (LPLUT) _cmsMalloc(sizeof(LUT)); if (NewLUT) ZeroMemory(NewLUT, sizeof(LUT)); @@ -171,9 +171,10 @@ static LPVOID DupBlockTab(LPVOID Org, size_t size) { - LPVOID mem = malloc(size); + LPVOID mem = _cmsMalloc(size); + if (mem != NULL) + CopyMemory(mem, Org, size); - CopyMemory(mem, Org, size); return mem; } @@ -211,6 +212,37 @@ } +LCMSBOOL _cmsValidateLUT(LPLUT NewLUT) +{ + unsigned int calc = 1; + unsigned int oldCalc; + unsigned int power = NewLUT -> InputChan; + + if (NewLUT -> cLutPoints > 100) return FALSE; + if (NewLUT -> InputChan > MAXCHANNELS) return FALSE; + if (NewLUT -> OutputChan > MAXCHANNELS) return FALSE; + + if (NewLUT -> cLutPoints == 0) return TRUE; + + for (; power > 0; power--) { + + oldCalc = calc; + calc *= NewLUT -> cLutPoints; + + if (calc / NewLUT -> cLutPoints != oldCalc) { + return FALSE; + } + } + + oldCalc = calc; + calc *= NewLUT -> OutputChan; + if (NewLUT -> OutputChan && calc / NewLUT -> OutputChan != oldCalc) { + return FALSE; + } + + return TRUE; +} + LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int outputChan) { DWORD nTabSize; @@ -220,12 +252,17 @@ NewLUT -> InputChan = inputChan; NewLUT -> OutputChan = outputChan; + if (!_cmsValidateLUT(NewLUT)) { + return NULL; + } - nTabSize = (NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints, - NewLUT->InputChan) - * sizeof(WORD)); + nTabSize = NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints, + NewLUT->InputChan); - NewLUT -> T = (LPWORD) malloc(nTabSize); + NewLUT -> T = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize); + nTabSize *= sizeof(WORD); + if (NewLUT -> T == NULL) return NULL; + ZeroMemory(NewLUT -> T, nTabSize); NewLUT ->Tsize = nTabSize; @@ -254,10 +291,12 @@ for (i=0; i < NewLUT -> InputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> InputEntries); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries); + if (PtrW == NULL) return NULL; + NewLUT -> L1[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> InputEntries); - CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); + CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); } @@ -268,10 +307,12 @@ NewLUT -> OutputEntries = Tables[0] -> nEntries; for (i=0; i < NewLUT -> OutputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> OutputEntries); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries); + if (PtrW == NULL) return NULL; + NewLUT -> L2[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> OutputEntries); - CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); + CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); } break; @@ -285,10 +326,12 @@ for (i=0; i < NewLUT -> InputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L3Entries); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L3Entries); + if (PtrW == NULL) return NULL; + NewLUT -> L3[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L3Entries); - CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); + CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); } break; @@ -298,10 +341,12 @@ NewLUT -> L4Entries = Tables[0] -> nEntries; for (i=0; i < NewLUT -> OutputChan; i++) { - PtrW = (LPWORD) malloc(sizeof(WORD) * NewLUT -> L4Entries); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L4Entries); + if (PtrW == NULL) return NULL; + NewLUT -> L4[i] = PtrW; CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L4Entries); - CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); + CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS)); } break; @@ -580,7 +625,7 @@ LPL16PARAMS p = &Lut ->CLut16params; - p8 = (LPL8PARAMS) malloc(sizeof(L8PARAMS)); + p8 = (LPL8PARAMS) _cmsMalloc(sizeof(L8PARAMS)); if (p8 == NULL) return NULL; // values comes * 257, so we can safely take first byte (x << 8 + x) @@ -593,8 +638,8 @@ if (Lut ->wFlags & LUT_HASTL1) { for (j=0; j < 3; j++) - StageABC[i] = cmsLinearInterpLUT16(StageABC[i], - Lut -> L1[i], + StageABC[j] = cmsLinearInterpLUT16(StageABC[j], + Lut -> L1[j], &Lut -> In16params); Lut ->wFlags &= ~LUT_HASTL1; } @@ -697,7 +742,7 @@ wIn[3] = FixedK; cmsEvalLUT(Lut, wIn, wOut); - cmsLabEncoded2Float(Out, wOut); + cmsLabEncoded2Float(Out, wOut); } // Builds a Jacobian CMY->Lab @@ -722,9 +767,9 @@ EvalLUTdoubleKLab(Lut, &ColorantD, K, &LabD); - Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON); - Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON); - Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON); + Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON); + Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON); + Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON); } } @@ -797,18 +842,18 @@ // Obtain slope ComputeJacobianLab(Lut, &Jacobian, &x, FixedK); - // Solve system - tmp2.n[0] = fx.L - Goal.L; - tmp2.n[1] = fx.a - Goal.a; - tmp2.n[2] = fx.b - Goal.b; + // Solve system + tmp2.n[0] = fx.L - Goal.L; + tmp2.n[1] = fx.a - Goal.a; + tmp2.n[2] = fx.b - Goal.b; - if (!MAT3solve(&tmp, &Jacobian, &tmp2)) - break; + if (!MAT3solve(&tmp, &Jacobian, &tmp2)) + break; // Move our guess - x.n[0] -= tmp.n[0]; - x.n[1] -= tmp.n[1]; - x.n[2] -= tmp.n[2]; + x.n[0] -= tmp.n[0]; + x.n[1] -= tmp.n[1]; + x.n[2] -= tmp.n[2]; // Some clipping.... VEC3saturate(&x); @@ -822,3 +867,6 @@ return LastError; } + + + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -62,6 +62,7 @@ // data yet in fixed point, so no additional process is required. // Then, we obtain data on 15.16, so we need to shift >> by 1 to // obtain 1.15 PCS format. + // On OUTPUT profiles, things are inverse, we must first expand 1 bit // by shifting left, and then convert result between 0 and 1.000 to // RGB, so FromFixedDomain() must be called before pass values to @@ -71,6 +72,7 @@ // input is encoded from 0 to 0xffff, we must first use the shaper and // then the matrix, an additional FromFixedDomain() must be used to // accomodate output values. + // For a sake of simplicity, I will handle this three behaviours // with different routines, so the flags MATSHAPER_INPUT and MATSHAPER_OUTPUT // can be conbined to signal smelted matrix-shapers @@ -89,7 +91,7 @@ { LPWORD PtrW; - PtrW = (LPWORD) malloc(sizeof(WORD) * p16 -> nSamples); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * p16 -> nSamples); if (PtrW == NULL) return -1; // Signal error @@ -119,7 +121,7 @@ LPMATSHAPER NewMatShaper; int rc; - NewMatShaper = (LPMATSHAPER) malloc(sizeof(MATSHAPER)); + NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER)); if (NewMatShaper) ZeroMemory(NewMatShaper, sizeof(MATSHAPER)); @@ -171,7 +173,13 @@ LPMATSHAPER NewMatShaper; int i, AllLinear; - NewMatShaper = (LPMATSHAPER) malloc(sizeof(MATSHAPER)); + if (Matrix == NULL) return NULL; + for (i=0; i < 3; i++) { + + if (Tables[i] == NULL) return NULL; + } + + NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER)); if (NewMatShaper) ZeroMemory(NewMatShaper, sizeof(MATSHAPER)); @@ -187,17 +195,16 @@ NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX; // Now, on the table characteristics - cmsCalcL16Params(Tables[0] -> nEntries, &NewMatShaper -> p16); // Copy tables AllLinear = 0; - for (i=0; i < 3; i++) - { + for (i=0; i < 3; i++) { + LPWORD PtrW; - PtrW = (LPWORD) malloc(sizeof(WORD) * NewMatShaper -> p16.nSamples); + PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewMatShaper -> p16.nSamples); if (PtrW == NULL) { cmsFreeMatShaper(NewMatShaper); @@ -235,11 +242,11 @@ for (i=0; i < 3; i++) { - if (MatShaper -> L[i]) free(MatShaper ->L[i]); - if (MatShaper -> L2[i]) free(MatShaper ->L2[i]); + if (MatShaper -> L[i]) _cmsFree(MatShaper ->L[i]); + if (MatShaper -> L2[i]) _cmsFree(MatShaper ->L2[i]); } - free(MatShaper); + _cmsFree(MatShaper); } diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -71,16 +71,16 @@ double cdecl VEC3distance(LPVEC3 a, LPVEC3 b); -void cdecl MAT3identity(LPMAT3 a); -void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b); -int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b); -BOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b); -double cdecl MAT3det(LPMAT3 m); -void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v); -void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v); -void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v); -void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d); -void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d); +void cdecl MAT3identity(LPMAT3 a); +void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b); +int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b); +LCMSBOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b); +double cdecl MAT3det(LPMAT3 m); +void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v); +void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v); +void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v); +void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d); +void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d); // --------------------- Implementation ---------------------------- @@ -345,13 +345,13 @@ // Check id two vectors are the same, allowing tolerance static -BOOL RangeCheck(double l, double h, double v) +LCMSBOOL RangeCheck(double l, double h, double v) { return (v >= l && v <= h); } -BOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance) +LCMSBOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance) { int i; double c; @@ -367,7 +367,7 @@ return TRUE; } -BOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance) +LCMSBOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance) { int i; double c; @@ -462,7 +462,7 @@ // Check if matrix is Identity. Allow a tolerance as % -BOOL MAT3isIdentity(LPWMAT3 a, double Tolerance) +LCMSBOOL MAT3isIdentity(LPWMAT3 a, double Tolerance) { int i; MAT3 Idd; @@ -545,16 +545,16 @@ // Solve a system in the form Ax = b -BOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b) +LCMSBOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b) { - MAT3 m, a_1; + MAT3 m, a_1; - CopyMemory(&m, a, sizeof(MAT3)); + CopyMemory(&m, a, sizeof(MAT3)); - if (!MAT3inverse(&m, &a_1)) return FALSE; // Singular matrix + if (!MAT3inverse(&m, &a_1)) return FALSE; // Singular matrix - MAT3eval(x, &a_1, b); - return TRUE; + MAT3eval(x, &a_1, b); + return TRUE; } @@ -839,3 +839,7 @@ VEC3scaleAndCut(&r -> v[1], &v -> v[1], d); VEC3scaleAndCut(&r -> v[2], &v -> v[2], d); } + + + + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -74,7 +74,7 @@ NewElements *= 2; size = sizeof(cmsNAMEDCOLORLIST) + (sizeof(cmsNAMEDCOLOR) * NewElements); - TheNewList = (LPcmsNAMEDCOLORLIST) malloc(size); + TheNewList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size); if (TheNewList == NULL) { @@ -86,7 +86,7 @@ CopyMemory(TheNewList, v, sizeof(cmsNAMEDCOLORLIST) + (v ->nColors - 1) * sizeof(cmsNAMEDCOLOR)); TheNewList -> Allocated = NewElements; - free(v); + _cmsFree(v); return TheNewList; } } @@ -99,7 +99,7 @@ { size_t size = sizeof(cmsNAMEDCOLORLIST) + (n - 1) * sizeof(cmsNAMEDCOLOR); - LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) malloc(size); + LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size); if (v == NULL) { @@ -124,10 +124,10 @@ return; } - free(v); + _cmsFree(v); } -BOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]) +LCMSBOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]) { _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform; LPcmsNAMEDCOLORLIST List; @@ -146,6 +146,7 @@ List ->List[List ->nColors].PCS[i] = PCS[i]; strncpy(List ->List[List ->nColors].Name, Name, MAX_PATH-1); + List ->List[List ->nColors].Name[MAX_PATH-1] = 0; List ->nColors++; return TRUE; @@ -164,18 +165,17 @@ } -BOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix) +LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix) { _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform; - if (v ->NamedColorList == NULL) return FALSE; if (nColor < 0 || nColor >= cmsNamedColorCount(xform)) return FALSE; - if (Name) strncpy(Name, v ->NamedColorList->List[nColor].Name, 31); - if (Prefix) strncpy(Prefix, v ->NamedColorList->Prefix, 31); - if (Suffix) strncpy(Suffix, v ->NamedColorList->Suffix, 31); + if (Name) { strncpy(Name, v ->NamedColorList->List[nColor].Name, 31); Name[31] = 0; } + if (Prefix) { strncpy(Prefix, v ->NamedColorList->Prefix, 31); Prefix[31] = 0; } + if (Suffix) { strncpy(Suffix, v ->NamedColorList->Suffix, 31); Suffix[31] = 0; } return TRUE; } @@ -196,3 +196,5 @@ return -1; } + + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspack.c Tue Mar 24 09:14:02 2009 -0700 @@ -28,7 +28,7 @@ // file: // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -639,9 +639,81 @@ +static +LPBYTE UnrollDouble1Chan(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum) +{ + double* Inks = (double*) accum; + double v; + + + v = floor(Inks[0] * 65535.0 + 0.5); + + if (v > 65535.0) v = 65535.0; + if (v < 0) v = 0; + + + wIn[0] = wIn[1] = wIn[2] = (WORD) v; + + return accum + sizeof(double); +} + + // ----------------------------------------------------------- Packing routines +// Generic N-bytes plus dither 16-to-8 conversion. Currently is just a quick hack + +static int err[MAXCHANNELS]; + +static +LPBYTE PackNBytesDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + register int i; + unsigned int n, pe, pf; + + for (i=0; i < nChan; i++) { + + n = wOut[i] + err[i]; // Value + + pe = (n / 257); // Whole part + pf = (n % 257); // Fractional part + + err[i] = pf; // Store it for next pixel + + *output++ = (BYTE) pe; + } + + return output + T_EXTRA(info ->OutputFormat); +} + + + +static +LPBYTE PackNBytesSwapDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output) +{ + int nChan = T_CHANNELS(info -> OutputFormat); + register int i; + unsigned int n, pe, pf; + + for (i=nChan-1; i >= 0; --i) { + + n = wOut[i] + err[i]; // Value + + pe = (n / 257); // Whole part + pf = (n % 257); // Fractional part + + err[i] = pf; // Store it for next pixel + + *output++ = (BYTE) pe; + } + + + return output + T_EXTRA(info ->OutputFormat); +} + + + // Generic chunky for byte static @@ -1486,7 +1558,10 @@ case PT_HSV: case PT_HLS: case PT_Yxy: - FromInput = UnrollDouble; + if (T_CHANNELS(dwInput) == 1) + FromInput = UnrollDouble1Chan; + else + FromInput = UnrollDouble; break; // Inks (%) 0.0 .. 100.0 @@ -1749,6 +1824,9 @@ switch (T_CHANNELS(dwOutput)) { case 1: + if (T_DITHER(dwOutput)) + ToOutput = PackNBytesDither; + else ToOutput = Pack1Byte; if (T_EXTRA(dwOutput) == 1) { if (T_SWAPFIRST(dwOutput)) @@ -1766,8 +1844,12 @@ else if (T_COLORSPACE(dwOutput) == PT_Lab) ToOutput = Pack3BytesLab; + else { + if (T_DITHER(dwOutput)) + ToOutput = PackNBytesDither; else ToOutput = Pack3Bytes; + } break; case 1: // TODO: ALab8 should be handled here @@ -1793,13 +1875,23 @@ case 4: if (T_EXTRA(dwOutput) == 0) { + if (T_DOSWAP(dwOutput)) { - if (T_SWAPFIRST(dwOutput)) + + if (T_SWAPFIRST(dwOutput)) { ToOutput = Pack4BytesSwapSwapFirst; - else + } + else { + + if (T_DITHER(dwOutput)) { + ToOutput = PackNBytesSwapDither; + } + else { ToOutput = Pack4BytesSwap; } + } + } else { if (T_SWAPFIRST(dwOutput)) ToOutput = Pack4BytesSwapFirst; @@ -1807,11 +1899,15 @@ if (T_FLAVOR(dwOutput)) ToOutput = Pack4BytesReverse; + else { + if (T_DITHER(dwOutput)) + ToOutput = PackNBytesDither; else ToOutput = Pack4Bytes; } } } + } else { if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput)) ToOutput = PackNBytes; @@ -1833,7 +1929,7 @@ } break; - case 2: + case 2: case 5: case 7: case 8: @@ -1849,8 +1945,13 @@ { if (T_DOSWAP(dwOutput)) ToOutput = PackNBytesSwap; + else { + + if (T_DITHER(dwOutput)) + ToOutput = PackNBytesDither; else ToOutput = PackNBytes; + } } break; @@ -1984,7 +2085,7 @@ break; - case 2: + case 2: case 5: case 7: case 8: diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmspcs.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -624,3 +624,7 @@ fXYZ -> Z = XYZ2float(XYZ[2]); } + + + + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsps2.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -144,6 +144,8 @@ /Table [ p p p [<...>]] /RangeABC [ 0 1 0 1 0 1] /DecodeABC[ ] + /RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ] + % -128/500 1+127/500 0 1 -127/200 1+128/200 /MatrixABC [ 1 1 1 1 0 0 0 0 -1] /WhitePoint [D50] /BlackPoint [BP] @@ -347,7 +349,8 @@ static LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols) { - LPMEMSTREAM m = (LPMEMSTREAM) malloc(sizeof(MEMSTREAM)); + LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM)); + if (m == NULL) return NULL; ZeroMemory(m, sizeof(MEMSTREAM)); @@ -376,9 +379,9 @@ static BYTE L2Byte(WORD w) { - int ww = w + 0x0080; + int ww = w + 0x0080; - if (ww > 0xFFFF) return 0xFF; + if (ww > 0xFFFF) return 0xFF; return (BYTE) ((WORD) (ww >> 8) & 0xFF); } @@ -387,7 +390,6 @@ static void WriteRawByte(LPMEMSTREAM m, BYTE b) { - if (m -> dwUsed + 1 > m -> dwMax) { m -> HasError = 1; } @@ -422,7 +424,7 @@ } -// Does write a formatted string +// Does write a formatted string. Guaranteed to be 2048 bytes at most. static void Writef(LPMEMSTREAM m, const char *frm, ...) { @@ -432,7 +434,7 @@ va_start(args, frm); - vsprintf((char*) Buffer, frm, args); + vsnprintf((char*) Buffer, 2048, frm, args); for (pt = Buffer; *pt; pt++) { @@ -562,7 +564,7 @@ Writef(m, "{255 mul 128 sub 200 div } bind\n"); Writef(m, "]\n"); Writef(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n"); - Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n"); + Writef(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n"); Writef(m, "/DecodeLMN [\n"); Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n"); Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n"); @@ -584,7 +586,11 @@ if (nEntries <= 0) return; // Empty table // Suppress whole if identity - if (cmsIsLinear(Table, nEntries)) return; + if (cmsIsLinear(Table, nEntries)) { + Writef(m, "{} "); + return; + } + // Check if is really an exponential. If so, emit "exp" gamma = cmsEstimateGammaEx(Table, nEntries, 0.001); @@ -646,7 +652,7 @@ // Compare gamma table static -BOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries) +LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries) { return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0; } @@ -676,7 +682,7 @@ // Check whatever a profile has CLUT tables (only on input) static -BOOL IsLUTbased(cmsHPROFILE hProfile, int Intent) +LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent) { icTagSignature Tag; @@ -718,10 +724,10 @@ if (sc -> FixWhite) { - if (In[0] == 0xFFFF) { // Only in L* = 100 + if (In[0] == 0xFFFF) { // Only in L* = 100, ab = [-8..8] - if ((In[1] >= 0x8000 && In[1] <= 0x87FF) || - (In[2] >= 0x8000 && In[2] <= 0x87FF)) { + if ((In[1] >= 0x7800 && In[1] <= 0x8800) && + (In[2] >= 0x7800 && In[2] <= 0x8800)) { WORD* Black; WORD* White; @@ -829,8 +835,8 @@ sc.PreMaj = PreMaj; sc.PostMaj= PostMaj; - sc.PreMin = PreMin; - sc.PostMin= PostMin; + sc.PreMin = PreMin; + sc.PostMin = PostMin; sc.lIsInput = lIsInput; sc.FixWhite = FixWhite; sc.ColorSpace = ColorSpace; @@ -1231,7 +1237,7 @@ if (!WriteNamedColorCSA(mem, hProfile, Intent)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1246,7 +1252,7 @@ ColorSpace != icSigLabData) { cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space"); - free((void*) mem); + _cmsFree((void*) mem); return 0; } @@ -1256,7 +1262,7 @@ // Yes, so handle as LUT-based if (!WriteInputLUT(mem, hProfile, Intent)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1266,7 +1272,7 @@ if (!WriteInputMatrixShaper(mem, hProfile)) { - free((void*) mem); // Something went wrong + _cmsFree((void*) mem); // Something went wrong return 0; } } @@ -1277,7 +1283,7 @@ dwBytesUsed = mem ->dwUsed; // Get rid of memory stream - free((void*) mem); + _cmsFree((void*) mem); // Finally, return used byte count return dwBytesUsed; @@ -1350,27 +1356,40 @@ static -void EmitPQRStage(LPMEMSTREAM m, int DoBPC, int lIsAbsolute) +void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute) { + if (lIsAbsolute) { + + // For absolute colorimetric intent, encode back to relative + // and generate a relative LUT + + // Relative encoding is obtained across XYZpcs*(D50/WhitePoint) + + cmsCIEXYZ White; + + cmsTakeMediaWhitePoint(&White, hProfile); + + Writef(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n"); + Writef(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); + + Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n" + "/TransformPQR [\n" + "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n" + "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n" + "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n", + White.X, White.Y, White.Z); + return; + } + + Writef(m,"%% Bradford Cone Space\n" "/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n"); Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n"); - if (lIsAbsolute) { - - // For absolute colorimetric intent, do nothing - - Writef(m, "%% Absolute colorimetric -- no transformation\n" - "/TransformPQR [\n" - "{exch pop exch pop exch pop exch pop} bind dup dup]\n"); - return; - } - - // No BPC if (!DoBPC) { @@ -1414,6 +1433,7 @@ static void EmitXYZ2Lab(LPMEMSTREAM m) { + Writef(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n"); Writef(m, "/EncodeLMN [\n"); Writef(m, "{ 0.964200 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); Writef(m, "{ 1.000000 div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n"); @@ -1423,17 +1443,10 @@ Writef(m, "/EncodeABC [\n"); - Writef(m, "{ 116 mul 16 sub 100 div } bind\n"); - Writef(m, "{ 500 mul 128 add 255 div } bind\n"); - Writef(m, "{ 200 mul 128 add 255 div } bind\n"); - + Writef(m, "{ 500 mul 128 add 256 div } bind\n"); + Writef(m, "{ 200 mul 128 add 256 div } bind\n"); - /* - Writef(m, "{ 116 mul 16 sub 256 mul 25700 div } bind\n"); - Writef(m, "{ 500 mul 128 add 256 mul 65535 div } bind\n"); - Writef(m, "{ 200 mul 128 add 256 mul 65535 div } bind\n"); - */ Writef(m, "]\n"); @@ -1458,20 +1471,27 @@ LPLUT DeviceLink; cmsHPROFILE Profiles[3]; cmsCIEXYZ BlackPointAdaptedToD50; - BOOL lFreeDeviceLink = FALSE; - BOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); + LCMSBOOL lFreeDeviceLink = FALSE; + LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); + LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP); + int RelativeEncodingIntent; - // Trick our v4 profile as it were v2. This prevents the ajusting done - // in perceptual & saturation. We only neew v4 encoding! - hLab = cmsCreateLab4Profile(NULL); - cmsSetProfileICCversion(hLab, 0); + hLab = cmsCreateLabProfile(NULL); ColorSpace = cmsGetColorSpace(hProfile); nChannels = _cmsChannelsOf(ColorSpace); OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2); + // For absolute colorimetric, the LUT is encoded as relative + // in order to preserve precission. + + RelativeEncodingIntent = Intent; + if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC) + RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC; + + // Is a devicelink profile? if (cmsGetDeviceClass(hProfile) == icSigLinkClass) { @@ -1479,13 +1499,14 @@ if (ColorSpace == icSigLabData) { - // adjust input to Lab to out v4 + // adjust input to Lab to our v4 Profiles[0] = hLab; Profiles[1] = hProfile; xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL, - OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION); + OutputFormat, RelativeEncodingIntent, + dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION); } else { @@ -1499,7 +1520,7 @@ // This is a normal profile xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile, - OutputFormat, Intent, cmsFLAGS_NOPRELINEARIZATION); + OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION); } if (xform == NULL) { @@ -1515,7 +1536,7 @@ if (!DeviceLink) { - DeviceLink = _cmsPrecalculateDeviceLink(xform, 0); + DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION); lFreeDeviceLink = TRUE; } @@ -1527,7 +1548,7 @@ // Emit headers, etc. EmitWhiteBlackD50(m, &BlackPointAdaptedToD50); - EmitPQRStage(m, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); + EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC); EmitXYZ2Lab(m); if (DeviceLink ->wFlags & LUT_HASTL1) { @@ -1544,10 +1565,13 @@ // zero. This would sacrifice a bit of highlights, but failure to do so would cause // scum dot. Ouch. + if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) + lFixWhite = FALSE; + Writef(m, "/RenderTable "); WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE, - (Intent != INTENT_ABSOLUTE_COLORIMETRIC), ColorSpace); + lFixWhite, ColorSpace); Writef(m, " %d {} bind ", nChannels); @@ -1582,6 +1606,9 @@ int j; Colorant[0] = 0; + if (nColorant > MAXCHANNELS) + nColorant = MAXCHANNELS; + for (j=0; j < nColorant; j++) { sprintf(Buff, "%.3f", Out[j] / 65535.0); @@ -1677,7 +1704,7 @@ if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1687,7 +1714,7 @@ if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) { - free((void*) mem); + _cmsFree((void*) mem); return 0; } } @@ -1702,7 +1729,7 @@ dwBytesUsed = mem ->dwUsed; // Get rid of memory stream - free((void*) mem); + _cmsFree((void*) mem); // Finally, return used byte count return dwBytesUsed; diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmssamp.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -120,7 +120,7 @@ // This routine does a sweep on whole input space, and calls its callback // function on knots. returns TRUE if all ok, FALSE otherwise. -BOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags) +LCMSBOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags) { int i, t, nTotalPoints, Colorant, index; WORD In[MAXCHANNELS], Out[MAXCHANNELS]; @@ -145,12 +145,16 @@ &Lut -> In16params); } + for (t=0; t < (int) Lut -> OutputChan; t++) + Out[t] = Lut->T[index + t]; - // if (dwFlags & SAMPLER_INSPECT) { + if (dwFlags & SAMPLER_HASTL2) { for (t=0; t < (int) Lut -> OutputChan; t++) - Out[t] = Lut->T[index + t]; - // } + Out[t] = cmsLinearInterpLUT16(Out[t], + Lut -> L2[t], + &Lut -> Out16params); + } if (!Sampler(In, Out, Cargo)) @@ -255,9 +259,11 @@ LPLUT Grid; int nGridPoints; DWORD dwFormatIn, dwFormatOut; + DWORD SaveFormatIn, SaveFormatOut; int ChannelsIn, ChannelsOut; LPLUT SaveGamutLUT; + // Remove any gamut checking SaveGamutLUT = p ->Gamut; p ->Gamut = NULL; @@ -276,8 +282,13 @@ dwFormatIn = (CHANNELS_SH(ChannelsIn)|BYTES_SH(2)); dwFormatOut = (CHANNELS_SH(ChannelsOut)|BYTES_SH(2)); - p -> FromInput = _cmsIdentifyInputFormat(p, dwFormatIn); - p -> ToOutput = _cmsIdentifyOutputFormat(p, dwFormatOut); + SaveFormatIn = p ->InputFormat; + SaveFormatOut = p ->OutputFormat; + + p -> InputFormat = dwFormatIn; + p -> OutputFormat = dwFormatOut; + p -> FromInput = _cmsIdentifyInputFormat(p, dwFormatIn); + p -> ToOutput = _cmsIdentifyOutputFormat(p, dwFormatOut); // Fix gamut & gamma possible mismatches. @@ -289,7 +300,6 @@ _cmsComputePrelinearizationTablesFromXFORM(hOne, 1, Grid); } - // Attention to this typecast! we can take the luxury to // do this since cmsHTRANSFORM is only an alias to a pointer // to the transform struct. @@ -297,11 +307,13 @@ if (!cmsSample3DGrid(Grid, XFormSampler, (LPVOID) p, Grid -> wFlags)) { cmsFreeLUT(Grid); - return NULL; + Grid = NULL; } + p ->Gamut = SaveGamutLUT; + p ->InputFormat = SaveFormatIn; + p ->OutputFormat = SaveFormatOut; - p ->Gamut = SaveGamutLUT; return Grid; } @@ -348,7 +360,7 @@ -// That is our K-preserving callback. +// Preserve all K plane. static int BlackPreservingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo) { @@ -469,6 +481,7 @@ return OldVal; } +#pragma warning(disable: 4550) // Get a pointer to callback on depending of strategy static @@ -504,11 +517,10 @@ if (p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) LocalFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION; - // Fill in cargo struct Cargo.cmyk2cmyk = hCMYK2CMYK; - // Compute tone curve + // Compute tone curve. Cargo.KTone = _cmsBuildKToneCurve(hCMYK2CMYK, 256); if (Cargo.KTone == NULL) return NULL; cmsCalcL16Params(Cargo.KTone ->nEntries, &Cargo.KToneParams); @@ -522,11 +534,11 @@ Cargo.LabK2cmyk = cmsReadICCLut(p->OutputProfile, Device2PCS[p->Intent]); // Is there any table available? - if (Cargo.LabK2cmyk == NULL) { + if (Cargo.LabK2cmyk == NULL) { - Grid = NULL; + Grid = NULL; goto Cleanup; - } + } // Setup a roundtrip on output profile for TAC estimation Cargo.hRoundTrip = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16, @@ -654,7 +666,7 @@ -BOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p) +LCMSBOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p) { WORD *WhitePointIn, *WhitePointOut, *BlackPointIn, *BlackPointOut; @@ -682,3 +694,4 @@ return TRUE; } + diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -320,7 +320,7 @@ cmsHPROFILE hICC; _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) hTransform; LPLUT Lut; - BOOL MustFreeLUT; + LCMSBOOL MustFreeLUT; LPcmsNAMEDCOLORLIST InputColorant = NULL; LPcmsNAMEDCOLORLIST OutputColorant = NULL; @@ -373,10 +373,8 @@ if (cmsGetDeviceClass(hICC) == icSigOutputClass) { - cmsAddTag(hICC, icSigBToA0Tag, (LPVOID) Lut); } - else cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut); @@ -404,7 +402,7 @@ OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableTag); } - } + } if (InputColorant) cmsAddTag(hICC, icSigColorantTableTag, InputColorant); @@ -446,6 +444,7 @@ // Creates a LUT with prelinearization step only Lut = cmsAllocLUT(); + if (Lut == NULL) return NULL; // Set up channels Lut ->InputChan = Lut ->OutputChan = _cmsChannelsOf(ColorSpace); @@ -548,6 +547,10 @@ // Creates a LUT with 3D grid only Lut = cmsAllocLUT(); + if (Lut == NULL) { + cmsCloseProfile(hICC); + return NULL; + } cmsAlloc3DGrid(Lut, 17, _cmsChannelsOf(ColorSpace), @@ -584,8 +587,9 @@ LPLUT Create3x3EmptyLUT(void) { LPLUT AToB0 = cmsAllocLUT(); + if (AToB0 == NULL) return NULL; + AToB0 -> InputChan = AToB0 -> OutputChan = 3; - return AToB0; } @@ -597,8 +601,8 @@ cmsHPROFILE hProfile; LPLUT Lut; - hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); + if (hProfile == NULL) return NULL; cmsSetDeviceClass(hProfile, icSigAbstractClass); cmsSetColorSpace(hProfile, icSigLabData); @@ -611,7 +615,10 @@ // An empty LUTs is all we need Lut = Create3x3EmptyLUT(); - if (Lut == NULL) return NULL; + if (Lut == NULL) { + cmsCloseProfile(hProfile); + return NULL; + } cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut); cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut); @@ -628,8 +635,8 @@ cmsHPROFILE hProfile; LPLUT Lut; - hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL); + if (hProfile == NULL) return NULL; cmsSetProfileICCversion(hProfile, 0x4000000); @@ -644,7 +651,10 @@ // An empty LUTs is all we need Lut = Create3x3EmptyLUT(); - if (Lut == NULL) return NULL; + if (Lut == NULL) { + cmsCloseProfile(hProfile); + return NULL; + } Lut -> wFlags |= LUT_V4_INPUT_EMULATE_V2; cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut); @@ -666,6 +676,7 @@ LPLUT Lut; hProfile = cmsCreateRGBProfile(cmsD50_xyY(), NULL, NULL); + if (hProfile == NULL) return NULL; cmsSetDeviceClass(hProfile, icSigAbstractClass); cmsSetColorSpace(hProfile, icSigXYZData); @@ -677,15 +688,16 @@ // An empty LUTs is all we need Lut = Create3x3EmptyLUT(); - if (Lut == NULL) return NULL; + if (Lut == NULL) { + cmsCloseProfile(hProfile); + return NULL; + } cmsAddTag(hProfile, icSigAToB0Tag, (LPVOID) Lut); cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut); cmsAddTag(hProfile, icSigPreview0Tag, (LPVOID) Lut); cmsFreeLUT(Lut); - - return hProfile; } @@ -723,6 +735,7 @@ return cmsBuildParametricGamma(1024, 4, Parameters); } +// Create the ICC virtual profile for sRGB space cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void) { cmsCIExyY D65; @@ -739,6 +752,7 @@ hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma22); cmsFreeGamma(Gamma22[0]); + if (hsRGB == NULL) return NULL; cmsAddTag(hsRGB, icSigDeviceMfgDescTag, (LPVOID) "(lcms internal)"); @@ -750,7 +764,6 @@ - typedef struct { double Brightness; double Contrast; @@ -793,7 +806,6 @@ cmsFloat2LabEncoded(Out, &LabOut); - return TRUE; } @@ -839,7 +851,10 @@ // Creates a LUT with 3D grid only Lut = cmsAllocLUT(); - + if (Lut == NULL) { + cmsCloseProfile(hICC); + return NULL; + } cmsAlloc3DGrid(Lut, nLUTPoints, 3, 3); @@ -890,7 +905,10 @@ // An empty LUTs is all we need Lut = cmsAllocLUT(); - if (Lut == NULL) return NULL; + if (Lut == NULL) { + cmsCloseProfile(hProfile); + return NULL; + } Lut -> InputChan = 3; Lut -> OutputChan = 1; diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -51,10 +51,6 @@ #include "lcms.h" -// Uncomment this line if you want lcms to use the black point tag in profile, -// if commented, lcms will compute the black point by its own. -// It is safer to leve it commented out -// #define HONOR_BLACK_POINT_TAG // Conversions @@ -79,10 +75,9 @@ } - // Obtains WhitePoint from Temperature -BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint) +LCMSBOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint) { double x, y; double T, T2, T3; @@ -147,7 +142,7 @@ // - Then, I apply these coeficients to the original matrix -BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt, +LCMSBOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt, LPcmsCIExyYTRIPLE Primrs) { VEC3 WhitePoint, Coef; @@ -169,14 +164,12 @@ // Build Primaries matrix - VEC3init(&Primaries.v[0], xr, xg, xb); VEC3init(&Primaries.v[1], yr, yg, yb); VEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg), (1-xb-yb)); // Result = Primaries ^ (-1) inverse matrix - if (!MAT3inverse(&Primaries, &Result)) return FALSE; @@ -184,11 +177,9 @@ VEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn); // Across inverse primaries ... - MAT3eval(&Coef, &Result, &WhitePoint); // Give us the Coefs, then I build transformation matrix - VEC3init(&r -> v[0], Coef.n[VX]*xr, Coef.n[VY]*xg, Coef.n[VZ]*xb); VEC3init(&r -> v[1], Coef.n[VX]*yr, Coef.n[VY]*yg, Coef.n[VZ]*yb); VEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb)); @@ -246,7 +237,7 @@ // Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll // The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed -BOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll) +LCMSBOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll) { MAT3 LamRigg = {{ // Bradford matrix {{ 0.8951, 0.2664, -0.1614 }}, @@ -265,7 +256,7 @@ // Same as anterior, but assuming D50 destination. White point is given in xyY -BOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt) +LCMSBOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt) { cmsCIEXYZ Dn; MAT3 Bradford; @@ -284,7 +275,7 @@ // Same as anterior, but assuming D50 source. White point is given in xyY -BOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt) +LCMSBOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt) { cmsCIEXYZ Dn; MAT3 Bradford; @@ -304,7 +295,7 @@ // Adapts a color to a given illuminant. Original color is expected to have // a SourceWhitePt white point. -BOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result, +LCMSBOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result, LPcmsCIEXYZ SourceWhitePt, LPcmsCIEXYZ Illuminant, LPcmsCIEXYZ Value) @@ -404,8 +395,6 @@ dj = ((vs - vj) - tj * (us - uj)) / sqrt(1 + tj*tj); - - if ((j!=0) && (di/dj < 0.0)) { Tc = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi)); break; @@ -423,7 +412,7 @@ static -BOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance) +LCMSBOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance) { double dist_x, dist_y; @@ -458,6 +447,7 @@ } +// To be removed in future versions void _cmsIdentifyWhitePoint(char *Buffer, LPcmsCIEXYZ WhitePt) { int i, n; @@ -518,7 +508,6 @@ cmsCIEXYZ BlackXYZ, MediaWhite; // If the profile does not support input direction, assume Black point 0 - if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) { BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0; @@ -527,7 +516,6 @@ // Try to get black by using black colorant - Space = cmsGetColorSpace(hInput); if (!_cmsEndPointsBySpace(Space, &White, &Black, &nChannels)) { @@ -576,7 +564,7 @@ // Get a black point of output CMYK profile, discounting any ink-limiting embedded -// in the profile. Fou doing that, use perceptual intent in input direction: +// in the profile. For doing that, use perceptual intent in input direction: // Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab static @@ -651,6 +639,8 @@ D50BlackPoint.X = PERCEPTUAL_BLACK_X; D50BlackPoint.Y = PERCEPTUAL_BLACK_Y; D50BlackPoint.Z = PERCEPTUAL_BLACK_Z; + + // Obtain the absolute XYZ. Adapt perceptual black back from D50 to whatever media white cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &D50BlackPoint); } @@ -662,26 +652,24 @@ // This function shouldn't exist at all -- there is such quantity of broken // profiles on black point tag, that we must somehow fix chromaticity to // avoid huge tint when doing Black point compensation. This function does -// just that. If BP is specified, then forces it to neutral and uses only L -// component. If does not exist, computes it by taking 400% of ink or RGB=0 This -// works well on relative intent and is undefined on perceptual & saturation. -// However, I will support all intents for tricking & trapping. - +// just that. There is a special flag for using black point tag, but turned +// off by default because it is bogus on most profiles. The detection algorithm +// involves to turn BP to neutral and to use only L component. int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent, DWORD dwFlags) { - // v4 + perceptual & saturation intents does have its own black point + // v4 + perceptual & saturation intents does have its own black point, and it is + // well specified enough to use it. if ((cmsGetProfileICCversion(hProfile) >= 0x4000000) && (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) { // Matrix shaper share MRC & perceptual intents - if (_cmsIsMatrixShaper(hProfile)) return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, cmsFLAGS_NOTPRECALC); - // Get fixed value + // CLUT based - Get perceptual black point (fixed value) return GetV4PerceptualBlack(BlackPoint, hProfile, dwFlags); } @@ -701,7 +689,6 @@ cmsTakeMediaWhitePoint(&MediaWhite, hProfile); // Black point is absolute XYZ, so adapt to D50 to get PCS value - cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ); // Force a=b=0 to get rid of any chroma @@ -713,7 +700,6 @@ cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab); // Return BP as D50 relative or absolute XYZ (depends on flags) - if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)) cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &TrustedBlackPoint); else @@ -724,15 +710,15 @@ #endif - // If output profile, discount ink-limiting + // That is about v2 profiles. + // If output profile, discount ink-limiting and that's all if (Intent == INTENT_RELATIVE_COLORIMETRIC && (cmsGetDeviceClass(hProfile) == icSigOutputClass) && (cmsGetColorSpace(hProfile) == icSigCmykData)) return BlackPointUsingPerceptualBlack(BlackPoint, hProfile, dwFlags); // Nope, compute BP using current intent. - return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags); } diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsxform.c Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -52,7 +52,6 @@ #include "lcms.h" -// #define DEBUG 1 // Transformations stuff // ----------------------------------------------------------------------- @@ -85,7 +84,7 @@ void LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b); void LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b); -BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, +LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection); // ------------------------------------------------------------------------- @@ -343,7 +342,7 @@ p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut, p ->DeviceLink -> T, &p ->DeviceLink -> CLut16params); - } + } else cmsEvalLUT(p -> DeviceLink, wIn, wOut); @@ -414,7 +413,7 @@ register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; - WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS]; + WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS]; accum = (LPBYTE) in; @@ -427,10 +426,10 @@ ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS); - LCMS_READ_LOCK(&p ->rwlock); - CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS); - CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS); - LCMS_UNLOCK(&p ->rwlock); + LCMS_READ_LOCK(&p ->rwlock); + CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS); + CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS); + LCMS_UNLOCK(&p ->rwlock); for (i=0; i < n; i++) { @@ -443,14 +442,14 @@ } else { - // Try to speedup things on plain devicelinks - - if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) { + // Try to speedup things on plain devicelinks + + if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) { p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut, p ->DeviceLink -> T, &p ->DeviceLink -> CLut16params); - } + } else cmsEvalLUT(p -> DeviceLink, wIn, wOut); @@ -463,10 +462,10 @@ } - LCMS_WRITE_LOCK(&p ->rwlock); - CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS); - CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS); - LCMS_UNLOCK(&p ->rwlock); + LCMS_WRITE_LOCK(&p ->rwlock); + CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS); + CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS); + LCMS_UNLOCK(&p ->rwlock); } @@ -483,7 +482,7 @@ register LPBYTE output; WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS]; register unsigned int i, n; - WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS]; + WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS]; accum = (LPBYTE) in; @@ -495,10 +494,10 @@ ZeroMemory(wIn, sizeof(WORD) * MAXCHANNELS); ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS); - LCMS_READ_LOCK(&p ->rwlock); - CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS); - CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS); - LCMS_UNLOCK(&p ->rwlock); + LCMS_READ_LOCK(&p ->rwlock); + CopyMemory(CacheIn, p ->CacheIn, sizeof(WORD) * MAXCHANNELS); + CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS); + LCMS_UNLOCK(&p ->rwlock); for (i=0; i < n; i++) { @@ -520,10 +519,10 @@ output = p -> ToOutput(p, wOut, output); } - LCMS_WRITE_LOCK(&p ->rwlock); - CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS); - CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS); - LCMS_UNLOCK(&p ->rwlock); + LCMS_WRITE_LOCK(&p ->rwlock); + CopyMemory(p->CacheIn, CacheIn, sizeof(WORD) * MAXCHANNELS); + CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS); + LCMS_UNLOCK(&p ->rwlock); } @@ -635,6 +634,8 @@ MAT3 Scale; GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag); // Y + if (GrayTRC == NULL) return NULL; + cmsTakeIluminant(&Illuminant, hProfile); if (cmsGetPCS(hProfile) == icSigLabData) { @@ -789,6 +790,10 @@ InverseShapes[1] = cmsReadICCGammaReversed(OutputProfile, icSigGreenTRCTag); InverseShapes[2] = cmsReadICCGammaReversed(OutputProfile, icSigBlueTRCTag); + if (InverseShapes[0] == NULL || + InverseShapes[1] == NULL || + InverseShapes[2] == NULL) return NULL; + OutMatSh = cmsAllocMatShaper(&DoubleInv, InverseShapes, MATSHAPER_OUTPUT); cmsFreeGammaTriple(InverseShapes); @@ -801,7 +806,7 @@ // This function builds a transform matrix chaining parameters static -BOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p) +LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p) { MAT3 From, To, ToInv, Transfer; LPGAMMATABLE In[3], InverseOut[3]; @@ -814,7 +819,6 @@ if (!cmsReadICCMatrixRGB2XYZ(&To, p -> OutputProfile)) return FALSE; - // invert dest if (MAT3inverse(&To, &ToInv) < 0) @@ -838,10 +842,14 @@ InverseOut[1] = cmsReadICCGammaReversed(p -> OutputProfile, icSigGreenTRCTag); InverseOut[2] = cmsReadICCGammaReversed(p -> OutputProfile, icSigBlueTRCTag); + if (!InverseOut[0] || !InverseOut[1] || !InverseOut[2]) { + cmsFreeGammaTriple(In); + return FALSE; + } + p -> SmeltMatShaper = cmsAllocMatShaper2(&Transfer, In, InverseOut, MATSHAPER_ALLSMELTED); cmsFreeGammaTriple(In); - cmsFreeGammaTriple(InverseOut); return (p -> SmeltMatShaper != NULL); @@ -1029,7 +1037,7 @@ // Check colorspace static -BOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, BOOL lUsePCS) +LCMSBOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, LCMSBOOL lUsePCS) { int Space = T_COLORSPACE(dwFormat); @@ -1049,10 +1057,10 @@ { // Allocate needed memory - _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) malloc(sizeof(_cmsTRANSFORM)); + _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) _cmsMalloc(sizeof(_cmsTRANSFORM)); if (!p) { - cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: malloc() failed"); + cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: _cmsMalloc() failed"); return NULL; } @@ -1078,7 +1086,7 @@ p -> ExitColorSpace = (icColorSpaceSignature) 0; p -> AdaptationState = GlobalAdaptationState; - LCMS_CREATE_LOCK(&p->rwlock); + LCMS_CREATE_LOCK(&p->rwlock); return p; } @@ -1269,12 +1277,12 @@ else { // Can we optimize matrix-shaper only transform? - if (*FromTagPtr == 0 && - *ToTagPtr == 0 && - !p->PreviewProfile && - p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC && + if ((*FromTagPtr == 0) && + (*ToTagPtr == 0) && + (!p->PreviewProfile) && + (p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC) && (p -> EntryColorSpace == icSigRgbData) && - (p -> ExitColorSpace == icSigRgbData) && + (p -> ExitColorSpace == icSigRgbData) && !(p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)) { // Yes... try to smelt matrix-shapers @@ -1530,7 +1538,6 @@ TakeConversionRoutines(p, dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION); - if (!(p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) { LPLUT DeviceLink; @@ -1553,7 +1560,8 @@ DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags); } - if (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK) { + // Allow to specify cmsFLAGS_GAMUTCHECK, even if no proofing profile is given + if ((p ->PreviewProfile != NULL) && (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK)) { GamutCheck = _cmsPrecalculateGamutCheck((cmsHTRANSFORM) p); } @@ -1561,7 +1569,6 @@ // If input colorspace is Rgb, Cmy, then use tetrahedral interpolation // for speed reasons (it only works well on spaces on Luma is diagonal, and // not if luma is in separate channel) - if (p ->EntryColorSpace == icSigRgbData || p ->EntryColorSpace == icSigCmyData) { @@ -1663,12 +1670,12 @@ cmsFreeMatShaper(p -> SmeltMatShaper); if (p ->NamedColorList) cmsFreeNamedColorList(p ->NamedColorList); - if (p -> GamutCheck) - cmsFreeLUT(p -> GamutCheck); - - LCMS_FREE_LOCK(&p->rwlock); - - free((void *) p); + if (p -> GamutCheck) + cmsFreeLUT(p -> GamutCheck); + + LCMS_FREE_LOCK(&p->rwlock); + + _cmsFree((void *) p); } @@ -1704,7 +1711,7 @@ // Returns TRUE if the profile is implemented as matrix-shaper -BOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile) +LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile) { switch (cmsGetColorSpace(hProfile)) { @@ -1728,7 +1735,7 @@ } -BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, +LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection) { @@ -1774,6 +1781,16 @@ } +static +int IsAllowedInSingleXform(icProfileClassSignature aClass) +{ + return (aClass == icSigInputClass) || + (aClass == icSigDisplayClass) || + (aClass == icSigOutputClass) || + (aClass == icSigColorSpaceClass); +} + + // A multiprofile transform does chain several profiles into a single // devicelink. It couls also be used to merge named color profiles into // a single database. @@ -1805,10 +1822,16 @@ // There is a simple case with just two profiles, try to catch it in order of getting // black preservation to work on this function, at least with two profiles. + if (nProfiles == 2) { - if ((cmsGetDeviceClass(hProfiles[0]) != icSigLinkClass) && - (cmsGetDeviceClass(hProfiles[1]) != icSigLinkClass)) + icProfileClassSignature Class1 = cmsGetDeviceClass(hProfiles[0]); + icProfileClassSignature Class2 = cmsGetDeviceClass(hProfiles[1]); + + // Only input, output and display are allowed + + if (IsAllowedInSingleXform(Class1) && + IsAllowedInSingleXform(Class2)) return cmsCreateTransform(hProfiles[0], dwInput, hProfiles[1], dwOutput, Intent, dwFlags); } @@ -1984,6 +2007,14 @@ if (hLab) cmsCloseProfile(hLab); if (hXYZ) cmsCloseProfile(hXYZ); + + if (p ->EntryColorSpace == icSigRgbData || + p ->EntryColorSpace == icSigCmyData) { + + p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16; + } + + if ((Intent != INTENT_ABSOLUTE_COLORIMETRIC) && !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) _cmsFixWhiteMisalignment(p); diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/icc34.h --- a/jdk/src/share/native/sun/java2d/cmm/lcms/icc34.h Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/icc34.h Tue Mar 24 09:14:02 2009 -0700 @@ -206,6 +206,11 @@ #if defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__) +#if defined (__MINGW) || defined(__MINGW32__) +#include +#endif + + typedef uint8_t icUInt8Number; typedef uint16_t icUInt16Number; typedef uint32_t icUInt32Number; diff -r ea28f24e1708 -r 404cbe399601 jdk/src/share/native/sun/java2d/cmm/lcms/lcms.h --- a/jdk/src/share/native/sun/java2d/cmm/lcms/lcms.h Mon Mar 23 10:40:54 2009 -0700 +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/lcms.h Tue Mar 24 09:14:02 2009 -0700 @@ -29,7 +29,7 @@ // // // Little cms -// Copyright (C) 1998-2006 Marti Maria +// Copyright (C) 1998-2007 Marti Maria // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -49,8 +49,8 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// Version 1.16 -#undef DEBUG +// Version 1.18 + #ifndef __cms_H // ********** Configuration toggles **************************************** @@ -62,13 +62,8 @@ // virtually any machine. //#define USE_FLOAT 1 -#ifdef _WIN64 -#define USE_C 1 -#undef USE_ASSEMBLER -#else -#undef USE_C +// #define USE_C 1 #define USE_ASSEMBLER 1 -#endif // Define this if you are using this package as a DLL (windows only) @@ -77,15 +72,11 @@ // Uncomment if you are trying the engine in a non-windows environment // like linux, SGI, VAX, FreeBSD, BeOS, etc. -#if !defined(_WIN32) || !defined(_WIN64) #define NON_WINDOWS 1 -#endif // Uncomment this one if you are using big endian machines (only meaningful // when NON_WINDOWS is used) -#ifndef _LITTLE_ENDIAN -#define USE_BIG_ENDIAN 1 -#endif +// #define USE_BIG_ENDIAN 1 // Uncomment this one if your compiler/machine does support the // "long long" type This will speedup fixed point math. (USE_C only) @@ -104,18 +95,24 @@ // Uncomment this line on multithreading environments // #define USE_PTHREADS 1 +// Uncomment this line if you want lcms to use the black point tag in profile, +// if commented, lcms will compute the black point by its own. +// It is safer to leve it commented out +// #define HONOR_BLACK_POINT_TAG 1 + // ********** End of configuration toggles ****************************** -#define LCMS_VERSION 116 +#define LCMS_VERSION 118 // Microsoft VisualC++ // Deal with Microsoft's attempt at deprecating C standard runtime functions - #ifdef _MSC_VER # undef NON_WINDOWS # if (_MSC_VER >= 1400) +# ifndef _CRT_SECURE_NO_DEPRECATE # define _CRT_SECURE_NO_DEPRECATE 1 +# endif # endif #endif @@ -125,7 +122,6 @@ # undef NON_WINDOWS #endif - #include #include #include @@ -134,11 +130,11 @@ #include // Metroworks CodeWarrior - #ifdef __MWERKS__ # define unlink remove # if WIN32 # define USE_CUSTOM_SWAB 1 +# undef NON_WINDOWS # else # define NON_WINDOWS 1 # endif @@ -172,15 +168,21 @@ # define USE_BIG_ENDIAN 1 #endif -#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__) +#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__) || defined(__s390__) || defined(__s390x__) # define USE_BIG_ENDIAN 1 #endif -#ifdef TARGET_CPU_PPC +#if TARGET_CPU_PPC # define USE_BIG_ENDIAN 1 #endif -#ifdef macintosh +#if macintosh +# ifndef __LITTLE_ENDIAN__ +# define USE_BIG_ENDIAN 1 +# endif +#endif + +#ifdef __BIG_ENDIAN__ # define USE_BIG_ENDIAN 1 #endif @@ -217,11 +219,8 @@ typedef unsigned char BYTE, *LPBYTE; typedef unsigned short WORD, *LPWORD; typedef unsigned long DWORD, *LPDWORD; -typedef int BOOL; typedef char *LPSTR; typedef void *LPVOID; -typedef void* LCMSHANDLE; - #define ZeroMemory(p,l) memset((p),0,(l)) #define CopyMemory(d,s,l) memcpy((d),(s),(l)) @@ -263,8 +262,12 @@ #include -typedef HANDLE LCMSHANDLE; - +#ifdef _WIN64 +# ifdef USE_ASSEMBLER +# undef USE_ASSEMBLER +# define USE_C 1 +# endif +#endif #ifdef USE_INT64 # ifndef LCMSULONGLONG @@ -296,6 +299,10 @@ # define LCMS_UNLOCK(x) #endif +// Base types + +typedef int LCMSBOOL; +typedef void* LCMSHANDLE; #include "icc34.h" // ICC header file @@ -322,16 +329,10 @@ #define icSigMCHEData ((icColorSpaceSignature) 0x4d434845L) // MCHE #define icSigMCHFData ((icColorSpaceSignature) 0x4d434846L) // MCHF -#define icSigCAM97JABData ((icColorSpaceSignature) 0x4A616231L) // 'Jab1' H. Zeng -#define icSigCAM02JABData ((icColorSpaceSignature) 0x4A616232L) // 'Jab2' H. Zeng -#define icSigCAM02JCHData ((icColorSpaceSignature) 0x4A636A32L) // 'Jch2' H. Zeng - #define icSigChromaticityTag ((icTagSignature) 0x6368726dL) // As per Addendum 2 to Spec. ICC.1:1998-09 #define icSigChromaticAdaptationTag ((icTagSignature) 0x63686164L) // 'chad' #define icSigColorantTableTag ((icTagSignature) 0x636c7274L) // 'clrt' #define icSigColorantTableOutTag ((icTagSignature) 0x636c6f74L) // 'clot' -#define icSigHPGamutDescTag ((icTagSignature) 0x676D7441L) // 'gmtA' H. Zeng - #define icSigParametricCurveType ((icTagTypeSignature) 0x70617261L) // parametric (ICC 4.0) #define icSigMultiLocalizedUnicodeType ((icTagTypeSignature) 0x6D6C7563L) @@ -340,7 +341,6 @@ #define icSiglutAtoBType ((icTagTypeSignature) 0x6d414220L) // mAB #define icSiglutBtoAType ((icTagTypeSignature) 0x6d424120L) // mBA #define icSigColorantTableType ((icTagTypeSignature) 0x636c7274L) // clrt -#define icSigHPGamutDescType ((icTagTypeSignature) 0x676D7441L) // gmtA H. Zeng typedef struct { @@ -438,9 +438,6 @@ #ifndef itoa # define itoa _itoa #endif -#ifndef filelength -# define filelength _filelength -#endif #ifndef fileno # define fileno _fileno #endif @@ -450,6 +447,14 @@ #ifndef hypot # define hypot _hypot #endif +#ifndef snprintf +# define snprintf _snprintf +#endif +#ifndef vsnprintf +# define vsnprintf _vsnprintf +#endif + + #endif @@ -470,8 +475,9 @@ // Format of pixel is defined by one DWORD, using bit fields as follows // -// TTTTT U Y F P X S EEE CCCC BBB +// D TTTTT U Y F P X S EEE CCCC BBB // +// D: Use dither (8 bits only) // T: Pixeltype // F: Flavor 0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla) // P: Planar? 0=Chunky, 1=Planar @@ -483,6 +489,7 @@ // Y: Swap first - changes ABGR to BGRA and KCMY to CMYK +#define DITHER_SH(s) ((s) << 22) #define COLORSPACE_SH(s) ((s) << 16) #define SWAPFIRST_SH(s) ((s) << 14) #define FLAVOR_SH(s) ((s) << 13) @@ -711,20 +718,20 @@ typedef struct { - unsigned int Crc32; // Has my table been touched? - - // Keep initial parameters for further serialization + unsigned int Crc32; // Has my table been touched? + + // Keep initial parameters for further serialization int Type; double Params[10]; - } LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS; + } LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS; // Gamma tables. typedef struct { - LCMSGAMMAPARAMS Seed; // Parameters used for table creation + LCMSGAMMAPARAMS Seed; // Parameters used for table creation // Table-based representation follows @@ -858,7 +865,7 @@ LCMSAPI cmsHPROFILE LCMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess); LCMSAPI cmsHPROFILE LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize); -LCMSAPI BOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile); +LCMSAPI LCMSBOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile); // Predefined run-time profiles @@ -915,14 +922,14 @@ LCMSAPI void LCMSEXPORT cmsClampLab(LPcmsCIELab Lab, double amax, double amin, double bmax, double bmin); -LCMSAPI BOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint); - -LCMSAPI BOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result, +LCMSAPI LCMSBOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint); + +LCMSAPI LCMSBOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result, LPcmsCIEXYZ SourceWhitePt, LPcmsCIEXYZ Illuminant, LPcmsCIEXYZ Value); -LCMSAPI BOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, +LCMSAPI LCMSBOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePoint, LPcmsCIExyYTRIPLE Primaries); @@ -976,7 +983,7 @@ LCMSAPI LPGAMMATABLE LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma); LCMSAPI LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma); LCMSAPI LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma, int nPoints); -LCMSAPI BOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda); +LCMSAPI LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda); LCMSAPI double LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t); LCMSAPI double LCMSEXPORT cmsEstimateGammaEx(LPWORD Table, int nEntries, double Thereshold); LCMSAPI LPGAMMATABLE LCMSEXPORT cmsReadICCGamma(cmsHPROFILE hProfile, icTagSignature sig); @@ -984,14 +991,14 @@ // Access to Profile data. -LCMSAPI BOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile); -LCMSAPI BOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile); -LCMSAPI BOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile); -LCMSAPI BOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile); LCMSAPI DWORD LCMSEXPORT cmsTakeHeaderFlags(cmsHPROFILE hProfile); LCMSAPI DWORD LCMSEXPORT cmsTakeHeaderAttributes(cmsHPROFILE hProfile); -LCMSAPI void LCMSEXPORT cmsSetLanguage(int LanguageCode, int CountryCode); +LCMSAPI void LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4]); LCMSAPI const char* LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile); LCMSAPI const char* LCMSEXPORT cmsTakeProductDesc(cmsHPROFILE hProfile); LCMSAPI const char* LCMSEXPORT cmsTakeProductInfo(cmsHPROFILE hProfile); @@ -1000,13 +1007,13 @@ LCMSAPI const char* LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile); LCMSAPI const BYTE* LCMSEXPORT cmsTakeProfileID(cmsHPROFILE hProfile); -LCMSAPI BOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile); -LCMSAPI BOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile); - -LCMSAPI BOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile); + +LCMSAPI LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig); LCMSAPI int LCMSEXPORT cmsTakeRenderingIntent(cmsHPROFILE hProfile); -LCMSAPI BOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len); +LCMSAPI LCMSBOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len); LCMSAPI int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Text, size_t size); LCMSAPI int LCMSEXPORT cmsReadICCText(cmsHPROFILE hProfile, icTagSignature sig, char *Text); @@ -1038,50 +1045,18 @@ LCMSAPI void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq); -// Extended gamut tag -- an HP extension - -#define LCMSGAMUTMETHOD_SEGMENTMAXIMA 0 -#define LCMSGAMUTMETHOD_CONVEXHULL 1 -#define LCMSGAMUTMETHOD_ALPHASHAPE 2 - - -#define LCMSGAMUT_PHYSICAL 0 -#define LCMSGAMUT_HP1 1 -#define LCMSGAMUT_HP2 2 - -typedef struct { - - icColorSpaceSignature CoordSig; // Gamut coordinates signature - icUInt16Number Method; // Method used to generate gamut - icUInt16Number Usage; // Gamut usage or intent - - char Description[LCMS_DESC_MAX]; // Textual description - - cmsViewingConditions Vc; // The viewing conditions - - icUInt32Number Count; // Number of entries - double Data[1]; // The current data - - } cmsGAMUTEX, FAR* LPcmsGAMUTEX; - - -LCMSAPI LPcmsGAMUTEX LCMSEXPORT cmsReadExtendedGamut(cmsHPROFILE hProfile, int index); -LCMSAPI void LCMSEXPORT cmsFreeExtendedGamut(LPcmsGAMUTEX gex); - - - - // Translate form/to our notation to ICC LCMSAPI icColorSpaceSignature LCMSEXPORT _cmsICCcolorSpace(int OurNotation); -LCMSAPI int LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace); -LCMSAPI int LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace); -LCMSAPI BOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile); - +LCMSAPI int LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace); +LCMSAPI int LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile); + +// How profiles may be used #define LCMS_USED_AS_INPUT 0 #define LCMS_USED_AS_OUTPUT 1 #define LCMS_USED_AS_PROOF 2 -LCMSAPI BOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection); LCMSAPI icColorSpaceSignature LCMSEXPORT cmsGetPCS(cmsHPROFILE hProfile); LCMSAPI icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile); @@ -1141,7 +1116,7 @@ // CRD special -#define cmsFLAGS_NODEFAULTRESOURCEDEF 0x00010000 +#define cmsFLAGS_NODEFAULTRESOURCEDEF 0x01000000 // Gridpoints @@ -1220,9 +1195,9 @@ // Named color support -LCMSAPI int LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform); -LCMSAPI BOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix); -LCMSAPI int LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name); +LCMSAPI int LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform); +LCMSAPI LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix); +LCMSAPI int LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name); // Colorant tables @@ -1230,7 +1205,7 @@ // Profile creation -LCMSAPI BOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data); +LCMSAPI LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data); // Converts a transform to a devicelink profile LCMSAPI cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD dwFlags); @@ -1240,8 +1215,8 @@ // Save profile -LCMSAPI BOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName); -LCMSAPI BOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, +LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, size_t* BytesNeeded); @@ -1286,6 +1261,7 @@ LCMSAPI LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig); LCMSAPI LPLUT LCMSEXPORT cmsDupLUT(LPLUT Orig); + // LUT Sampling typedef int (* _cmsSAMPLER)(register WORD In[], @@ -1325,35 +1301,37 @@ // Persistence LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName); LCMSAPI LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len); -LCMSAPI BOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName); -LCMSAPI BOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded); // Properties LCMSAPI const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type); - -LCMSAPI BOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment); - -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val); - -LCMSAPI BOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type); + +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment); + +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer); LCMSAPI const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp); LCMSAPI double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp); -LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, char ***PropertyNames); +LCMSAPI const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp); +LCMSAPI int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames); +LCMSAPI int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames); // Datasets LCMSAPI const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col); LCMSAPI double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int row, int col); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val); LCMSAPI const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample); @@ -1361,25 +1339,28 @@ LCMSAPI double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample, const char *Val); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch, const char* cSample, double Val); LCMSAPI int LCMSEXPORT cmsIT8GetDataFormat(LCMSHANDLE hIT8, const char* cSample); -LCMSAPI BOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample); LCMSAPI int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames); LCMSAPI const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer); +LCMSAPI int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cSample); // The LABEL extension LCMSAPI int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType); +LCMSAPI LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample); + // Formatter for double LCMSAPI void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter); @@ -1405,15 +1386,16 @@ // Profiling Extensions --- Would be removed from API in future revisions -LCMSAPI BOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text); -LCMSAPI BOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ); -LCMSAPI BOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut); -LCMSAPI BOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction); -LCMSAPI BOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm); -LCMSAPI BOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq); -LCMSAPI BOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc); -LCMSAPI BOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime); -LCMSAPI BOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc); +LCMSAPI LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat); // --------------------------------------------------------------------------------------------------- Inline functions @@ -1455,6 +1437,38 @@ return (WORD) in; } +#ifndef LCMS_USER_ALLOC + +// Low-level alloc hook + +LCMS_INLINE void* _cmsMalloc(size_t size) +{ + if (size > ((size_t) 1024*1024*500)) return NULL; // Never allow over 500Mb + if (size < 0) return NULL; // Prevent signed size_t exploits + + return (void*) malloc(size); +} + +LCMS_INLINE void* _cmsCalloc(size_t nmemb, size_t size) +{ + size_t alloc = nmemb * size; + + if (size == 0) { + return _cmsMalloc(0); + } + if (alloc / size != nmemb) { + return NULL; + } + return _cmsMalloc(alloc); +} + +LCMS_INLINE void _cmsFree(void *Ptr) +{ + if (Ptr) free(Ptr); +} + +#endif + // ------------------------------------------------------------------------------------------- end of inline functions // Signal error from inside lcms code @@ -1531,36 +1545,36 @@ -void cdecl VEC3init(LPVEC3 r, double x, double y, double z); // double version -void cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version -void cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v); -void cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v); -void cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale); -void cdecl VEC3swap(LPVEC3 a, LPVEC3 b); -void cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d); -void cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d); -void cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b); -void cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b); -BOOL cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance); -BOOL cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance); -void cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d); -void cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v); -void cdecl VEC3saturate(LPVEC3 v); -double cdecl VEC3distance(LPVEC3 a, LPVEC3 b); -double cdecl VEC3length(LPVEC3 a); - -void cdecl MAT3identity(LPMAT3 a); -void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b); -void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d); -int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b); -BOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b); -double cdecl MAT3det(LPMAT3 m); -void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v); -void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v); -void cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v); -void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v); -BOOL cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance); -void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d); +void cdecl VEC3init(LPVEC3 r, double x, double y, double z); // double version +void cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version +void cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v); +void cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v); +void cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale); +void cdecl VEC3swap(LPVEC3 a, LPVEC3 b); +void cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d); +void cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d); +void cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b); +void cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b); +LCMSBOOL cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance); +LCMSBOOL cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance); +void cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d); +void cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v); +void cdecl VEC3saturate(LPVEC3 v); +double cdecl VEC3distance(LPVEC3 a, LPVEC3 b); +double cdecl VEC3length(LPVEC3 a); + +void cdecl MAT3identity(LPMAT3 a); +void cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b); +void cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d); +int cdecl MAT3inverse(LPMAT3 a, LPMAT3 b); +LCMSBOOL cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b); +double cdecl MAT3det(LPMAT3 m); +void cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v); +void cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v); +void cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v); +void cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v); +LCMSBOOL cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance); +void cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d); // Is a table linear? @@ -1608,7 +1622,7 @@ void cdecl cmsCalcL16Params(int nSamples, LPL16PARAMS p); void cdecl cmsCalcCLUT16Params(int nSamples, int InputChan, int OutputChan, LPL16PARAMS p); void cdecl cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan, - BOOL lUseTetrahedral, LPL16PARAMS p); + LCMSBOOL lUseTetrahedral, LPL16PARAMS p); WORD cdecl cmsLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p); Fixed32 cdecl cmsLinearInterpFixed(WORD Value1, WORD LutTable[], LPL16PARAMS p); @@ -1692,18 +1706,18 @@ // Gray axes fixup. Only on v2 8-bit Lab LUT - BOOL FixGrayAxes; - - - // Parameters used for curve creation - - LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS]; + LCMSBOOL FixGrayAxes; + + + // Parameters used for curve creation + + LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS]; }; // LUT, FAR* LPLUT; -BOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries); +LCMSBOOL cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries); // CRC of gamma tables @@ -1721,7 +1735,7 @@ void cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max); void cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max); -BOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda); +LCMSBOOL cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda); void cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints); LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints); @@ -1755,19 +1769,19 @@ void cdecl cmsFreeMatShaper(LPMATSHAPER MatShaper); void cdecl cmsEvalMatShaper(LPMATSHAPER MatShaper, WORD In[], WORD Out[]); -BOOL cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile); - -LPMATSHAPER cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile); -LPMATSHAPER cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile); +LCMSBOOL cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile); + +LPMATSHAPER cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile); +LPMATSHAPER cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile); // White Point & Primary chromas handling -BOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll); -BOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt); -BOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt); - -BOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile); +LCMSBOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll); +LCMSBOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt); +LCMSBOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt); + +LCMSBOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile); // Inter-PCS conversion routines. They assume D50 as white point. void cdecl cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3]); @@ -1782,7 +1796,7 @@ LPcmsNAMEDCOLORLIST cdecl cmsAllocNamedColorList(int n); int cdecl cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSignature sig); void cdecl cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST List); -BOOL cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]); +LCMSBOOL cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]); // I/O @@ -1804,7 +1818,7 @@ icColorSpaceSignature PCS; icRenderingIntent RenderingIntent; icUInt32Number flags; - icUInt32Number attributes; + icUInt32Number attributes; cmsCIEXYZ Illuminant; // Additions for V4 profiles @@ -1826,23 +1840,23 @@ char PhysicalFile[MAX_PATH]; - BOOL IsWrite; - BOOL SaveAs8Bits; + LCMSBOOL IsWrite; + LCMSBOOL SaveAs8Bits; struct tm Created; // I/O handlers - size_t (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc); - - BOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset); - BOOL (* Close)(struct _lcms_iccprofile_struct* Icc); - size_t (* Tell)(struct _lcms_iccprofile_struct* Icc); - BOOL (* Grow)(struct _lcms_iccprofile_struct* Icc, size_t amount); + size_t (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc); + + LCMSBOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset); + LCMSBOOL (* Close)(struct _lcms_iccprofile_struct* Icc); + size_t (* Tell)(struct _lcms_iccprofile_struct* Icc); + LCMSBOOL (* Grow)(struct _lcms_iccprofile_struct* Icc, size_t amount); // Writting - BOOL (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr); + LCMSBOOL (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr); size_t UsedSpace; @@ -1854,7 +1868,7 @@ cmsHPROFILE cdecl _cmsCreateProfilePlaceholder(void); // Search into tag dictionary -icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, BOOL lSignalError); +icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError); // Search for a particular tag, replace if found or add new one else LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init); @@ -1870,6 +1884,7 @@ // These macros unpack format specifiers into integers +#define T_DITHER(s) (((s)>>22)&1) #define T_COLORSPACE(s) (((s)>>16)&31) #define T_SWAPFIRST(s) (((s)>>14)&1) #define T_FLAVOR(s) (((s)>>13)&1) @@ -1966,7 +1981,7 @@ // Flag for transform involving v4 profiles - BOOL lInputV4Lab, lOutputV4Lab; + LCMSBOOL lInputV4Lab, lOutputV4Lab; // 1-pixel cache @@ -1976,7 +1991,7 @@ double AdaptationState; // Figure for v4 incomplete state of adaptation - LCMS_RWLOCK_T rwlock; + LCMS_RWLOCK_T rwlock; } _cmsTRANSFORM,FAR *_LPcmsTRANSFORM; @@ -2013,7 +2028,7 @@ // Clamping & Gamut handling -BOOL cdecl _cmsEndPointsBySpace(icColorSpaceSignature Space, +LCMSBOOL cdecl _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black, int *nOutputs); WORD * cdecl _cmsWhiteBySpace(icColorSpaceSignature Space); @@ -2042,7 +2057,7 @@ LPLUT cdecl _cmsPrecalculateGamutCheck(cmsHTRANSFORM h); // Hot fixes bad profiles -BOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p); +LCMSBOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p); // Marks LUT as 8 bit on input LPLUT cdecl _cmsBlessLUT8(LPLUT Lut); @@ -2060,6 +2075,10 @@ // Build a tone curve for K->K' if possible (only works on CMYK) LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints); +// Validates a LUT +LCMSBOOL cdecl _cmsValidateLUT(LPLUT NewLUT); + + // These are two VITAL macros, from converting between 8 and 16 bit // representation. @@ -2077,3 +2096,4 @@ #endif #endif +