aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/lcms2/src
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2023-12-21 15:05:38 +0100
committerGitHub <noreply@github.com>2023-12-21 15:05:38 +0100
commite98bcbc74422492351c51646dba3849a138a8ffc (patch)
tree38ad7a09b1f9c201ce8a7e3d69f2017388769224 /contrib/libs/lcms2/src
parent559d7083cd8378cb25b9e966dedcca21d413e338 (diff)
downloadydb-e98bcbc74422492351c51646dba3849a138a8ffc.tar.gz
Import libs 1 (#590)
* Import libs 1 * Add new file without extension * Add file missed in export config
Diffstat (limited to 'contrib/libs/lcms2/src')
-rw-r--r--contrib/libs/lcms2/src/cmsalpha.c28
-rw-r--r--contrib/libs/lcms2/src/cmscgats.c499
-rw-r--r--contrib/libs/lcms2/src/cmscnvrt.c43
-rw-r--r--contrib/libs/lcms2/src/cmserr.c7
-rw-r--r--contrib/libs/lcms2/src/cmsgamma.c28
-rw-r--r--contrib/libs/lcms2/src/cmsgmt.c4
-rw-r--r--contrib/libs/lcms2/src/cmsio0.c31
-rw-r--r--contrib/libs/lcms2/src/cmsio1.c12
-rw-r--r--contrib/libs/lcms2/src/cmslut.c11
-rw-r--r--contrib/libs/lcms2/src/cmsnamed.c250
-rw-r--r--contrib/libs/lcms2/src/cmsopt.c16
-rw-r--r--contrib/libs/lcms2/src/cmspack.c185
-rw-r--r--contrib/libs/lcms2/src/cmsplugin.c21
-rw-r--r--contrib/libs/lcms2/src/cmsps2.c191
-rw-r--r--contrib/libs/lcms2/src/cmssamp.c2
-rw-r--r--contrib/libs/lcms2/src/cmstypes.c273
-rw-r--r--contrib/libs/lcms2/src/cmsvirt.c137
-rw-r--r--contrib/libs/lcms2/src/cmsxform.c15
-rw-r--r--contrib/libs/lcms2/src/lcms2_internal.h7
19 files changed, 1416 insertions, 344 deletions
diff --git a/contrib/libs/lcms2/src/cmsalpha.c b/contrib/libs/lcms2/src/cmsalpha.c
index 806577f994..7422256ca3 100644
--- a/contrib/libs/lcms2/src/cmsalpha.c
+++ b/contrib/libs/lcms2/src/cmsalpha.c
@@ -402,7 +402,7 @@ static cmsFormatterAlphaFn FormattersAlpha[6][6] = {
// This function computes the distance from each component to the next one in bytes.
static
-void ComputeIncrementsForChunky(cmsUInt32Number Format,
+cmsBool ComputeIncrementsForChunky(cmsUInt32Number Format,
cmsUInt32Number ComponentStartingOrder[],
cmsUInt32Number ComponentPointerIncrements[])
{
@@ -416,7 +416,7 @@ void ComputeIncrementsForChunky(cmsUInt32Number Format,
// Sanity check
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
- return;
+ return FALSE;
memset(channels, 0, sizeof(channels));
@@ -453,13 +453,15 @@ void ComputeIncrementsForChunky(cmsUInt32Number Format,
for (i = 0; i < extra; i++)
ComponentStartingOrder[i] = channels[i + nchannels];
+
+ return TRUE;
}
// On planar configurations, the distance is the stride added to any non-negative
static
-void ComputeIncrementsForPlanar(cmsUInt32Number Format,
+cmsBool ComputeIncrementsForPlanar(cmsUInt32Number Format,
cmsUInt32Number BytesPerPlane,
cmsUInt32Number ComponentStartingOrder[],
cmsUInt32Number ComponentPointerIncrements[])
@@ -473,7 +475,7 @@ void ComputeIncrementsForPlanar(cmsUInt32Number Format,
// Sanity check
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
- return;
+ return FALSE;
memset(channels, 0, sizeof(channels));
@@ -509,29 +511,29 @@ void ComputeIncrementsForPlanar(cmsUInt32Number Format,
for (i = 0; i < extra; i++)
ComponentStartingOrder[i] = channels[i + nchannels];
+
+ return TRUE;
}
// Dispatcher por chunky and planar RGB
static
-void ComputeComponentIncrements(cmsUInt32Number Format,
+cmsBool ComputeComponentIncrements(cmsUInt32Number Format,
cmsUInt32Number BytesPerPlane,
cmsUInt32Number ComponentStartingOrder[],
cmsUInt32Number ComponentPointerIncrements[])
{
if (T_PLANAR(Format)) {
- ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements);
+ return ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements);
}
else {
- ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements);
+ return ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements);
}
}
-
-
// Handles extra channels copying alpha if requested by the flags
void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
void* out,
@@ -565,9 +567,11 @@ void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
if (nExtra == 0)
return;
- // Compute the increments
- ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements);
- ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements);
+ // Compute the increments
+ if (!ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements))
+ return;
+ if (!ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements))
+ return;
// Check for conversions 8, 16, half, float, dbl
copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
diff --git a/contrib/libs/lcms2/src/cmscgats.c b/contrib/libs/lcms2/src/cmscgats.c
index 51fc2a6e28..bccbf58c10 100644
--- a/contrib/libs/lcms2/src/cmscgats.c
+++ b/contrib/libs/lcms2/src/cmscgats.c
@@ -58,7 +58,7 @@ typedef enum {
SEOF, // End of stream
SSYNERROR, // Syntax error found on stream
- // Keywords
+ // IT8 symbols
SBEGIN_DATA,
SBEGIN_DATA_FORMAT,
@@ -66,7 +66,19 @@ typedef enum {
SEND_DATA_FORMAT,
SKEYWORD,
SDATA_FORMAT_ID,
- SINCLUDE
+ SINCLUDE,
+
+ // Cube symbols
+
+ SDOMAIN_MAX,
+ SDOMAIN_MIN,
+ S_LUT1D_SIZE,
+ S_LUT1D_INPUT_RANGE,
+ S_LUT3D_SIZE,
+ S_LUT3D_INPUT_RANGE,
+ S_LUT_IN_VIDEO_RANGE,
+ S_LUT_OUT_VIDEO_RANGE,
+ STITLE
} SYMBOL;
@@ -149,6 +161,10 @@ typedef struct struct_it8 {
cmsUInt32Number TablesCount; // How many tables in this stream
cmsUInt32Number nTable; // The actual table
+ // Partser type
+ cmsBool IsCUBE;
+
+ // Tables
TABLE Tab[MAXTABLES];
// Memory management
@@ -208,8 +224,8 @@ typedef struct {
} KEYWORD;
-// The keyword->symbol translation table. Sorting is required.
-static const KEYWORD TabKeys[] = {
+// The keyword->symbol translation tables. Sorting is required.
+static const KEYWORD TabKeysIT8[] = {
{"$INCLUDE", SINCLUDE}, // This is an extension!
{".INCLUDE", SINCLUDE}, // This is an extension!
@@ -222,7 +238,25 @@ static const KEYWORD TabKeys[] = {
{"KEYWORD", SKEYWORD}
};
-#define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD))
+#define NUMKEYS_IT8 (sizeof(TabKeysIT8)/sizeof(KEYWORD))
+
+static const KEYWORD TabKeysCUBE[] = {
+
+ {"DOMAIN_MAX", SDOMAIN_MAX },
+ {"DOMAIN_MIN", SDOMAIN_MIN },
+ {"LUT_1D_SIZE", S_LUT1D_SIZE },
+ {"LUT_1D_INPUT_RANGE", S_LUT1D_INPUT_RANGE },
+ {"LUT_3D_SIZE", S_LUT3D_SIZE },
+ {"LUT_3D_INPUT_RANGE", S_LUT3D_INPUT_RANGE },
+ {"LUT_IN_VIDEO_RANGE", S_LUT_IN_VIDEO_RANGE },
+ {"LUT_OUT_VIDEO_RANGE", S_LUT_OUT_VIDEO_RANGE },
+ {"TITLE", STITLE }
+
+};
+
+#define NUMKEYS_CUBE (sizeof(TabKeysCUBE)/sizeof(KEYWORD))
+
+
// Predefined properties
@@ -426,7 +460,7 @@ void StringCat(string* s, const char* c)
static
cmsBool isseparator(int c)
{
- return (c == ' ') || (c == '\t') ;
+ return (c == ' ') || (c == '\t');
}
// Checks whatever c is a valid identifier char
@@ -447,7 +481,7 @@ cmsBool isidchar(int c)
static
cmsBool isfirstidchar(int c)
{
- return !isdigit(c) && ismiddle(c);
+ return c != '-' && !isdigit(c) && ismiddle(c);
}
// Guess whether the supplied path looks like an absolute path
@@ -486,13 +520,13 @@ cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffe
// Already absolute?
if (isabsolutepath(relPath)) {
- strncpy(buffer, relPath, MaxLen);
+ memcpy(buffer, relPath, MaxLen);
buffer[MaxLen-1] = 0;
return TRUE;
}
// No, search for last
- strncpy(buffer, basePath, MaxLen);
+ memcpy(buffer, basePath, MaxLen);
buffer[MaxLen-1] = 0;
tail = strrchr(buffer, DIR_CHAR);
@@ -574,10 +608,10 @@ void NextCh(cmsIT8* it8)
// Try to see if current identifier is a keyword, if so return the referred symbol
static
-SYMBOL BinSrchKey(const char *id)
+SYMBOL BinSrchKey(const char *id, int NumKeys, const KEYWORD* TabKeys)
{
int l = 1;
- int r = NUMKEYS;
+ int r = NumKeys;
int x, res;
while (r >= l)
@@ -747,7 +781,7 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer)
}
-// Reads a string, special case to avoid infinite resursion on .include
+// Reads a string, special case to avoid infinite recursion on .include
static
void InStringSymbol(cmsIT8* it8)
{
@@ -804,7 +838,9 @@ void InSymbol(cmsIT8* it8)
} while (isidchar(it8->ch));
- key = BinSrchKey(StringPtr(it8->id));
+ key = BinSrchKey(StringPtr(it8->id),
+ it8->IsCUBE ? NUMKEYS_CUBE : NUMKEYS_IT8,
+ it8->IsCUBE ? TabKeysCUBE : TabKeysIT8);
if (key == SUNDEFINED) it8->sy = SIDENT;
else it8->sy = key;
@@ -913,6 +949,7 @@ void InSymbol(cmsIT8* it8)
snprintf(buffer, sizeof(buffer), it8 ->DoubleFormatter, it8->dnum);
}
+ StringClear(it8->id);
StringCat(it8->id, buffer);
do {
@@ -942,7 +979,7 @@ void InSymbol(cmsIT8* it8)
// Next line
case '\r':
NextCh(it8);
- if (it8 ->ch == '\n')
+ if (it8->ch == '\n')
NextCh(it8);
it8->sy = SEOLN;
it8->lineno++;
@@ -1263,7 +1300,12 @@ KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *S
// This may work for editing properties
- // return SynError(it8, "duplicate key <%s>", Key);
+ if (cmsstrcasecmp(Key, "NUMBER_OF_FIELDS") == 0 ||
+ cmsstrcasecmp(Key, "NUMBER_OF_SETS") == 0) {
+
+ SynError(it8, "duplicate key <%s>", Key);
+ return NULL;
+ }
}
else {
@@ -1384,6 +1426,8 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
it8->MemoryBlock = NULL;
it8->MemorySink = NULL;
+ it8->IsCUBE = FALSE;
+
it8 ->nTable = 0;
it8->ContextID = ContextID;
@@ -1665,7 +1709,7 @@ char* GetData(cmsIT8* it8, int nSet, int nField)
int nSamples = t -> nSamples;
int nPatches = t -> nPatches;
- if (nSet >= nPatches || nField >= nSamples)
+ if (nSet < 0 || nSet >= nPatches || nField < 0 || nField >= nSamples)
return NULL;
if (!t->Data) return NULL;
@@ -1850,11 +1894,14 @@ void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
WriteStr(fp, " ");
nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
- for (i = 0; i < nSamples; i++) {
+ if (nSamples <= t->nSamples) {
- WriteStr(fp, t->DataFormat[i]);
- WriteStr(fp, ((i == (nSamples-1)) ? "\n" : "\t"));
- }
+ for (i = 0; i < nSamples; i++) {
+
+ WriteStr(fp, t->DataFormat[i]);
+ WriteStr(fp, ((i == (nSamples - 1)) ? "\n" : "\t"));
+ }
+ }
WriteStr (fp, "END_DATA_FORMAT\n");
}
@@ -1864,39 +1911,42 @@ void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
static
void WriteData(SAVESTREAM* fp, cmsIT8* it8)
{
- int i, j;
+ int i, j, nPatches;
TABLE* t = GetTable(it8);
if (!t->Data) return;
WriteStr (fp, "BEGIN_DATA\n");
- t->nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
+ nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
- for (i = 0; i < t-> nPatches; i++) {
+ if (nPatches <= t->nPatches) {
- WriteStr(fp, " ");
+ for (i = 0; i < nPatches; i++) {
- for (j = 0; j < t->nSamples; j++) {
+ WriteStr(fp, " ");
- char *ptr = t->Data[i*t->nSamples+j];
+ for (j = 0; j < t->nSamples; j++) {
- if (ptr == NULL) WriteStr(fp, "\"\"");
- else {
- // If value contains whitespace, enclose within quote
+ char* ptr = t->Data[i * t->nSamples + j];
- if (strchr(ptr, ' ') != NULL) {
+ if (ptr == NULL) WriteStr(fp, "\"\"");
+ else {
+ // If value contains whitespace, enclose within quote
- WriteStr(fp, "\"");
- WriteStr(fp, ptr);
- WriteStr(fp, "\"");
- }
- else
- WriteStr(fp, ptr);
- }
+ if (strchr(ptr, ' ') != NULL) {
- WriteStr(fp, ((j == (t->nSamples-1)) ? "\n" : "\t"));
- }
+ WriteStr(fp, "\"");
+ WriteStr(fp, ptr);
+ WriteStr(fp, "\"");
+ }
+ else
+ WriteStr(fp, ptr);
+ }
+
+ WriteStr(fp, ((j == (t->nSamples - 1)) ? "\n" : "\t"));
+ }
+ }
}
WriteStr (fp, "END_DATA\n");
}
@@ -1917,15 +1967,29 @@ cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
for (i=0; i < it8 ->TablesCount; i++) {
- cmsIT8SetTable(hIT8, i);
- WriteHeader(it8, &sd);
- WriteDataFormat(&sd, it8);
- WriteData(&sd, it8);
+ TABLE* t;
+
+ if (cmsIT8SetTable(hIT8, i) < 0) goto Error;
+
+ /**
+ * Check for wrong data
+ */
+ t = GetTable(it8);
+ if (t->Data == NULL) goto Error;
+ if (t->DataFormat == NULL) goto Error;
+
+ WriteHeader(it8, &sd);
+ WriteDataFormat(&sd, it8);
+ WriteData(&sd, it8);
}
if (fclose(sd.stream) != 0) return FALSE;
-
return TRUE;
+
+Error:
+ fclose(sd.stream);
+ return FALSE;
+
}
@@ -2302,78 +2366,72 @@ void CookPointers(cmsIT8* it8)
int idField, i;
char* Fld;
cmsUInt32Number j;
- cmsUInt32Number nOldTable = it8 ->nTable;
+ cmsUInt32Number nOldTable = it8->nTable;
- for (j=0; j < it8 ->TablesCount; j++) {
+ for (j = 0; j < it8->TablesCount; j++) {
- TABLE* t = it8 ->Tab + j;
+ TABLE* t = it8->Tab + j;
- t -> SampleID = 0;
- it8 ->nTable = j;
-
- for (idField = 0; idField < t -> nSamples; idField++)
- {
- if (t ->DataFormat == NULL){
- SynError(it8, "Undefined DATA_FORMAT");
- return;
- }
-
- Fld = t->DataFormat[idField];
- if (!Fld) continue;
-
-
- if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
-
- t -> SampleID = idField;
- }
+ t->SampleID = 0;
+ it8->nTable = j;
- // "LABEL" is an extension. It keeps references to forward tables
-
- if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
+ for (idField = 0; idField < t->nSamples; idField++)
+ {
+ if (t->DataFormat == NULL) {
+ SynError(it8, "Undefined DATA_FORMAT");
+ return;
+ }
- // Search for table references...
- for (i = 0; i < t->nPatches; i++) {
+ Fld = t->DataFormat[idField];
+ if (!Fld) continue;
- char* Label = GetData(it8, i, idField);
- if (Label) {
+ if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
- cmsUInt32Number k;
+ t->SampleID = idField;
+ }
- // This is the label, search for a table containing
- // this property
+ // "LABEL" is an extension. It keeps references to forward tables
- for (k = 0; k < it8->TablesCount; k++) {
+ if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
- TABLE* Table = it8->Tab + k;
- KEYVALUE* p;
+ // Search for table references...
+ for (i = 0; i < t->nPatches; i++) {
- if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
+ char* Label = GetData(it8, i, idField);
- // Available, keep type and table
- char Buffer[256];
+ if (Label) {
- char* Type = p->Value;
- int nTable = (int)k;
+ cmsUInt32Number k;
- snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type);
+ // This is the label, search for a table containing
+ // this property
- SetData(it8, i, idField, Buffer);
- }
- }
+ for (k = 0; k < it8->TablesCount; k++) {
+ TABLE* Table = it8->Tab + k;
+ KEYVALUE* p;
- }
+ if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
- }
+ // Available, keep type and table
+ char Buffer[256];
+ char* Type = p->Value;
+ int nTable = (int)k;
- }
+ snprintf(Buffer, 255, "%s %d %s", Label, nTable, Type);
- }
- }
+ SetData(it8, i, idField, Buffer);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
- it8 ->nTable = nOldTable;
+ it8->nTable = nOldTable;
}
// Try to infere if the file is a CGATS/IT8 file at all. Read first line
@@ -2464,7 +2522,7 @@ cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cm
if (it8->MemoryBlock == NULL)
{
cmsIT8Free(hIT8);
- return FALSE;
+ return NULL;
}
strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
@@ -2476,7 +2534,7 @@ cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cm
if (!ParseIT8(it8, type-1)) {
cmsIT8Free(hIT8);
- return FALSE;
+ return NULL;
}
CookPointers(it8);
@@ -2573,17 +2631,17 @@ cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyN
}
- Props = (char**)AllocChunk(it8, sizeof(char*) * n);
- if (Props != NULL) {
+ Props = (char**)AllocChunk(it8, sizeof(char*) * n);
+ if (Props != NULL) {
- // Pass#2 - Fill pointers
- n = 0;
- for (p = t->HeaderList; p != NULL; p = p->Next) {
- Props[n++] = p->Keyword;
- }
+ // Pass#2 - Fill pointers
+ n = 0;
+ for (p = t->HeaderList; p != NULL; p = p->Next) {
+ Props[n++] = p->Keyword;
+ }
- }
- *PropertyNames = Props;
+ }
+ *PropertyNames = Props;
return n;
}
@@ -2943,3 +3001,236 @@ void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter)
it8 ->DoubleFormatter[sizeof(it8 ->DoubleFormatter)-1] = 0;
}
+
+static
+cmsBool ReadNumbers(cmsIT8* cube, int n, cmsFloat64Number* arr)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+
+ if (cube->sy == SINUM)
+ arr[i] = cube->inum;
+ else
+ if (cube->sy == SDNUM)
+ arr[i] = cube->dnum;
+ else
+ return SynError(cube, "Number expected");
+
+ InSymbol(cube);
+ }
+
+ return CheckEOLN(cube);
+}
+
+static
+cmsBool ParseCube(cmsIT8* cube, cmsStage** Shaper, cmsStage** CLUT, char title[])
+{
+ cmsFloat64Number domain_min[3] = { 0, 0, 0 };
+ cmsFloat64Number domain_max[3] = { 1.0, 1.0, 1.0 };
+ cmsFloat64Number check_0_1[2] = { 0, 1.0 };
+ int shaper_size = 0;
+ int lut_size = 0;
+ int i;
+
+ InSymbol(cube);
+
+ while (cube->sy != SEOF) {
+ switch (cube->sy)
+ {
+ // Set profile description
+ case STITLE:
+ InSymbol(cube);
+ if (!Check(cube, SSTRING, "Title string expected")) return FALSE;
+ memcpy(title, StringPtr(cube->str), MAXSTR);
+ title[MAXSTR - 1] = 0;
+ InSymbol(cube);
+ break;
+
+ // Define domain
+ case SDOMAIN_MIN:
+ InSymbol(cube);
+ if (!ReadNumbers(cube, 3, domain_min)) return FALSE;
+ break;
+
+ case SDOMAIN_MAX:
+ InSymbol(cube);
+ if (!ReadNumbers(cube, 3, domain_max)) return FALSE;
+ break;
+
+ // Define shaper
+ case S_LUT1D_SIZE:
+ InSymbol(cube);
+ if (!Check(cube, SINUM, "Shaper size expected")) return FALSE;
+ shaper_size = cube->inum;
+ InSymbol(cube);
+ break;
+
+ // Deefine CLUT
+ case S_LUT3D_SIZE:
+ InSymbol(cube);
+ if (!Check(cube, SINUM, "LUT size expected")) return FALSE;
+ lut_size = cube->inum;
+ InSymbol(cube);
+ break;
+
+ // Range. If present, has to be 0..1.0
+ case S_LUT1D_INPUT_RANGE:
+ case S_LUT3D_INPUT_RANGE:
+ InSymbol(cube);
+ if (!ReadNumbers(cube, 2, check_0_1)) return FALSE;
+ if (check_0_1[0] != 0 || check_0_1[1] != 1.0) {
+ return SynError(cube, "Unsupported format");
+ }
+ break;
+
+ case SEOLN:
+ InSymbol(cube);
+ break;
+
+ default:
+ case S_LUT_IN_VIDEO_RANGE:
+ case S_LUT_OUT_VIDEO_RANGE:
+ return SynError(cube, "Unsupported format");
+
+ // Read and create tables
+ case SINUM:
+ case SDNUM:
+
+ if (shaper_size > 0) {
+
+ cmsToneCurve* curves[3];
+ cmsFloat32Number* shapers = (cmsFloat32Number*)_cmsMalloc(cube->ContextID, 3 * shaper_size * sizeof(cmsFloat32Number));
+ if (shapers == NULL) return FALSE;
+
+ for (i = 0; i < shaper_size; i++) {
+
+ cmsFloat64Number nums[3];
+
+ if (!ReadNumbers(cube, 3, nums)) return FALSE;
+
+ shapers[i + 0] = (cmsFloat32Number) ((nums[0] - domain_min[0]) / (domain_max[0] - domain_min[0]));
+ shapers[i + 1 * shaper_size] = (cmsFloat32Number) ((nums[1] - domain_min[1]) / (domain_max[1] - domain_min[1]));
+ shapers[i + 2 * shaper_size] = (cmsFloat32Number) ((nums[2] - domain_min[2]) / (domain_max[2] - domain_min[2]));
+ }
+
+ for (i = 0; i < 3; i++) {
+
+ curves[i] = cmsBuildTabulatedToneCurveFloat(cube->ContextID, shaper_size,
+ &shapers[i * shaper_size]);
+ if (curves[i] == NULL) return FALSE;
+ }
+
+ *Shaper = cmsStageAllocToneCurves(cube->ContextID, 3, curves);
+
+ cmsFreeToneCurveTriple(curves);
+ }
+
+ if (lut_size > 0) {
+
+ int nodes = lut_size * lut_size * lut_size;
+
+ cmsFloat32Number* lut_table = _cmsMalloc(cube->ContextID, nodes * 3 * sizeof(cmsFloat32Number));
+ if (lut_table == NULL) return FALSE;
+
+ for (i = 0; i < nodes; i++) {
+
+ cmsFloat64Number nums[3];
+
+ if (!ReadNumbers(cube, 3, nums)) return FALSE;
+
+ lut_table[i * 3 + 2] = (cmsFloat32Number) ((nums[0] - domain_min[0]) / (domain_max[0] - domain_min[0]));
+ lut_table[i * 3 + 1] = (cmsFloat32Number) ((nums[1] - domain_min[1]) / (domain_max[1] - domain_min[1]));
+ lut_table[i * 3 + 0] = (cmsFloat32Number) ((nums[2] - domain_min[2]) / (domain_max[2] - domain_min[2]));
+ }
+
+ *CLUT = cmsStageAllocCLutFloat(cube->ContextID, lut_size, 3, 3, lut_table);
+ _cmsFree(cube->ContextID, lut_table);
+ }
+
+ if (!Check(cube, SEOF, "Extra symbols found in file")) return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// Share the parser to read .cube format and create RGB devicelink profiles
+cmsHPROFILE CMSEXPORT cmsCreateDeviceLinkFromCubeFileTHR(cmsContext ContextID, const char* cFileName)
+{
+ cmsHPROFILE hProfile = NULL;
+ cmsIT8* cube = NULL;
+ cmsPipeline* Pipeline = NULL;
+ cmsStage* CLUT = NULL;
+ cmsStage* Shaper = NULL;
+ cmsMLU* DescriptionMLU = NULL;
+ char title[MAXSTR];
+
+ _cmsAssert(cFileName != NULL);
+
+ cube = (cmsIT8*) cmsIT8Alloc(ContextID);
+ if (!cube) return NULL;
+
+ cube->IsCUBE = TRUE;
+ cube->FileStack[0]->Stream = fopen(cFileName, "rt");
+
+ if (!cube->FileStack[0]->Stream) goto Done;
+
+ strncpy(cube->FileStack[0]->FileName, cFileName, cmsMAX_PATH - 1);
+ cube->FileStack[0]->FileName[cmsMAX_PATH - 1] = 0;
+
+ if (!ParseCube(cube, &Shaper, &CLUT, title)) goto Done;
+
+ // Success on parsing, let's create the profile
+ hProfile = cmsCreateProfilePlaceholder(ContextID);
+ if (!hProfile) goto Done;
+
+ cmsSetProfileVersion(hProfile, 4.4);
+
+ cmsSetDeviceClass(hProfile, cmsSigLinkClass);
+ cmsSetColorSpace(hProfile, cmsSigRgbData);
+ cmsSetPCS(hProfile, cmsSigRgbData);
+
+ cmsSetHeaderRenderingIntent(hProfile, INTENT_PERCEPTUAL);
+
+ // Creates a Pipeline to hold CLUT and shaper
+ Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
+ if (Pipeline == NULL) goto Done;
+
+ // Populates the pipeline
+ if (Shaper != NULL) {
+ if (!cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Shaper))
+ goto Done;
+ }
+
+ if (CLUT != NULL) {
+ if (!cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT))
+ goto Done;
+ }
+
+ // Propagate the description. We put no copyright because we know
+ // nothing on the copyrighted state of the .cube
+ DescriptionMLU = cmsMLUalloc(ContextID, 1);
+ if (!cmsMLUsetUTF8(DescriptionMLU, cmsNoLanguage, cmsNoCountry, title)) goto Done;
+
+ // Flush the tags
+ if (!cmsWriteTag(hProfile, cmsSigProfileDescriptionTag, DescriptionMLU)) goto Done;
+ if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, (void*)Pipeline)) goto Done;
+
+Done:
+
+ if (DescriptionMLU != NULL)
+ cmsMLUfree(DescriptionMLU);
+
+ if (Pipeline != NULL)
+ cmsPipelineFree(Pipeline);
+
+ cmsIT8Free((cmsHANDLE) cube);
+
+ return hProfile;
+}
+
+cmsHPROFILE CMSEXPORT cmsCreateDeviceLinkFromCubeFile(const char* cFileName)
+{
+ return cmsCreateDeviceLinkFromCubeFileTHR(NULL, cFileName);
+}
diff --git a/contrib/libs/lcms2/src/cmscnvrt.c b/contrib/libs/lcms2/src/cmscnvrt.c
index de63975427..f00c117337 100644
--- a/contrib/libs/lcms2/src/cmscnvrt.c
+++ b/contrib/libs/lcms2/src/cmscnvrt.c
@@ -715,6 +715,16 @@ int BlackPreservingGrayOnlySampler(CMSREGISTER const cmsUInt16Number In[], CMSRE
return TRUE;
}
+
+// Check whatever the profile is a CMYK->CMYK devicelink
+static
+cmsBool is_cmyk_devicelink(cmsHPROFILE hProfile)
+{
+ return cmsGetDeviceClass(hProfile) == cmsSigLinkClass &&
+ cmsGetColorSpace(hProfile) == cmsSigCmykData &&
+ cmsGetColorSpace(hProfile) == cmsSigCmykData;
+}
+
// This is the entry for black-preserving K-only intents, which are non-ICC
static
cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
@@ -747,14 +757,16 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
lastProfilePos = nProfiles - 1;
hLastProfile = hProfiles[lastProfilePos];
- while (lastProfilePos > 1)
+ // Skip CMYK->CMYK devicelinks on ending
+ while (is_cmyk_devicelink(hLastProfile))
{
- hLastProfile = hProfiles[--lastProfilePos];
- if (cmsGetColorSpace(hLastProfile) != cmsSigCmykData ||
- cmsGetDeviceClass(hLastProfile) != cmsSigLinkClass)
+ if (lastProfilePos < 2)
break;
+
+ hLastProfile = hProfiles[--lastProfilePos];
}
+
preservationProfilesCount = lastProfilePos + 1;
// Check for non-cmyk profiles
@@ -771,7 +783,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
// Create a LUT holding normal ICC transform
bp.cmyk2cmyk = DefaultICCintents(ContextID,
- preservationProfilesCount,
+ preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@@ -783,7 +795,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
// Now, compute the tone curve
bp.KTone = _cmsBuildKToneCurve(ContextID,
4096,
- preservationProfilesCount,
+ preservationProfilesCount,
ICCIntents,
hProfiles,
BPC,
@@ -973,13 +985,14 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext ContextID,
lastProfilePos = nProfiles - 1;
hLastProfile = hProfiles[lastProfilePos];
- while (lastProfilePos > 1)
- {
+ // Skip CMYK->CMYK devicelinks on ending
+ while (is_cmyk_devicelink(hLastProfile))
+ {
+ if (lastProfilePos < 2)
+ break;
+
hLastProfile = hProfiles[--lastProfilePos];
- if (cmsGetColorSpace(hLastProfile) != cmsSigCmykData ||
- cmsGetDeviceClass(hLastProfile) != cmsSigLinkClass)
- break;
- }
+ }
preservationProfilesCount = lastProfilePos + 1;
@@ -1148,8 +1161,7 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUIn
cmsIntentsList* pt;
cmsUInt32Number nIntents;
-
- for (nIntents=0, pt = ctx->Intents; pt != NULL; pt = pt -> Next)
+ for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next)
{
if (nIntents < nMax) {
if (Codes != NULL)
@@ -1162,7 +1174,7 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUIn
nIntents++;
}
- for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next)
+ for (pt = ctx->Intents; pt != NULL; pt = pt -> Next)
{
if (nIntents < nMax) {
if (Codes != NULL)
@@ -1174,6 +1186,7 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUIn
nIntents++;
}
+
return nIntents;
}
diff --git a/contrib/libs/lcms2/src/cmserr.c b/contrib/libs/lcms2/src/cmserr.c
index ccb40f9261..811c63502d 100644
--- a/contrib/libs/lcms2/src/cmserr.c
+++ b/contrib/libs/lcms2/src/cmserr.c
@@ -72,7 +72,7 @@ long int CMSEXPORT cmsfilelength(FILE* f)
//
// This is the interface to low-level memory management routines. By default a simple
// wrapping to malloc/free/realloc is provided, although there is a limit on the max
-// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent
+// amount of memory that can be reclaimed. This is mostly as a safety feature to prevent
// bogus or evil code to allocate huge blocks that otherwise lcms would never need.
#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U))
@@ -92,7 +92,8 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plug
static
void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size)
{
- if (size > MAX_MEMORY_FOR_ALLOC) return NULL; // Never allow over maximum
+ // Never allow 0 or over maximum
+ if (size == 0 || size > MAX_MEMORY_FOR_ALLOC) return NULL;
return (void*) malloc(size);
@@ -234,7 +235,7 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data)
// NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure.
// Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the
- // context internal data should be malloce'd by using those functions.
+ // context internal data should be malloc'ed by using those functions.
if (Data == NULL) {
struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID;
diff --git a/contrib/libs/lcms2/src/cmsgamma.c b/contrib/libs/lcms2/src/cmsgamma.c
index 1031fc15e0..a8a8946205 100644
--- a/contrib/libs/lcms2/src/cmsgamma.c
+++ b/contrib/libs/lcms2/src/cmsgamma.c
@@ -300,6 +300,10 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsUInt32Number nEnt
return p;
Error:
+ for (i=0; i < nSegments; i++) {
+ if (p ->Segments && p ->Segments[i].SampledPoints) _cmsFree(ContextID, p ->Segments[i].SampledPoints);
+ if (p ->SegInterp && p ->SegInterp[i]) _cmsFree(ContextID, p ->SegInterp[i]);
+ }
if (p -> SegInterp) _cmsFree(ContextID, p -> SegInterp);
if (p -> Segments) _cmsFree(ContextID, p -> Segments);
if (p -> Evals) _cmsFree(ContextID, p -> Evals);
@@ -593,10 +597,16 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
case 6:
e = Params[1]*R + Params[2];
- if (e < 0)
- Val = Params[3];
- else
- Val = pow(e, Params[0]) + Params[3];
+ // On gamma 1.0, don't clamp
+ if (Params[0] == 1.0) {
+ Val = e + Params[3];
+ }
+ else {
+ if (e < 0)
+ Val = Params[3];
+ else
+ Val = pow(e, Params[0]) + Params[3];
+ }
break;
// ((Y - c) ^1/Gamma - b) / a
@@ -1491,13 +1501,13 @@ cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Num
return (sum / n); // The mean
}
+// Retrieve segments on tone curves
-// Retrieve parameters on one-segment tone curves
-
-cmsFloat64Number* CMSEXPORT cmsGetToneCurveParams(const cmsToneCurve* t)
+const cmsCurveSegment* CMSEXPORT cmsGetToneCurveSegment(cmsInt32Number n, const cmsToneCurve* t)
{
_cmsAssert(t != NULL);
- if (t->nSegments != 1) return NULL;
- return t->Segments[0].Params;
+ if (n < 0 || n >= (cmsInt32Number) t->nSegments) return NULL;
+ return t->Segments + n;
}
+
diff --git a/contrib/libs/lcms2/src/cmsgmt.c b/contrib/libs/lcms2/src/cmsgmt.c
index 5109bfaefb..64573476c8 100644
--- a/contrib/libs/lcms2/src/cmsgmt.c
+++ b/contrib/libs/lcms2/src/cmsgmt.c
@@ -219,7 +219,7 @@ int GamutSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Nu
cmsUInt16Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS];
cmsFloat64Number dE1, dE2, ErrorRatio;
- // Assume in-gamut by default.
+ // Assume in-gamut by default. NEVER READ, USED FOR DEBUG PURPOSES.
ErrorRatio = 1.0;
// Convert input to Lab
@@ -596,7 +596,7 @@ cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,
// Actually, doing that "well" is quite hard, since every component may behave completely different.
// Since the true point of this function is to detect suitable optimizations, I am imposing some requirements
// that simplifies things: only RGB, and only profiles that can got in both directions.
-// The algorithm obtains Y from a syntetical gray R=G=B. Then least squares fitting is used to estimate gamma.
+// The algorithm obtains Y from a synthetical gray R=G=B. Then least squares fitting is used to estimate gamma.
// For gamma close to 1.0, RGB is linear. On profiles not supported, -1 is returned.
cmsFloat64Number CMSEXPORT cmsDetectRGBProfileGamma(cmsHPROFILE hProfile, cmsFloat64Number threshold)
diff --git a/contrib/libs/lcms2/src/cmsio0.c b/contrib/libs/lcms2/src/cmsio0.c
index 945140a3c8..75442e664d 100644
--- a/contrib/libs/lcms2/src/cmsio0.c
+++ b/contrib/libs/lcms2/src/cmsio0.c
@@ -530,7 +530,21 @@ cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
// Set default version
Icc ->Version = 0x02100000;
-
+
+ // Set default CMM (that's me!)
+ Icc ->CMM = lcmsSignature;
+
+ // Set default creator
+ // Created by LittleCMS (that's me!)
+ Icc ->creator = lcmsSignature;
+
+ // Set default platform
+#ifdef CMS_IS_WINDOWS_
+ Icc ->platform = cmsSigMicrosoft;
+#else
+ Icc ->platform = cmsSigMacintosh;
+#endif
+
// Set default device class
Icc->DeviceClass = cmsSigDisplayClass;
@@ -784,16 +798,18 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
}
// Adjust endianness of the used parameters
+ Icc -> CMM = _cmsAdjustEndianess32(Header.cmmId);
Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass);
Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace);
Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs);
Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent);
+ Icc -> platform = (cmsPlatformSignature)_cmsAdjustEndianess32(Header.platform);
Icc -> flags = _cmsAdjustEndianess32(Header.flags);
Icc -> manufacturer = _cmsAdjustEndianess32(Header.manufacturer);
Icc -> model = _cmsAdjustEndianess32(Header.model);
Icc -> creator = _cmsAdjustEndianess32(Header.creator);
-
+
_cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes);
Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version));
@@ -893,7 +909,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace)
cmsUInt32Number Count;
Header.size = _cmsAdjustEndianess32(UsedSpace);
- Header.cmmId = _cmsAdjustEndianess32(lcmsSignature);
+ Header.cmmId = _cmsAdjustEndianess32(Icc ->CMM);
Header.version = _cmsAdjustEndianess32(Icc ->Version);
Header.deviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Icc -> DeviceClass);
@@ -905,11 +921,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace)
Header.magic = _cmsAdjustEndianess32(cmsMagicNumber);
-#ifdef CMS_IS_WINDOWS_
- Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMicrosoft);
-#else
- Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMacintosh);
-#endif
+ Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(Icc -> platform);
Header.flags = _cmsAdjustEndianess32(Icc -> flags);
Header.manufacturer = _cmsAdjustEndianess32(Icc -> manufacturer);
@@ -925,8 +937,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace)
Header.illuminant.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y));
Header.illuminant.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z));
- // Created by LittleCMS (that's me!)
- Header.creator = _cmsAdjustEndianess32(lcmsSignature);
+ Header.creator = _cmsAdjustEndianess32(Icc ->creator);
memset(&Header.reserved, 0, sizeof(Header.reserved));
diff --git a/contrib/libs/lcms2/src/cmsio1.c b/contrib/libs/lcms2/src/cmsio1.c
index b923739f60..c75b454cd5 100644
--- a/contrib/libs/lcms2/src/cmsio1.c
+++ b/contrib/libs/lcms2/src/cmsio1.c
@@ -578,7 +578,7 @@ Error:
return NULL;
}
-// Create an output MPE LUT from agiven profile. Version mismatches are handled here
+// Create an output MPE LUT from a given profile. Version mismatches are handled here
cmsPipeline* CMSEXPORT _cmsReadOutputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent)
{
cmsTagTypeSignature OriginalType;
@@ -1027,3 +1027,13 @@ cmsUInt32Number CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoT
return cmsMLUgetASCII(mlu, LanguageCode, CountryCode, Buffer, BufferSize);
}
+
+cmsUInt32Number CMSEXPORT cmsGetProfileInfoUTF8(cmsHPROFILE hProfile, cmsInfoType Info,
+ const char LanguageCode[3], const char CountryCode[3],
+ char* Buffer, cmsUInt32Number BufferSize)
+{
+ const cmsMLU* mlu = GetInfo(hProfile, Info);
+ if (mlu == NULL) return 0;
+
+ return cmsMLUgetUTF8(mlu, LanguageCode, CountryCode, Buffer, BufferSize);
+}
diff --git a/contrib/libs/lcms2/src/cmslut.c b/contrib/libs/lcms2/src/cmslut.c
index 77977fc6c9..1ea61a806b 100644
--- a/contrib/libs/lcms2/src/cmslut.c
+++ b/contrib/libs/lcms2/src/cmslut.c
@@ -475,6 +475,9 @@ cmsUInt32Number CubeSize(const cmsUInt32Number Dims[], cmsUInt32Number b)
if (rv > UINT_MAX / dim) return 0;
}
+ // Again, prevent overflow
+ if (rv > UINT_MAX / 15) return 0;
+
return rv;
}
@@ -814,7 +817,13 @@ cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler
cmsUInt32Number nInputs, nOutputs;
cmsUInt32Number* nSamples;
cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
- _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
+ _cmsStageCLutData* clut;
+
+ if (mpe == NULL) return FALSE;
+
+ clut = (_cmsStageCLutData*)mpe->Data;
+
+ if (clut == NULL) return FALSE;
nSamples = clut->Params ->nSamples;
nInputs = clut->Params ->nInputs;
diff --git a/contrib/libs/lcms2/src/cmsnamed.c b/contrib/libs/lcms2/src/cmsnamed.c
index 54d1abf913..f368fe2483 100644
--- a/contrib/libs/lcms2/src/cmsnamed.c
+++ b/contrib/libs/lcms2/src/cmsnamed.c
@@ -200,17 +200,145 @@ void strFrom16(char str[3], cmsUInt16Number n)
str[0] = (char)(n >> 8);
str[1] = (char)n;
str[2] = (char)0;
+}
+
+
+// Convert from UTF8 to wchar, returns len.
+static
+cmsUInt32Number decodeUTF8(wchar_t* out, const char* in)
+{
+ cmsUInt32Number codepoint = 0;
+ cmsUInt32Number size = 0;
+
+ while (*in)
+ {
+ cmsUInt8Number ch = (cmsUInt8Number) *in;
+
+ if (ch <= 0x7f)
+ {
+ codepoint = ch;
+ }
+ else if (ch <= 0xbf)
+ {
+ codepoint = (codepoint << 6) | (ch & 0x3f);
+ }
+ else if (ch <= 0xdf)
+ {
+ codepoint = ch & 0x1f;
+ }
+ else if (ch <= 0xef)
+ {
+ codepoint = ch & 0x0f;
+ }
+ else
+ {
+ codepoint = ch & 0x07;
+ }
+
+ in++;
+
+ if (((*in & 0xc0) != 0x80) && (codepoint <= 0x10ffff))
+ {
+ if (sizeof(wchar_t) > 2)
+ {
+ if (out) *out++ = (wchar_t) codepoint;
+ size++;
+ }
+ else
+ if (codepoint > 0xffff)
+ {
+ if (out)
+ {
+ *out++ = (wchar_t)(0xd800 + (codepoint >> 10));
+ *out++ = (wchar_t)(0xdc00 + (codepoint & 0x03ff));
+ size += 2;
+ }
+ }
+ else
+ if (codepoint < 0xd800 || codepoint >= 0xe000)
+ {
+ if (out) *out++ = (wchar_t) codepoint;
+ size++;
+ }
+ }
+ }
+
+ return size;
+}
+
+// Convert from wchar_t to UTF8
+static
+cmsUInt32Number encodeUTF8(char* out, const wchar_t* in, cmsUInt32Number max_wchars, cmsUInt32Number max_chars)
+{
+ cmsUInt32Number codepoint = 0;
+ cmsUInt32Number size = 0;
+ cmsUInt32Number len_w = 0;
+
+ while (*in && len_w < max_wchars)
+ {
+ if (*in >= 0xd800 && *in <= 0xdbff)
+ codepoint = ((*in - 0xd800) << 10) + 0x10000;
+ else
+ {
+ if (*in >= 0xdc00 && *in <= 0xdfff)
+ codepoint |= *in - 0xdc00;
+ else
+ codepoint = *in;
+
+ if (codepoint <= 0x7f)
+ {
+ if (out && (size + 1 < max_chars)) *out++ = (char)codepoint;
+ size++;
+ }
+
+ else if (codepoint <= 0x7ff)
+ {
+ if (out && (max_chars > 0) && (size + 2 < max_chars))
+ {
+ *out++ = (char)(cmsUInt32Number)(0xc0 | ((codepoint >> 6) & 0x1f));
+ *out++ = (char)(cmsUInt32Number)(0x80 | (codepoint & 0x3f));
+ }
+ size += 2;
+ }
+ else if (codepoint <= 0xffff)
+ {
+ if (out && (max_chars > 0) && (size + 3 < max_chars))
+ {
+ *out++ = (char)(cmsUInt32Number)(0xe0 | ((codepoint >> 12) & 0x0f));
+ *out++ = (char)(cmsUInt32Number)(0x80 | ((codepoint >> 6) & 0x3f));
+ *out++ = (char)(cmsUInt32Number)(0x80 | (codepoint & 0x3f));
+ }
+ size += 3;
+ }
+ else
+ {
+ if (out && (max_chars > 0) && (size + 4 < max_chars))
+ {
+ *out++ = (char)(cmsUInt32Number)(0xf0 | ((codepoint >> 18) & 0x07));
+ *out++ = (char)(cmsUInt32Number)(0x80 | ((codepoint >> 12) & 0x3f));
+ *out++ = (char)(cmsUInt32Number)(0x80 | ((codepoint >> 6) & 0x3f));
+ *out++ = (char)(cmsUInt32Number)(0x80 | (codepoint & 0x3f));
+ }
+ size += 4;
+ }
+
+ codepoint = 0;
+ }
+ in++; len_w++;
+ }
+
+ return size;
}
// Add an ASCII entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61)
// In the case the user explicitly sets an empty string, we force a \0
cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
{
- cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString);
+ cmsUInt32Number i, len = (cmsUInt32Number)strlen(ASCIIString);
wchar_t* WStr;
cmsBool rc;
- cmsUInt16Number Lang = strTo16(LanguageCode);
+ cmsUInt16Number Lang = strTo16(LanguageCode);
cmsUInt16Number Cntry = strTo16(CountryCode);
if (mlu == NULL) return FALSE;
@@ -218,22 +346,56 @@ cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const
// len == 0 would prevent operation, so we set a empty string pointing to zero
if (len == 0)
{
- len = 1;
+ wchar_t empty = 0;
+ return AddMLUBlock(mlu, sizeof(wchar_t), &empty, Lang, Cntry);
}
- WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len, sizeof(wchar_t));
+ WStr = (wchar_t*)_cmsCalloc(mlu->ContextID, len, sizeof(wchar_t));
if (WStr == NULL) return FALSE;
- for (i=0; i < len; i++)
- WStr[i] = (wchar_t) ASCIIString[i];
+ for (i = 0; i < len; i++)
+ WStr[i] = (wchar_t)ASCIIString[i];
- rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry);
+ rc = AddMLUBlock(mlu, len * sizeof(wchar_t), WStr, Lang, Cntry);
- _cmsFree(mlu ->ContextID, WStr);
+ _cmsFree(mlu->ContextID, WStr);
return rc;
}
+// Add an UTF8 entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61)
+// In the case the user explicitly sets an empty string, we force a \0
+cmsBool CMSEXPORT cmsMLUsetUTF8(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* UTF8String)
+{
+ cmsUInt32Number UTF8len;
+ wchar_t* WStr;
+ cmsBool rc;
+ cmsUInt16Number Lang = strTo16(LanguageCode);
+ cmsUInt16Number Cntry = strTo16(CountryCode);
+
+ if (mlu == NULL) return FALSE;
+
+ if (*UTF8String == '\0')
+ {
+ wchar_t empty = 0;
+ return AddMLUBlock(mlu, sizeof(wchar_t), &empty, Lang, Cntry);
+ }
+
+ // Len excluding terminator 0
+ UTF8len = decodeUTF8(NULL, UTF8String);
+
+ // Get space for dest
+ WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, UTF8len, sizeof(wchar_t));
+ if (WStr == NULL) return FALSE;
+
+ decodeUTF8(WStr, UTF8String);
+
+ rc = AddMLUBlock(mlu, UTF8len * sizeof(wchar_t), WStr, Lang, Cntry);
+
+ _cmsFree(mlu ->ContextID, WStr);
+ return rc;
+}
+
// We don't need any wcs support library
static
cmsUInt32Number mywcslen(const wchar_t *s)
@@ -372,7 +534,7 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
if (v->StrW + v->Len > mlu->PoolSize) return NULL;
- return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
+ return (wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
}
@@ -410,10 +572,12 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
// Precess each character
for (i=0; i < ASCIIlen; i++) {
- if (Wide[i] == 0)
- Buffer[i] = 0;
+ wchar_t wc = Wide[i];
+
+ if (wc < 0xff)
+ Buffer[i] = (char)wc;
else
- Buffer[i] = (char) Wide[i];
+ Buffer[i] = '?';
}
// We put a termination "\0"
@@ -421,6 +585,46 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
return ASCIIlen + 1;
}
+
+// Obtain a UTF8 representation of the wide string. Setting buffer to NULL returns the len
+cmsUInt32Number CMSEXPORT cmsMLUgetUTF8(const cmsMLU* mlu,
+ const char LanguageCode[3], const char CountryCode[3],
+ char* Buffer, cmsUInt32Number BufferSize)
+{
+ const wchar_t *Wide;
+ cmsUInt32Number StrLen = 0;
+ cmsUInt32Number UTF8len;
+
+ cmsUInt16Number Lang = strTo16(LanguageCode);
+ cmsUInt16Number Cntry = strTo16(CountryCode);
+
+ // Sanitize
+ if (mlu == NULL) return 0;
+
+ // Get WideChar
+ Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
+ if (Wide == NULL) return 0;
+
+ UTF8len = encodeUTF8(NULL, Wide, StrLen / sizeof(wchar_t), BufferSize);
+
+ // Maybe we want only to know the len?
+ if (Buffer == NULL) return UTF8len + 1; // Note the zero at the end
+
+ // No buffer size means no data
+ if (BufferSize <= 0) return 0;
+
+ // Some clipping may be required
+ if (BufferSize < UTF8len + 1)
+ UTF8len = BufferSize - 1;
+
+ // Process it
+ encodeUTF8(Buffer, Wide, StrLen / sizeof(wchar_t), BufferSize);
+
+ // We put a termination "\0"
+ Buffer[UTF8len] = 0;
+ return UTF8len + 1;
+}
+
// Obtain a wide representation of the MLU, on depending on current locale settings
cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
const char LanguageCode[3], const char CountryCode[3],
@@ -441,12 +645,12 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
// Maybe we want only to know the len?
if (Buffer == NULL) return StrLen + sizeof(wchar_t);
- // No buffer size means no data
- if (BufferSize <= 0) return 0;
+ // Invalid buffer size means no data
+ if (BufferSize < sizeof(wchar_t)) return 0;
// Some clipping may be required
if (BufferSize < StrLen + sizeof(wchar_t))
- StrLen = BufferSize - + sizeof(wchar_t);
+ StrLen = BufferSize - sizeof(wchar_t);
memmove(Buffer, Wide, StrLen);
Buffer[StrLen / sizeof(wchar_t)] = 0;
@@ -814,13 +1018,19 @@ void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq)
{
cmsUInt32Number i;
- for (i=0; i < pseq ->n; i++) {
- if (pseq ->seq[i].Manufacturer != NULL) cmsMLUfree(pseq ->seq[i].Manufacturer);
- if (pseq ->seq[i].Model != NULL) cmsMLUfree(pseq ->seq[i].Model);
- if (pseq ->seq[i].Description != NULL) cmsMLUfree(pseq ->seq[i].Description);
+ if (pseq == NULL)
+ return;
+
+ if (pseq ->seq != NULL) {
+ for (i=0; i < pseq ->n; i++) {
+ if (pseq ->seq[i].Manufacturer != NULL) cmsMLUfree(pseq ->seq[i].Manufacturer);
+ if (pseq ->seq[i].Model != NULL) cmsMLUfree(pseq ->seq[i].Model);
+ if (pseq ->seq[i].Description != NULL) cmsMLUfree(pseq ->seq[i].Description);
+ }
+
+ _cmsFree(pseq ->ContextID, pseq ->seq);
}
- if (pseq ->seq != NULL) _cmsFree(pseq ->ContextID, pseq ->seq);
_cmsFree(pseq -> ContextID, pseq);
}
diff --git a/contrib/libs/lcms2/src/cmsopt.c b/contrib/libs/lcms2/src/cmsopt.c
index b3d831cbd9..4038088b2b 100644
--- a/contrib/libs/lcms2/src/cmsopt.c
+++ b/contrib/libs/lcms2/src/cmsopt.c
@@ -183,6 +183,7 @@ cmsBool isFloatMatrixIdentity(const cmsMAT3* a)
return TRUE;
}
+
// if two adjacent matrices are found, multiply them.
static
cmsBool _MultiplyMatrix(cmsPipeline* Lut)
@@ -1113,14 +1114,17 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
// Store result in curve
for (t=0; t < OriginalLut ->InputChannels; t++)
- Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0);
+ {
+ if (Trans[t]->Table16 != NULL)
+ Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0);
+ }
}
// Slope-limit the obtained curves
for (t = 0; t < OriginalLut ->InputChannels; t++)
SlopeLimiting(Trans[t]);
- // Check for validity
+ // Check for validity. lIsLinear is here for debug purposes
lIsSuitable = TRUE;
lIsLinear = TRUE;
for (t=0; (lIsSuitable && (t < OriginalLut ->InputChannels)); t++) {
@@ -1724,6 +1728,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
_cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1);
+ if (Matrix1->InputChannels != 3 || Matrix1->OutputChannels != 3) return FALSE;
+
// Copy the matrix to our result
memcpy(&res, Data->Double, sizeof(res));
@@ -1768,7 +1774,7 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
_cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);
// In this particular optimization, cache does not help as it takes more time to deal with
- // the cache that with the pixel handling
+ // the cache than with the pixel handling
*dwFlags |= cmsFLAGS_NOCACHE;
// Setup the optimizarion routines
@@ -1924,8 +1930,8 @@ cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
// Named color pipelines cannot be optimized
for (mpe = cmsPipelineGetPtrToFirstStage(*PtrLut);
mpe != NULL;
- mpe = cmsStageNext(mpe)) {
- if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
+ mpe = cmsStageNext(mpe)) {
+ if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
}
// Try to get rid of identities and trivial conversions.
diff --git a/contrib/libs/lcms2/src/cmspack.c b/contrib/libs/lcms2/src/cmspack.c
index 5a96712a48..c191896c08 100644
--- a/contrib/libs/lcms2/src/cmspack.c
+++ b/contrib/libs/lcms2/src/cmspack.c
@@ -2952,6 +2952,108 @@ cmsUInt8Number* PackFloatFrom16(CMSREGISTER _cmsTRANSFORM* info,
// --------------------------------------------------------------------------------------------------------
static
+cmsUInt8Number* PackBytesFromFloat(_cmsTRANSFORM* info,
+ cmsFloat32Number wOut[],
+ cmsUInt8Number* output,
+ cmsUInt32Number Stride)
+{
+ cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
+ cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
+ cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
+ cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
+ cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
+ cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
+ cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+ cmsUInt8Number* swap1 = (cmsUInt8Number*)output;
+ cmsFloat64Number v = 0;
+ cmsUInt8Number vv = 0;
+ cmsUInt32Number i, start = 0;
+
+ if (ExtraFirst)
+ start = Extra;
+
+ for (i = 0; i < nChan; i++) {
+
+ cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
+
+ v = wOut[index] * 65535.0;
+
+ if (Reverse)
+ v = 65535.0 - v;
+
+ vv = FROM_16_TO_8(_cmsQuickSaturateWord(v));
+
+ if (Planar)
+ ((cmsUInt8Number*)output)[(i + start) * Stride] = vv;
+ else
+ ((cmsUInt8Number*)output)[i + start] = vv;
+ }
+
+
+ if (Extra == 0 && SwapFirst) {
+
+ memmove(swap1 + 1, swap1, (nChan - 1) * sizeof(cmsUInt8Number));
+ *swap1 = vv;
+ }
+
+ if (T_PLANAR(info->OutputFormat))
+ return output + sizeof(cmsUInt8Number);
+ else
+ return output + (nChan + Extra) * sizeof(cmsUInt8Number);
+}
+
+static
+cmsUInt8Number* PackWordsFromFloat(_cmsTRANSFORM* info,
+ cmsFloat32Number wOut[],
+ cmsUInt8Number* output,
+ cmsUInt32Number Stride)
+{
+ cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
+ cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
+ cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
+ cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
+ cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
+ cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
+ cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+ cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
+ cmsFloat64Number v = 0;
+ cmsUInt16Number vv = 0;
+ cmsUInt32Number i, start = 0;
+
+ if (ExtraFirst)
+ start = Extra;
+
+ for (i = 0; i < nChan; i++) {
+
+ cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
+
+ v = wOut[index] * 65535.0;
+
+ if (Reverse)
+ v = 65535.0 - v;
+
+ vv = _cmsQuickSaturateWord(v);
+
+ if (Planar)
+ ((cmsUInt16Number*)output)[(i + start) * Stride] = vv;
+ else
+ ((cmsUInt16Number*)output)[i + start] = vv;
+ }
+
+ if (Extra == 0 && SwapFirst) {
+
+ memmove(swap1 + 1, swap1, (nChan - 1) * sizeof(cmsUInt16Number));
+ *swap1 = vv;
+ }
+
+ if (T_PLANAR(info->OutputFormat))
+ return output + sizeof(cmsUInt16Number);
+ else
+ return output + (nChan + Extra) * sizeof(cmsUInt16Number);
+}
+
+
+static
cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
cmsFloat32Number wOut[],
cmsUInt8Number* output,
@@ -3114,6 +3216,77 @@ cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info,
}
+static
+cmsUInt8Number* PackEncodedBytesLabV2FromFloat(_cmsTRANSFORM* Info,
+ cmsFloat32Number wOut[],
+ cmsUInt8Number* output,
+ cmsUInt32Number Stride)
+{
+ cmsCIELab Lab;
+ cmsUInt16Number wlab[3];
+
+ Lab.L = (cmsFloat64Number)(wOut[0] * 100.0);
+ Lab.a = (cmsFloat64Number)(wOut[1] * 255.0 - 128.0);
+ Lab.b = (cmsFloat64Number)(wOut[2] * 255.0 - 128.0);
+
+ cmsFloat2LabEncoded(wlab, &Lab);
+
+ if (T_PLANAR(Info -> OutputFormat)) {
+
+ Stride /= PixelSize(Info->OutputFormat);
+
+ output[0] = wlab[0] >> 8;
+ output[Stride] = wlab[1] >> 8;
+ output[Stride*2] = wlab[2] >> 8;
+
+ return output + 1;
+ }
+ else {
+
+ output[0] = wlab[0] >> 8;
+ output[1] = wlab[1] >> 8;
+ output[2] = wlab[2] >> 8;
+
+ return output + (3 + T_EXTRA(Info ->OutputFormat));
+ }
+}
+
+static
+cmsUInt8Number* PackEncodedWordsLabV2FromFloat(_cmsTRANSFORM* Info,
+ cmsFloat32Number wOut[],
+ cmsUInt8Number* output,
+ cmsUInt32Number Stride)
+{
+ cmsCIELab Lab;
+ cmsUInt16Number wlab[3];
+
+ Lab.L = (cmsFloat64Number)(wOut[0] * 100.0);
+ Lab.a = (cmsFloat64Number)(wOut[1] * 255.0 - 128.0);
+ Lab.b = (cmsFloat64Number)(wOut[2] * 255.0 - 128.0);
+
+ cmsFloat2LabEncodedV2(wlab, &Lab);
+
+ if (T_PLANAR(Info -> OutputFormat)) {
+
+ Stride /= PixelSize(Info->OutputFormat);
+
+ ((cmsUInt16Number*) output)[0] = wlab[0];
+ ((cmsUInt16Number*) output)[Stride] = wlab[1];
+ ((cmsUInt16Number*) output)[Stride*2] = wlab[2];
+
+ return output + sizeof(cmsUInt16Number);
+ }
+ else {
+
+ ((cmsUInt16Number*) output)[0] = wlab[0];
+ ((cmsUInt16Number*) output)[1] = wlab[1];
+ ((cmsUInt16Number*) output)[2] = wlab[2];
+
+ return output + (3 + T_EXTRA(Info ->OutputFormat)) * sizeof(cmsUInt16Number);
+ }
+}
+
+
// From 0..1 range to 0..MAX_ENCODEABLE_XYZ
static
cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info,
@@ -3647,10 +3820,20 @@ static const cmsFormattersFloat OutputFormattersFloat[] = {
{ TYPE_Lab_DBL, ANYPLANAR|ANYEXTRA, PackLabDoubleFromFloat},
{ TYPE_XYZ_DBL, ANYPLANAR|ANYEXTRA, PackXYZDoubleFromFloat},
+ { TYPE_LabV2_8, ANYPLANAR|ANYEXTRA, PackEncodedBytesLabV2FromFloat},
+ { TYPE_LabV2_16, ANYPLANAR|ANYEXTRA, PackEncodedWordsLabV2FromFloat},
+
{ FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|
ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackFloatsFromFloat },
{ FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|
ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackDoublesFromFloat },
+
+ { BYTES_SH(2), ANYPLANAR|
+ ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackWordsFromFloat },
+
+ { BYTES_SH(1), ANYPLANAR|
+ ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackBytesFromFloat },
+
#ifndef CMS_NO_HALF_SUPPORT
{ FLOAT_SH(1)|BYTES_SH(2),
ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackHalfFromFloat },
@@ -3861,7 +4044,7 @@ cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsU
cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);
- cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
+ cmsInt32Number nOutputChans = cmsChannelsOfColorSpace(ColorSpace);
cmsUInt32Number Float = lIsFloat ? 1U : 0;
// Unsupported color space?
diff --git a/contrib/libs/lcms2/src/cmsplugin.c b/contrib/libs/lcms2/src/cmsplugin.c
index 3876506dac..e278832813 100644
--- a/contrib/libs/lcms2/src/cmsplugin.c
+++ b/contrib/libs/lcms2/src/cmsplugin.c
@@ -364,12 +364,7 @@ cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ)
// from Fixed point 8.8 to double
cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8)
{
- cmsUInt8Number msb, lsb;
-
- lsb = (cmsUInt8Number) (fixed8 & 0xff);
- msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff);
-
- return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0));
+ return fixed8 / 256.0;
}
cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)
@@ -381,19 +376,7 @@ cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)
// from Fixed point 15.16 to double
cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32)
{
- cmsFloat64Number floater, sign, mid;
- int Whole, FracPart;
-
- sign = (fix32 < 0 ? -1 : 1);
- fix32 = abs(fix32);
-
- Whole = (cmsUInt16Number)(fix32 >> 16) & 0xffff;
- FracPart = (cmsUInt16Number)(fix32 & 0xffff);
-
- mid = (cmsFloat64Number) FracPart / 65536.0;
- floater = (cmsFloat64Number) Whole + mid;
-
- return sign * floater;
+ return fix32 / 65536.0;
}
// from double to Fixed point 15.16
diff --git a/contrib/libs/lcms2/src/cmsps2.c b/contrib/libs/lcms2/src/cmsps2.c
index 9aeea36d4f..eea1629d35 100644
--- a/contrib/libs/lcms2/src/cmsps2.c
+++ b/contrib/libs/lcms2/src/cmsps2.c
@@ -431,48 +431,46 @@ void EmitLab2XYZ(cmsIOHANDLER* m)
_cmsIOPrintf(m, "]\n");
}
-static
-void EmitSafeGuardBegin(cmsIOHANDLER* m, const char* name)
-{
- _cmsIOPrintf(m, "%%LCMS2: Save previous definition of %s on the operand stack\n", name);
- _cmsIOPrintf(m, "currentdict /%s known { /%s load } { null } ifelse\n", name, name);
-}
-static
-void EmitSafeGuardEnd(cmsIOHANDLER* m, const char* name, int depth)
-{
- _cmsIOPrintf(m, "%%LCMS2: Restore previous definition of %s\n", name);
- if (depth > 1) {
- // cycle topmost items on the stack to bring the previous definition to the front
- _cmsIOPrintf(m, "%d -1 roll ", depth);
- }
- _cmsIOPrintf(m, "dup null eq { pop currentdict /%s undef } { /%s exch def } ifelse\n", name, name);
-}
// Outputs a table of words. It does use 16 bits
static
-void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
+void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table)
{
cmsUInt32Number i;
cmsFloat64Number gamma;
- if (Table == NULL) return; // Error
+ /**
+ * On error, empty tables or lienar assume gamma 1.0
+ */
+ if (Table == NULL ||
+ Table->nEntries <= 0 ||
+ cmsIsToneCurveLinear(Table)) {
- if (Table ->nEntries <= 0) return; // Empty table
+ _cmsIOPrintf(m, "{ 1 } bind ");
+ return;
+ }
- // Suppress whole if identity
- if (cmsIsToneCurveLinear(Table)) return;
// Check if is really an exponential. If so, emit "exp"
gamma = cmsEstimateGamma(Table, 0.001);
if (gamma > 0) {
- _cmsIOPrintf(m, "/%s { %g exp } bind def\n", name, gamma);
+ _cmsIOPrintf(m, "{ %g exp } bind ", gamma);
return;
}
- EmitSafeGuardBegin(m, "lcms2gammatable");
- _cmsIOPrintf(m, "/lcms2gammatable [");
+ _cmsIOPrintf(m, "{ ");
+
+ // Bounds check
+ EmitRangeCheck(m);
+
+ // Emit intepolation code
+
+ // PostScript code Stack
+ // =============== ========================
+ // v
+ _cmsIOPrintf(m, " [");
for (i=0; i < Table->nEntries; i++) {
if (i % 10 == 0)
@@ -480,20 +478,8 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
_cmsIOPrintf(m, "%d ", Table->Table16[i]);
}
- _cmsIOPrintf(m, "] def\n");
+ _cmsIOPrintf(m, "] "); // v tab
-
- // Emit interpolation code
-
- // PostScript code Stack
- // =============== ========================
- // v
- _cmsIOPrintf(m, "/%s {\n ", name);
-
- // Bounds check
- EmitRangeCheck(m);
-
- _cmsIOPrintf(m, "\n //lcms2gammatable "); // v tab
_cmsIOPrintf(m, "dup "); // v tab tab
_cmsIOPrintf(m, "length 1 sub "); // v tab dom
_cmsIOPrintf(m, "3 -1 roll "); // tab dom v
@@ -520,9 +506,7 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
_cmsIOPrintf(m, "add "); // y
_cmsIOPrintf(m, "65535 div\n"); // result
- _cmsIOPrintf(m, "} bind def\n");
-
- EmitSafeGuardEnd(m, "lcms2gammatable", 1);
+ _cmsIOPrintf(m, " } bind ");
}
@@ -539,10 +523,10 @@ cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Numb
// Does write a set of gamma curves
static
-void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[], const char* nameprefix)
+void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[])
{
cmsUInt32Number i;
- static char buffer[2048];
+
for( i=0; i < n; i++ )
{
@@ -550,12 +534,10 @@ void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[], const cha
if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i-1]->nEntries, g[i]->nEntries)) {
- _cmsIOPrintf(m, "/%s%d /%s%d load def\n", nameprefix, i, nameprefix, i-1);
+ _cmsIOPrintf(m, "dup ");
}
else {
- snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, (int) i);
- buffer[sizeof(buffer)-1] = '\0';
- Emit1Gamma(m, g[i], buffer);
+ Emit1Gamma(m, g[i]);
}
}
@@ -679,18 +661,21 @@ void WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj,
sc.FixWhite = FixWhite;
sc.ColorSpace = ColorSpace;
- _cmsIOPrintf(m, "[");
+ if (sc.Pipeline != NULL && sc.Pipeline->Params != NULL) {
+
+ _cmsIOPrintf(m, "[");
- for (i=0; i < sc.Pipeline->Params->nInputs; i++)
- _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
+ for (i = 0; i < sc.Pipeline->Params->nInputs; i++)
+ _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
- _cmsIOPrintf(m, " [\n");
+ _cmsIOPrintf(m, " [\n");
- cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*) &sc, SAMPLER_INSPECT);
+ cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*)&sc, SAMPLER_INSPECT);
- _cmsIOPrintf(m, PostMin);
- _cmsIOPrintf(m, PostMaj);
- _cmsIOPrintf(m, "] ");
+ _cmsIOPrintf(m, PostMin);
+ _cmsIOPrintf(m, PostMaj);
+ _cmsIOPrintf(m, "] ");
+ }
}
@@ -704,11 +689,11 @@ int EmitCIEBasedA(cmsIOHANDLER* m, cmsToneCurve* Curve, cmsCIEXYZ* BlackPoint)
_cmsIOPrintf(m, "[ /CIEBasedA\n");
_cmsIOPrintf(m, " <<\n");
- EmitSafeGuardBegin(m, "lcms2gammaproc");
- Emit1Gamma(m, Curve, "lcms2gammaproc");
+ _cmsIOPrintf(m, "/DecodeA ");
+
+ Emit1Gamma(m, Curve);
- _cmsIOPrintf(m, "/DecodeA /lcms2gammaproc load\n");
- EmitSafeGuardEnd(m, "lcms2gammaproc", 3);
+ _cmsIOPrintf(m, " \n");
_cmsIOPrintf(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n");
_cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
@@ -732,19 +717,11 @@ int EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** Cu
_cmsIOPrintf(m, "[ /CIEBasedABC\n");
_cmsIOPrintf(m, "<<\n");
+ _cmsIOPrintf(m, "/DecodeABC [ ");
+
+ EmitNGamma(m, 3, CurveSet);
- EmitSafeGuardBegin(m, "lcms2gammaproc0");
- EmitSafeGuardBegin(m, "lcms2gammaproc1");
- EmitSafeGuardBegin(m, "lcms2gammaproc2");
- EmitNGamma(m, 3, CurveSet, "lcms2gammaproc");
- _cmsIOPrintf(m, "/DecodeABC [\n");
- _cmsIOPrintf(m, " /lcms2gammaproc0 load\n");
- _cmsIOPrintf(m, " /lcms2gammaproc1 load\n");
- _cmsIOPrintf(m, " /lcms2gammaproc2 load\n");
_cmsIOPrintf(m, "]\n");
- EmitSafeGuardEnd(m, "lcms2gammaproc2", 3);
- EmitSafeGuardEnd(m, "lcms2gammaproc1", 3);
- EmitSafeGuardEnd(m, "lcms2gammaproc0", 3);
_cmsIOPrintf(m, "/MatrixABC [ " );
@@ -776,11 +753,9 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Inte
{
const char* PreMaj;
const char* PostMaj;
- const char* PreMin, * PostMin;
+ const char* PreMin, *PostMin;
cmsStage* mpe;
- int i, numchans;
- static char buffer[2048];
-
+
mpe = Pipeline->Elements;
switch (cmsStageInputChannels(mpe)) {
@@ -808,34 +783,18 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Inte
if (cmsStageType(mpe) == cmsSigCurveSetElemType) {
- numchans = (int) cmsStageOutputChannels(mpe);
- for (i = 0; i < numchans; ++i) {
- snprintf(buffer, sizeof(buffer), "lcms2gammaproc%d", i);
- buffer[sizeof(buffer) - 1] = '\0';
- EmitSafeGuardBegin(m, buffer);
- }
- EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe), "lcms2gammaproc");
- _cmsIOPrintf(m, "/DecodeDEF [\n");
- for (i = 0; i < numchans; ++i) {
- snprintf(buffer, sizeof(buffer), " /lcms2gammaproc%d load\n", i);
- buffer[sizeof(buffer) - 1] = '\0';
- _cmsIOPrintf(m, buffer);
- }
+ _cmsIOPrintf(m, "/DecodeDEF [ ");
+ EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe));
_cmsIOPrintf(m, "]\n");
- for (i = numchans - 1; i >= 0; --i) {
- snprintf(buffer, sizeof(buffer), "lcms2gammaproc%d", i);
- buffer[sizeof(buffer) - 1] = '\0';
- EmitSafeGuardEnd(m, buffer, 3);
- }
- mpe = mpe->Next;
+ mpe = mpe ->Next;
}
if (cmsStageType(mpe) == cmsSigCLutElemType) {
- _cmsIOPrintf(m, "/Table ");
- WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature)0);
- _cmsIOPrintf(m, "]\n");
+ _cmsIOPrintf(m, "/Table ");
+ WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0);
+ _cmsIOPrintf(m, "]\n");
}
EmitLab2XYZ(m);
@@ -995,9 +954,9 @@ int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matr
for (j = 0; j < 3; j++)
Mat.v[i].n[j] *= MAX_ENCODEABLE_XYZ;
- rc = EmitCIEBasedABC(m, (cmsFloat64Number *)&Mat,
- _cmsStageGetPtrToCurveSet(Shaper),
- &BlackPointAdaptedToD50);
+ rc = EmitCIEBasedABC(m, (cmsFloat64Number *) &Mat,
+ _cmsStageGetPtrToCurveSet(Shaper),
+ &BlackPointAdaptedToD50);
}
else {
@@ -1024,10 +983,15 @@ int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number
hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, hLab, TYPE_Lab_DBL, Intent, 0);
+ cmsCloseProfile(hLab);
+
if (xform == NULL) return 0;
NamedColorList = cmsGetNamedColorList(xform);
- if (NamedColorList == NULL) return 0;
+ if (NamedColorList == NULL) {
+ cmsDeleteTransform(xform);
+ return 0;
+ }
_cmsIOPrintf(m, "<<\n");
_cmsIOPrintf(m, "(colorlistcomment) (%s)\n", "Named color CSA");
@@ -1036,7 +1000,6 @@ int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number
nColors = cmsNamedColorCount(NamedColorList);
-
for (i=0; i < nColors; i++) {
cmsUInt16Number In[1];
@@ -1051,12 +1014,9 @@ int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number
_cmsIOPrintf(m, " (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b);
}
-
-
_cmsIOPrintf(m, ">>\n");
cmsDeleteTransform(xform);
- cmsCloseProfile(hLab);
return 1;
}
@@ -1310,7 +1270,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
cmsUInt32Number InFrm = TYPE_Lab_16;
cmsUInt32Number RelativeEncodingIntent;
cmsColorSpaceSignature ColorSpace;
-
+ cmsStage* first;
hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
if (hLab == NULL) return 0;
@@ -1336,8 +1296,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
OutputFormat, RelativeEncodingIntent, 0);
cmsCloseProfile(hLab);
- if (xform == NULL) {
-
+ if (xform == NULL) {
cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation");
return 0;
}
@@ -1345,10 +1304,12 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
// Get a copy of the internal devicelink
v = (_cmsTRANSFORM*) xform;
DeviceLink = cmsPipelineDup(v ->Lut);
- if (DeviceLink == NULL) return 0;
-
+ if (DeviceLink == NULL) {
+ cmsDeleteTransform(xform);
+ return 0;
+ }
- // We need a CLUT
+ // We need a CLUT
dwFlags |= cmsFLAGS_FORCE_CLUT;
_cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
@@ -1375,8 +1336,10 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
_cmsIOPrintf(m, "/RenderTable ");
-
- WriteCLUT(m, cmsPipelineGetPtrToFirstStage(DeviceLink), "<", ">\n", "", "", lFixWhite, ColorSpace);
+ first = cmsPipelineGetPtrToFirstStage(DeviceLink);
+ if (first != NULL) {
+ WriteCLUT(m, first, "<", ">\n", "", "", lFixWhite, ColorSpace);
+ }
_cmsIOPrintf(m, " %d {} bind ", nChannels);
@@ -1385,7 +1348,6 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
_cmsIOPrintf(m, "]\n");
-
EmitIntent(m, Intent);
_cmsIOPrintf(m, ">>\n");
@@ -1448,7 +1410,10 @@ int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number
NamedColorList = cmsGetNamedColorList(xform);
- if (NamedColorList == NULL) return 0;
+ if (NamedColorList == NULL) {
+ cmsDeleteTransform(xform);
+ return 0;
+ }
_cmsIOPrintf(m, "<<\n");
_cmsIOPrintf(m, "(colorlistcomment) (%s) \n", "Named profile");
diff --git a/contrib/libs/lcms2/src/cmssamp.c b/contrib/libs/lcms2/src/cmssamp.c
index 4888f1ea88..0cee16a9ec 100644
--- a/contrib/libs/lcms2/src/cmssamp.c
+++ b/contrib/libs/lcms2/src/cmssamp.c
@@ -123,7 +123,7 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
// Convert black to Lab
cmsDoTransform(xform, Black, &Lab, 1);
- // Force it to be neutral, check for inconsistences
+ // Force it to be neutral, check for inconsistencies
Lab.a = Lab.b = 0;
if (Lab.L > 50 || Lab.L < 0) Lab.L = 0;
diff --git a/contrib/libs/lcms2/src/cmstypes.c b/contrib/libs/lcms2/src/cmstypes.c
index ec1909f8d3..8eabe1f079 100644
--- a/contrib/libs/lcms2/src/cmstypes.c
+++ b/contrib/libs/lcms2/src/cmstypes.c
@@ -93,7 +93,7 @@ cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient
return TRUE;
}
-// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons
+// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additions
// made by plug-ins and then the built-in defaults.
static
cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList)
@@ -925,6 +925,7 @@ static
void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
char* Text = NULL;
+ wchar_t* UnicodeString = NULL;
cmsMLU* mlu = NULL;
cmsUInt32Number AsciiCount;
cmsUInt32Number i, UnicodeCode, UnicodeCount;
@@ -944,7 +945,7 @@ void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHAND
if (SizeOfTag < AsciiCount) return NULL;
// All seems Ok, allocate the container
- mlu = cmsMLUalloc(self ->ContextID, 1);
+ mlu = cmsMLUalloc(self ->ContextID, 2);
if (mlu == NULL) return NULL;
// As many memory as size of tag
@@ -969,15 +970,30 @@ void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHAND
if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
SizeOfTag -= 2* sizeof(cmsUInt32Number);
- if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
+ if (UnicodeCount == 0 || SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
+
+ UnicodeString = (wchar_t*)_cmsMallocZero(self->ContextID, (UnicodeCount + 1) * sizeof(wchar_t));
+ if (UnicodeString == NULL) goto Done;
+
+ if (!_cmsReadWCharArray(io, UnicodeCount, UnicodeString)) {
+ _cmsFree(self->ContextID, (void*)UnicodeString);
+ goto Done;
+ }
+
+ UnicodeString[UnicodeCount] = 0;
- for (i=0; i < UnicodeCount; i++) {
- if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done;
+ if (!cmsMLUsetWide(mlu, cmsV2Unicode, cmsV2Unicode, UnicodeString)) {
+ _cmsFree(self->ContextID, (void*)UnicodeString);
+ goto Done;
}
+
+ _cmsFree(self->ContextID, (void*)UnicodeString);
+ UnicodeString = NULL;
+
SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number);
// Skip ScriptCode code if present. Some buggy profiles does have less
- // data that stricttly required. We need to skip it as this type may come
+ // data that strictly required. We need to skip it as this type may come
// embedded in other types.
if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) {
@@ -997,6 +1013,7 @@ Done:
return mlu;
Error:
+ if (UnicodeString) _cmsFree(self->ContextID, (void*)UnicodeString);
if (Text) _cmsFree(self ->ContextID, (void*) Text);
if (mlu) cmsMLUfree(mlu);
return NULL;
@@ -1049,7 +1066,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
// Get both representations.
cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, len * sizeof(char));
- cmsMLUgetWide(mlu, cmsNoLanguage, cmsNoCountry, Wide, len * sizeof(wchar_t));
+ cmsMLUgetWide(mlu, cmsV2Unicode, cmsV2Unicode, Wide, len * sizeof(wchar_t));
}
// Tell the real text len including the null terminator and padding
@@ -1548,8 +1565,6 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU
if (SizeOfTag == 0)
{
Block = NULL;
- NumOfWchar = 0;
-
}
else
{
@@ -1911,7 +1926,7 @@ Error:
// We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
static
-cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
cmsUInt32Number j, nTabSize, i;
cmsUInt8Number val;
@@ -1924,6 +1939,12 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
// Disassemble the LUT into components.
mpe = NewLUT -> Elements;
+
+ if (mpe == NULL) { // Should never be empty. Corrupted?
+ cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "empty LUT8 is not supported");
+ return FALSE;
+ }
+
if (mpe ->Type == cmsSigMatrixElemType) {
if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE;
@@ -2665,8 +2686,8 @@ cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
// If this is a table-based curve, use curve type even on V4
CurrentType = Type;
- if ((Curves[i] ->nSegments == 0)||
- ((Curves[i]->nSegments == 2) && (Curves[i] ->Segments[1].Type == 0)) )
+ if ((Curves[i] ->nSegments == 0) || // 16 bits tabulated
+ ((Curves[i]->nSegments == 3) && (Curves[i] ->Segments[1].Type == 0)) ) // Floating-point tabulated
CurrentType = cmsSigCurveType;
else
if (Curves[i] ->Segments[0].Type < 0)
@@ -4430,8 +4451,8 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
- if (InputChans == 0) goto Error;
- if (OutputChans == 0) goto Error;
+ if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) goto Error;
+ if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) goto Error;
if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
goto Error;
@@ -4452,7 +4473,7 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
clut = (_cmsStageCLutData*) mpe ->Data;
for (i=0; i < clut ->nEntries; i++) {
- if (!_cmsReadFloat32Number(io, &clut->Tab.TFloat[i])) goto Error;
+ if (!_cmsReadFloat32Number(io, &clut->Tab.TFloat[i])) goto Error;
}
*nItems = 1;
@@ -5221,11 +5242,13 @@ cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _c
}
Before = io ->Tell(io);
- e ->Offsets[i] = Before - BaseOffset;
+ if (e->Offsets != NULL)
+ e ->Offsets[i] = Before - BaseOffset;
if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE;
- e ->Sizes[i] = io ->Tell(io) - Before;
+ if (e->Sizes != NULL)
+ e ->Sizes[i] = io ->Tell(io) - Before;
return TRUE;
}
@@ -5470,6 +5493,216 @@ void Type_VideoSignal_Free(struct _cms_typehandler_struct* self, void* Ptr)
_cmsFree(self->ContextID, Ptr);
}
+
+// ********************************************************************************
+// Microsoft's MHC2 Type support
+// ********************************************************************************
+
+static
+void SetIdentity(cmsFloat64Number XYZ2XYZmatrix[3][4])
+{
+ XYZ2XYZmatrix[0][0] = 1.0; XYZ2XYZmatrix[0][1] = 0.0; XYZ2XYZmatrix[0][2] = 0.0; XYZ2XYZmatrix[0][3] = 0.0;
+ XYZ2XYZmatrix[1][0] = 0.0; XYZ2XYZmatrix[1][1] = 1.0; XYZ2XYZmatrix[1][2] = 0.0; XYZ2XYZmatrix[1][3] = 0.0;
+ XYZ2XYZmatrix[2][0] = 0.0; XYZ2XYZmatrix[2][1] = 0.0; XYZ2XYZmatrix[2][2] = 1.0; XYZ2XYZmatrix[2][3] = 0.0;
+}
+
+static
+cmsBool CloseEnough(cmsFloat64Number a, cmsFloat64Number b)
+{
+ return fabs(b - a) < (1.0 / 65535.0);
+}
+
+cmsBool IsIdentity(cmsFloat64Number XYZ2XYZmatrix[3][4])
+{
+ cmsFloat64Number Identity[3][4];
+ int i, j;
+
+ SetIdentity(Identity);
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 4; j++)
+ if (!CloseEnough(XYZ2XYZmatrix[i][j], Identity[i][j])) return FALSE;
+
+ return TRUE;
+}
+
+static
+void Type_MHC2_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+ cmsMHC2Type* mhc2 = (cmsMHC2Type*)Ptr;
+
+ if (mhc2->RedCurve != NULL) _cmsFree(self->ContextID, mhc2->RedCurve);
+ if (mhc2->GreenCurve != NULL) _cmsFree(self->ContextID, mhc2->GreenCurve);
+ if (mhc2->BlueCurve != NULL) _cmsFree(self->ContextID, mhc2->BlueCurve);
+
+ _cmsFree(self->ContextID, Ptr);
+}
+
+void* Type_MHC2_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+ cmsMHC2Type* mhc2 = _cmsDupMem(self->ContextID, Ptr, sizeof(cmsMHC2Type));
+
+ mhc2->RedCurve = _cmsDupMem(self->ContextID, mhc2->RedCurve, mhc2->CurveEntries*sizeof(cmsFloat64Number));
+ mhc2->GreenCurve = _cmsDupMem(self->ContextID, mhc2->GreenCurve, mhc2->CurveEntries * sizeof(cmsFloat64Number));
+ mhc2->BlueCurve = _cmsDupMem(self->ContextID, mhc2->BlueCurve, mhc2->CurveEntries * sizeof(cmsFloat64Number));
+
+ if (mhc2->RedCurve == NULL ||
+ mhc2->GreenCurve == NULL ||
+ mhc2->BlueCurve == NULL) {
+
+ Type_MHC2_Free(self, mhc2);
+ return NULL;
+ }
+
+ return mhc2;
+
+ cmsUNUSED_PARAMETER(n);
+}
+
+
+static
+cmsBool WriteDoubles(cmsIOHANDLER* io, cmsUInt32Number n, cmsFloat64Number* Values)
+{
+ cmsUInt32Number i;
+
+ for (i = 0; i < n; i++) {
+
+ if (!_cmsWrite15Fixed16Number(io, *Values++)) return FALSE;
+ }
+
+ return TRUE;
+}
+
+static
+cmsBool Type_MHC2_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+ cmsMHC2Type* mhc2 = (cmsMHC2Type*)Ptr;
+ cmsUInt32Number BaseOffset = io->Tell(io) - sizeof(_cmsTagBase);
+ cmsUInt32Number TablesOffsetPos;
+ cmsUInt32Number MatrixOffset;
+ cmsUInt32Number OffsetRedTable, OffsetGreenTable, OffsetBlueTable;
+
+ if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
+ if (!_cmsWriteUInt32Number(io, mhc2->CurveEntries)) return FALSE;
+
+ if (!_cmsWrite15Fixed16Number(io, mhc2->MinLuminance)) return FALSE;
+ if (!_cmsWrite15Fixed16Number(io, mhc2->PeakLuminance)) return FALSE;
+
+ TablesOffsetPos = io->Tell(io);
+
+ if (!_cmsWriteUInt32Number(io, 0)) return FALSE; // Matrix
+ if (!_cmsWriteUInt32Number(io, 0)) return FALSE; // Curve R
+ if (!_cmsWriteUInt32Number(io, 0)) return FALSE; // Curve G
+ if (!_cmsWriteUInt32Number(io, 0)) return FALSE; // Curve B
+
+
+ if (IsIdentity(mhc2->XYZ2XYZmatrix))
+ {
+ MatrixOffset = 0;
+ }
+ else
+ {
+ MatrixOffset = io->Tell(io) - BaseOffset;
+ if (!WriteDoubles(io, 3 * 4, &mhc2->XYZ2XYZmatrix[0][0])) return FALSE;
+ }
+
+ OffsetRedTable = io->Tell(io) - BaseOffset;
+ if (!WriteDoubles(io, mhc2->CurveEntries, mhc2->RedCurve)) return FALSE;
+ OffsetGreenTable = io->Tell(io) - BaseOffset;
+ if (!WriteDoubles(io, mhc2->CurveEntries, mhc2->GreenCurve)) return FALSE;
+ OffsetBlueTable = io->Tell(io) - BaseOffset;
+ if (!WriteDoubles(io, mhc2->CurveEntries, mhc2->BlueCurve)) return FALSE;
+
+ if (!io->Seek(io, TablesOffsetPos)) return FALSE;
+
+ if (!_cmsWriteUInt32Number(io, MatrixOffset)) return FALSE;
+ if (!_cmsWriteUInt32Number(io, OffsetRedTable)) return FALSE;
+ if (!_cmsWriteUInt32Number(io, OffsetGreenTable)) return FALSE;
+ if (!_cmsWriteUInt32Number(io, OffsetBlueTable)) return FALSE;
+
+ return TRUE;
+
+ cmsUNUSED_PARAMETER(self);
+ cmsUNUSED_PARAMETER(nItems);
+}
+
+
+static
+cmsBool ReadDoublesAt(cmsIOHANDLER* io, cmsUInt32Number At, cmsUInt32Number n, cmsFloat64Number* Values)
+{
+ cmsUInt32Number CurrentPos = io->Tell(io);
+ cmsUInt32Number i;
+
+ if (!io->Seek(io, At)) return FALSE;
+
+ for (i = 0; i < n; i++) {
+
+ if (!_cmsRead15Fixed16Number(io, Values++)) return FALSE;
+ }
+
+ if (!io->Seek(io, CurrentPos)) return FALSE;
+
+ return TRUE;
+}
+
+static
+void* Type_MHC2_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+ cmsMHC2Type* mhc2 = NULL;
+
+ cmsUInt32Number BaseOffset = io->Tell(io) - sizeof(_cmsTagBase);
+ cmsUInt32Number MatrixOffset;
+ cmsUInt32Number OffsetRedTable, OffsetGreenTable, OffsetBlueTable;
+
+ if (!_cmsReadUInt32Number(io, NULL)) return NULL;
+
+ mhc2 = (cmsMHC2Type*)_cmsCalloc(self->ContextID, 1, sizeof(cmsMHC2Type));
+ if (mhc2 == NULL) return NULL;
+
+ if (!_cmsReadUInt32Number(io, &mhc2->CurveEntries)) goto Error;
+
+ if (mhc2->CurveEntries > 4096) goto Error;
+
+ mhc2->RedCurve = (cmsFloat64Number*)_cmsCalloc(self->ContextID, mhc2->CurveEntries, sizeof(cmsFloat64Number));
+ mhc2->GreenCurve = (cmsFloat64Number*)_cmsCalloc(self->ContextID, mhc2->CurveEntries, sizeof(cmsFloat64Number));
+ mhc2->BlueCurve = (cmsFloat64Number*)_cmsCalloc(self->ContextID, mhc2->CurveEntries, sizeof(cmsFloat64Number));
+
+ if (mhc2->RedCurve == NULL ||
+ mhc2->GreenCurve == NULL ||
+ mhc2->BlueCurve == NULL) goto Error;
+
+ if (!_cmsRead15Fixed16Number(io, &mhc2->MinLuminance)) goto Error;
+ if (!_cmsRead15Fixed16Number(io, &mhc2->PeakLuminance)) goto Error;
+
+ if (!_cmsReadUInt32Number(io, &MatrixOffset)) goto Error;
+ if (!_cmsReadUInt32Number(io, &OffsetRedTable)) goto Error;
+ if (!_cmsReadUInt32Number(io, &OffsetGreenTable)) goto Error;
+ if (!_cmsReadUInt32Number(io, &OffsetBlueTable)) goto Error;
+
+ if (MatrixOffset == 0)
+ SetIdentity(mhc2->XYZ2XYZmatrix);
+ else
+ {
+ if (!ReadDoublesAt(io, BaseOffset + MatrixOffset, 3*4, &mhc2->XYZ2XYZmatrix[0][0])) goto Error;
+ }
+
+ if (!ReadDoublesAt(io, BaseOffset + OffsetRedTable, mhc2->CurveEntries, mhc2->RedCurve)) goto Error;
+ if (!ReadDoublesAt(io, BaseOffset + OffsetGreenTable, mhc2->CurveEntries, mhc2->GreenCurve)) goto Error;
+ if (!ReadDoublesAt(io, BaseOffset + OffsetBlueTable, mhc2->CurveEntries, mhc2->BlueCurve)) goto Error;
+
+ // Success
+ *nItems = 1;
+ return mhc2;
+
+Error:
+ Type_MHC2_Free(self, mhc2);
+ return NULL;
+
+ cmsUNUSED_PARAMETER(SizeOfTag);
+}
+
+
+
// ********************************************************************************
// Type support main routines
// ********************************************************************************
@@ -5509,7 +5742,8 @@ static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
{TYPE_HANDLER(cmsSigProfileSequenceIdType, ProfileSequenceId), (_cmsTagTypeLinkedList*) &SupportedTagTypes[29] },
{TYPE_HANDLER(cmsSigDictType, Dictionary), (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
{TYPE_HANDLER(cmsSigcicpType, VideoSignal), (_cmsTagTypeLinkedList*) &SupportedTagTypes[31] },
-{TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL }
+{TYPE_HANDLER(cmsSigVcgtType, vcgt), (_cmsTagTypeLinkedList*) &SupportedTagTypes[32] },
+{TYPE_HANDLER(cmsSigMHC2Type, MHC2), NULL }
};
@@ -5705,7 +5939,8 @@ static _cmsTagLinkedList SupportedTags[] = {
{ cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]},
{ cmsSigcicpTag, { 1, 1, { cmsSigcicpType}, NULL }, &SupportedTags[64]},
- { cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, NULL}
+ { cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, &SupportedTags[65]},
+ { cmsSigMHC2Tag, { 1, 1, { cmsSigMHC2Type }, NULL}, NULL}
};
diff --git a/contrib/libs/lcms2/src/cmsvirt.c b/contrib/libs/lcms2/src/cmsvirt.c
index 951a8ee29d..3d662b2cc6 100644
--- a/contrib/libs/lcms2/src/cmsvirt.c
+++ b/contrib/libs/lcms2/src/cmsvirt.c
@@ -406,10 +406,9 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
if (Limit < 0.0 || Limit > 400) {
- cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400");
- if (Limit < 0) Limit = 0;
+ cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 1..400");
+ if (Limit < 1) Limit = 1;
if (Limit > 400) Limit = 400;
-
}
hICC = cmsCreateProfilePlaceholder(ContextID);
@@ -672,6 +671,127 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
return cmsCreate_sRGBProfileTHR(NULL);
}
+/**
+* Oklab colorspace profile (experimental)
+*
+* This virtual profile cannot be saved as an ICC file
+*/
+cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
+{
+ cmsStage* XYZPCS = _cmsStageNormalizeFromXyzFloat(ctx);
+ cmsStage* PCSXYZ = _cmsStageNormalizeToXyzFloat(ctx);
+
+ const double M_D65_D50[] =
+ {
+ 1.047886, 0.022919, -0.050216,
+ 0.029582, 0.990484, -0.017079,
+ -0.009252, 0.015073, 0.751678
+ };
+
+ const double M_D50_D65[] =
+ {
+ 0.955512609517083, -0.023073214184645, 0.063308961782107,
+ -0.028324949364887, 1.009942432477107, 0.021054814890112,
+ 0.012328875695483, -0.020535835374141, 1.330713916450354
+ };
+
+ cmsStage* D65toD50 = cmsStageAllocMatrix(ctx, 3, 3, M_D65_D50, NULL);
+ cmsStage* D50toD65 = cmsStageAllocMatrix(ctx, 3, 3, M_D50_D65, NULL);
+
+ const double M_D65_LMS[] =
+ {
+ 0.8189330101, 0.3618667424, -0.1288597137,
+ 0.0329845436, 0.9293118715, 0.0361456387,
+ 0.0482003018, 0.2643662691, 0.6338517070
+ };
+
+ const double M_LMS_D65[] =
+ {
+ 1.227013851103521, -0.557799980651822, 0.281256148966468,
+ -0.040580178423281, 1.112256869616830, -0.071676678665601,
+ -0.076381284505707, -0.421481978418013, 1.586163220440795
+ };
+
+ cmsStage* D65toLMS = cmsStageAllocMatrix(ctx, 3, 3, M_D65_LMS, NULL);
+ cmsStage* LMStoD65 = cmsStageAllocMatrix(ctx, 3, 3, M_LMS_D65, NULL);
+
+ cmsToneCurve* CubeRoot = cmsBuildGamma(ctx, 1.0 / 3.0);
+ cmsToneCurve* Cube = cmsBuildGamma(ctx, 3.0);
+
+ cmsToneCurve* Roots[3] = { CubeRoot, CubeRoot, CubeRoot };
+ cmsToneCurve* Cubes[3] = { Cube, Cube, Cube };
+
+ cmsStage* NonLinearityFw = cmsStageAllocToneCurves(ctx, 3, Roots);
+ cmsStage* NonLinearityRv = cmsStageAllocToneCurves(ctx, 3, Cubes);
+
+ const double M_LMSprime_OkLab[] =
+ {
+ 0.2104542553, 0.7936177850, -0.0040720468,
+ 1.9779984951, -2.4285922050, 0.4505937099,
+ 0.0259040371, 0.7827717662, -0.8086757660
+ };
+
+ const double M_OkLab_LMSprime[] =
+ {
+ 0.999999998450520, 0.396337792173768, 0.215803758060759,
+ 1.000000008881761, -0.105561342323656, -0.063854174771706,
+ 1.000000054672411, -0.089484182094966, -1.291485537864092
+ };
+
+ cmsStage* LMSprime_OkLab = cmsStageAllocMatrix(ctx, 3, 3, M_LMSprime_OkLab, NULL);
+ cmsStage* OkLab_LMSprime = cmsStageAllocMatrix(ctx, 3, 3, M_OkLab_LMSprime, NULL);
+
+ cmsPipeline* AToB = cmsPipelineAlloc(ctx, 3, 3);
+ cmsPipeline* BToA = cmsPipelineAlloc(ctx, 3, 3);
+
+ cmsHPROFILE hProfile = cmsCreateProfilePlaceholder(ctx);
+
+ cmsSetProfileVersion(hProfile, 4.4);
+
+ cmsSetDeviceClass(hProfile, cmsSigColorSpaceClass);
+ cmsSetColorSpace(hProfile, cmsSig3colorData);
+ cmsSetPCS(hProfile, cmsSigXYZData);
+
+ cmsSetHeaderRenderingIntent(hProfile, INTENT_RELATIVE_COLORIMETRIC);
+
+ /**
+ * Conversion PCS (XYZ/D50) to OkLab
+ */
+ if (!cmsPipelineInsertStage(BToA, cmsAT_END, PCSXYZ)) goto error;
+ if (!cmsPipelineInsertStage(BToA, cmsAT_END, D50toD65)) goto error;
+ if (!cmsPipelineInsertStage(BToA, cmsAT_END, D65toLMS)) goto error;
+ if (!cmsPipelineInsertStage(BToA, cmsAT_END, NonLinearityFw)) goto error;
+ if (!cmsPipelineInsertStage(BToA, cmsAT_END, LMSprime_OkLab)) goto error;
+
+ if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, BToA)) goto error;
+
+ if (!cmsPipelineInsertStage(AToB, cmsAT_END, OkLab_LMSprime)) goto error;
+ if (!cmsPipelineInsertStage(AToB, cmsAT_END, NonLinearityRv)) goto error;
+ if (!cmsPipelineInsertStage(AToB, cmsAT_END, LMStoD65)) goto error;
+ if (!cmsPipelineInsertStage(AToB, cmsAT_END, D65toD50)) goto error;
+ if (!cmsPipelineInsertStage(AToB, cmsAT_END, XYZPCS)) goto error;
+
+ if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, AToB)) goto error;
+
+ cmsPipelineFree(BToA);
+ cmsPipelineFree(AToB);
+
+ cmsFreeToneCurve(CubeRoot);
+ cmsFreeToneCurve(Cube);
+
+ return hProfile;
+
+error:
+ cmsPipelineFree(BToA);
+ cmsPipelineFree(AToB);
+
+ cmsFreeToneCurve(CubeRoot);
+ cmsFreeToneCurve(Cube);
+ cmsCloseProfile(hProfile);
+
+ return NULL;
+
+}
typedef struct {
@@ -1031,7 +1151,7 @@ cmsBool CheckOne(const cmsAllowedLUT* Tab, const cmsPipeline* Lut)
for (n=0, mpe = Lut ->Elements; mpe != NULL; mpe = mpe ->Next, n++) {
- if (n > Tab ->nTypes) return FALSE;
+ if (n >= Tab ->nTypes) return FALSE;
if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE;
}
@@ -1062,9 +1182,9 @@ const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTa
cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
{
cmsHPROFILE hProfile = NULL;
- cmsUInt32Number FrmIn, FrmOut;
- cmsInt32Number ChansIn, ChansOut;
- int ColorSpaceBitsIn, ColorSpaceBitsOut;
+ cmsUInt32Number FrmIn, FrmOut;
+ cmsInt32Number ChansIn, ChansOut;
+ int ColorSpaceBitsIn, ColorSpaceBitsOut;
_cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
cmsPipeline* LUT = NULL;
cmsStage* mpe;
@@ -1075,6 +1195,9 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
_cmsAssert(hTransform != NULL);
+ // Check if the pipeline holding is valid
+ if (xform -> Lut == NULL) return NULL;
+
// Get the first mpe to check for named color
mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);
diff --git a/contrib/libs/lcms2/src/cmsxform.c b/contrib/libs/lcms2/src/cmsxform.c
index c70b7cbce1..8fe6b6b974 100644
--- a/contrib/libs/lcms2/src/cmsxform.c
+++ b/contrib/libs/lcms2/src/cmsxform.c
@@ -914,7 +914,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
}
// Check whatever this is a true floating point transform
- if (_cmsFormatterIsFloat(*OutputFormat)) {
+ if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) {
// Get formatter function always return a valid union, but the contents of this union may be NULL.
p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
@@ -989,6 +989,19 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
}
}
+ /**
+ * Check consistency for alpha channel copy
+ */
+ if (*dwFlags & cmsFLAGS_COPY_ALPHA)
+ {
+ if (T_EXTRA(*InputFormat) != T_EXTRA(*OutputFormat))
+ {
+ cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Mismatched alpha channels");
+ cmsDeleteTransform(p);
+ return NULL;
+ }
+ }
+
p ->InputFormat = *InputFormat;
p ->OutputFormat = *OutputFormat;
p ->dwOriginalFlags = *dwFlags;
diff --git a/contrib/libs/lcms2/src/lcms2_internal.h b/contrib/libs/lcms2/src/lcms2_internal.h
index 1fc99fbe7f..8e78a71e6e 100644
--- a/contrib/libs/lcms2/src/lcms2_internal.h
+++ b/contrib/libs/lcms2/src/lcms2_internal.h
@@ -260,6 +260,7 @@ typedef CRITICAL_SECTION _cmsMutex;
#ifdef _MSC_VER
# if (_MSC_VER >= 1800)
# pragma warning(disable : 26135)
+# pragma warning(disable : 4127)
# endif
#endif
@@ -517,7 +518,7 @@ struct _cmsContext_struct {
struct _cmsContext_struct* Next; // Points to next context in the new style
_cmsSubAllocator* MemPool; // The memory pool that stores context data
- void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is hold in the suballocator.
+ void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is held in the suballocator.
// If NULL, then it reverts to global Context0
_cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overridden
@@ -811,6 +812,9 @@ typedef struct _cms_iccprofile_struct {
// Creation time
struct tm Created;
+ // Color management module identification
+ cmsUInt32Number CMM;
+
// Only most important items found in ICC profiles
cmsUInt32Number Version;
cmsProfileClassSignature DeviceClass;
@@ -818,6 +822,7 @@ typedef struct _cms_iccprofile_struct {
cmsColorSpaceSignature PCS;
cmsUInt32Number RenderingIntent;
+ cmsPlatformSignature platform;
cmsUInt32Number flags;
cmsUInt32Number manufacturer, model;
cmsUInt64Number attributes;