8321489: Update LCMS to 2.16
Reviewed-by: serb, dnguyen, prr
This commit is contained in:
parent
84cf4cb350
commit
dc7d3b182d
@ -1,34 +1,29 @@
|
||||
## Little Color Management System (LCMS) v2.15
|
||||
## Little Color Management System (LCMS) v2.16
|
||||
|
||||
### LCMS License
|
||||
<pre>
|
||||
README.1ST file information
|
||||
|
||||
LittleCMS core is released under MIT License
|
||||
MIT License
|
||||
|
||||
---------------------------------
|
||||
|
||||
Little CMS
|
||||
Copyright (c) 1998-2023 Marti Maria Saguer
|
||||
Copyright (C) 1998-2023 Marti Maria Saguer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject
|
||||
to the following conditions:
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---------------------------------
|
||||
The below license applies to the following files:
|
||||
@ -47,7 +42,6 @@ Users of this code must verify correctness for their application.
|
||||
### AUTHORS File Information
|
||||
```
|
||||
|
||||
|
||||
Main Author
|
||||
------------
|
||||
Marti Maria
|
||||
@ -91,6 +85,7 @@ Philipp Knechtges
|
||||
Amyspark
|
||||
Lovell Fuller
|
||||
Eli Schwartz
|
||||
Diogo Teles Sant'Anna
|
||||
|
||||
Special Thanks
|
||||
--------------
|
||||
|
@ -431,7 +431,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[])
|
||||
{
|
||||
@ -445,7 +445,7 @@ void ComputeIncrementsForChunky(cmsUInt32Number Format,
|
||||
|
||||
// Sanity check
|
||||
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
memset(channels, 0, sizeof(channels));
|
||||
|
||||
@ -482,13 +482,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[])
|
||||
@ -502,7 +504,7 @@ void ComputeIncrementsForPlanar(cmsUInt32Number Format,
|
||||
|
||||
// Sanity check
|
||||
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
memset(channels, 0, sizeof(channels));
|
||||
|
||||
@ -538,29 +540,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,
|
||||
@ -595,8 +597,10 @@ void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
|
||||
return;
|
||||
|
||||
// Compute the increments
|
||||
ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements);
|
||||
ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements);
|
||||
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);
|
||||
|
@ -87,7 +87,7 @@ typedef enum {
|
||||
SEOF, // End of stream
|
||||
SSYNERROR, // Syntax error found on stream
|
||||
|
||||
// Keywords
|
||||
// IT8 symbols
|
||||
|
||||
SBEGIN_DATA,
|
||||
SBEGIN_DATA_FORMAT,
|
||||
@ -95,7 +95,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;
|
||||
|
||||
@ -178,6 +190,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
|
||||
@ -237,8 +253,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!
|
||||
@ -251,7 +267,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
|
||||
|
||||
@ -455,7 +489,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
|
||||
@ -476,7 +510,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
|
||||
@ -515,13 +549,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);
|
||||
@ -603,10 +637,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)
|
||||
@ -776,7 +810,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)
|
||||
{
|
||||
@ -833,7 +867,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;
|
||||
|
||||
@ -942,6 +978,7 @@ void InSymbol(cmsIT8* it8)
|
||||
snprintf(buffer, sizeof(buffer), it8 ->DoubleFormatter, it8->dnum);
|
||||
}
|
||||
|
||||
StringClear(it8->id);
|
||||
StringCat(it8->id, buffer);
|
||||
|
||||
do {
|
||||
@ -971,7 +1008,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++;
|
||||
@ -1292,7 +1329,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 {
|
||||
|
||||
@ -1413,6 +1455,8 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
|
||||
it8->MemoryBlock = NULL;
|
||||
it8->MemorySink = NULL;
|
||||
|
||||
it8->IsCUBE = FALSE;
|
||||
|
||||
it8 ->nTable = 0;
|
||||
|
||||
it8->ContextID = ContextID;
|
||||
@ -1694,7 +1738,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;
|
||||
@ -1879,11 +1923,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");
|
||||
}
|
||||
@ -1893,39 +1940,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");
|
||||
}
|
||||
@ -1946,15 +1996,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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2331,78 +2395,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;
|
||||
}
|
||||
|
||||
// "LABEL" is an extension. It keeps references to forward tables
|
||||
|
||||
if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
|
||||
|
||||
// Search for table references...
|
||||
for (i = 0; i < t->nPatches; i++) {
|
||||
|
||||
char* Label = GetData(it8, i, idField);
|
||||
|
||||
if (Label) {
|
||||
|
||||
cmsUInt32Number k;
|
||||
|
||||
// This is the label, search for a table containing
|
||||
// this property
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// "LABEL" is an extension. It keeps references to forward tables
|
||||
|
||||
if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$') {
|
||||
|
||||
// Search for table references...
|
||||
for (i = 0; i < t->nPatches; i++) {
|
||||
|
||||
char* Label = GetData(it8, i, idField);
|
||||
|
||||
if (Label) {
|
||||
|
||||
cmsUInt32Number k;
|
||||
|
||||
// This is the label, search for a table containing
|
||||
// this property
|
||||
|
||||
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
|
||||
@ -2493,7 +2551,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);
|
||||
@ -2505,7 +2563,7 @@ cmsHANDLE CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cm
|
||||
if (!ParseIT8(it8, type-1)) {
|
||||
|
||||
cmsIT8Free(hIT8);
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CookPointers(it8);
|
||||
@ -2602,17 +2660,17 @@ cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyN
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
*PropertyNames = Props;
|
||||
|
||||
}
|
||||
*PropertyNames = Props;
|
||||
|
||||
return n;
|
||||
}
|
||||
@ -2972,3 +3030,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);
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ cmsFloat64Number CHAD2Temp(const cmsMAT3* Chad)
|
||||
|
||||
// Compute a CHAD based on a given temperature
|
||||
static
|
||||
void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp)
|
||||
void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp)
|
||||
{
|
||||
cmsCIEXYZ White;
|
||||
cmsCIExyY ChromaticityOfWhite;
|
||||
@ -744,6 +744,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,
|
||||
@ -776,14 +786,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
|
||||
@ -800,7 +812,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
|
||||
|
||||
// Create a LUT holding normal ICC transform
|
||||
bp.cmyk2cmyk = DefaultICCintents(ContextID,
|
||||
preservationProfilesCount,
|
||||
preservationProfilesCount,
|
||||
ICCIntents,
|
||||
hProfiles,
|
||||
BPC,
|
||||
@ -812,7 +824,7 @@ cmsPipeline* BlackPreservingKOnlyIntents(cmsContext ContextID,
|
||||
// Now, compute the tone curve
|
||||
bp.KTone = _cmsBuildKToneCurve(ContextID,
|
||||
4096,
|
||||
preservationProfilesCount,
|
||||
preservationProfilesCount,
|
||||
ICCIntents,
|
||||
hProfiles,
|
||||
BPC,
|
||||
@ -1002,12 +1014,13 @@ cmsPipeline* BlackPreservingKPlaneIntents(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;
|
||||
@ -1177,20 +1190,6 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUIn
|
||||
cmsIntentsList* pt;
|
||||
cmsUInt32Number nIntents;
|
||||
|
||||
|
||||
for (nIntents=0, pt = ctx->Intents; pt != NULL; pt = pt -> Next)
|
||||
{
|
||||
if (nIntents < nMax) {
|
||||
if (Codes != NULL)
|
||||
Codes[nIntents] = pt ->Intent;
|
||||
|
||||
if (Descriptions != NULL)
|
||||
Descriptions[nIntents] = pt ->Description;
|
||||
}
|
||||
|
||||
nIntents++;
|
||||
}
|
||||
|
||||
for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next)
|
||||
{
|
||||
if (nIntents < nMax) {
|
||||
@ -1203,6 +1202,20 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUIn
|
||||
|
||||
nIntents++;
|
||||
}
|
||||
|
||||
for (pt = ctx->Intents; pt != NULL; pt = pt -> Next)
|
||||
{
|
||||
if (nIntents < nMax) {
|
||||
if (Codes != NULL)
|
||||
Codes[nIntents] = pt ->Intent;
|
||||
|
||||
if (Descriptions != NULL)
|
||||
Descriptions[nIntents] = pt ->Description;
|
||||
}
|
||||
|
||||
nIntents++;
|
||||
}
|
||||
|
||||
return nIntents;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,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))
|
||||
@ -121,7 +121,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);
|
||||
|
||||
@ -263,7 +264,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;
|
||||
|
@ -329,6 +329,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);
|
||||
@ -622,10 +626,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
|
||||
@ -1520,13 +1530,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;
|
||||
}
|
||||
|
||||
|
@ -248,7 +248,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
|
||||
@ -625,7 +625,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)
|
||||
|
@ -560,6 +560,20 @@ 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;
|
||||
|
||||
@ -813,11 +827,13 @@ 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);
|
||||
@ -922,7 +938,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);
|
||||
@ -934,11 +950,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);
|
||||
@ -954,8 +966,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));
|
||||
|
||||
|
@ -607,7 +607,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;
|
||||
@ -1056,3 +1056,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);
|
||||
}
|
||||
|
@ -504,6 +504,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;
|
||||
}
|
||||
|
||||
@ -843,7 +846,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;
|
||||
|
@ -229,17 +229,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;
|
||||
@ -247,20 +375,54 @@ 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);
|
||||
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
|
||||
@ -401,7 +563,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);
|
||||
}
|
||||
|
||||
|
||||
@ -439,10 +601,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"
|
||||
@ -450,6 +614,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],
|
||||
@ -470,12 +674,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;
|
||||
@ -843,13 +1047,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);
|
||||
}
|
||||
|
||||
|
@ -212,6 +212,7 @@ cmsBool isFloatMatrixIdentity(const cmsMAT3* a)
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// if two adjacent matrices are found, multiply them.
|
||||
static
|
||||
cmsBool _MultiplyMatrix(cmsPipeline* Lut)
|
||||
@ -1142,14 +1143,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++) {
|
||||
@ -1753,6 +1757,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));
|
||||
|
||||
@ -1797,7 +1803,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
|
||||
@ -1954,7 +1960,7 @@ cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
|
||||
for (mpe = cmsPipelineGetPtrToFirstStage(*PtrLut);
|
||||
mpe != NULL;
|
||||
mpe = cmsStageNext(mpe)) {
|
||||
if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
|
||||
if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
|
||||
}
|
||||
|
||||
// Try to get rid of identities and trivial conversions.
|
||||
|
@ -2980,6 +2980,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[],
|
||||
@ -3143,6 +3245,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,
|
||||
@ -3676,10 +3849,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 },
|
||||
@ -3890,7 +4073,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?
|
||||
|
@ -393,12 +393,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)
|
||||
@ -410,19 +405,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
|
||||
|
@ -460,48 +460,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)
|
||||
@ -509,20 +507,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
|
||||
@ -549,9 +535,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 ");
|
||||
}
|
||||
|
||||
|
||||
@ -568,10 +552,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++ )
|
||||
{
|
||||
@ -579,12 +563,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]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,18 +690,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) {
|
||||
|
||||
for (i=0; i < sc.Pipeline->Params->nInputs; i++)
|
||||
_cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
|
||||
_cmsIOPrintf(m, "[");
|
||||
|
||||
_cmsIOPrintf(m, " [\n");
|
||||
for (i = 0; i < sc.Pipeline->Params->nInputs; i++)
|
||||
_cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
|
||||
|
||||
cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*) &sc, SAMPLER_INSPECT);
|
||||
_cmsIOPrintf(m, " [\n");
|
||||
|
||||
_cmsIOPrintf(m, PostMin);
|
||||
_cmsIOPrintf(m, PostMaj);
|
||||
_cmsIOPrintf(m, "] ");
|
||||
cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*)&sc, SAMPLER_INSPECT);
|
||||
|
||||
_cmsIOPrintf(m, PostMin);
|
||||
_cmsIOPrintf(m, PostMaj);
|
||||
_cmsIOPrintf(m, "] ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -733,11 +718,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 ");
|
||||
|
||||
_cmsIOPrintf(m, "/DecodeA /lcms2gammaproc load\n");
|
||||
EmitSafeGuardEnd(m, "lcms2gammaproc", 3);
|
||||
Emit1Gamma(m, Curve);
|
||||
|
||||
_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");
|
||||
@ -761,19 +746,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 [ " );
|
||||
|
||||
@ -805,10 +782,8 @@ 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;
|
||||
|
||||
@ -837,34 +812,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);
|
||||
@ -1024,9 +983,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 {
|
||||
|
||||
@ -1053,10 +1012,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");
|
||||
@ -1065,7 +1029,6 @@ int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number
|
||||
|
||||
nColors = cmsNamedColorCount(NamedColorList);
|
||||
|
||||
|
||||
for (i=0; i < nColors; i++) {
|
||||
|
||||
cmsUInt16Number In[1];
|
||||
@ -1080,12 +1043,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;
|
||||
}
|
||||
|
||||
@ -1339,7 +1299,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;
|
||||
@ -1366,7 +1326,6 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
|
||||
cmsCloseProfile(hLab);
|
||||
|
||||
if (xform == NULL) {
|
||||
|
||||
cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation");
|
||||
return 0;
|
||||
}
|
||||
@ -1374,10 +1333,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);
|
||||
|
||||
@ -1404,8 +1365,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);
|
||||
|
||||
@ -1414,7 +1377,6 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
|
||||
|
||||
_cmsIOPrintf(m, "]\n");
|
||||
|
||||
|
||||
EmitIntent(m, Intent);
|
||||
|
||||
_cmsIOPrintf(m, ">>\n");
|
||||
@ -1477,7 +1439,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");
|
||||
|
@ -152,7 +152,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;
|
||||
|
||||
|
@ -122,7 +122,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)
|
||||
@ -954,6 +954,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;
|
||||
@ -973,7 +974,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
|
||||
@ -998,15 +999,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;
|
||||
|
||||
for (i=0; i < UnicodeCount; i++) {
|
||||
if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) 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;
|
||||
|
||||
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) {
|
||||
@ -1026,6 +1042,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;
|
||||
@ -1078,7 +1095,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
|
||||
@ -1577,8 +1594,6 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU
|
||||
if (SizeOfTag == 0)
|
||||
{
|
||||
Block = NULL;
|
||||
NumOfWchar = 0;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1940,7 +1955,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;
|
||||
@ -1953,6 +1968,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;
|
||||
@ -2694,8 +2715,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)
|
||||
@ -4459,8 +4480,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;
|
||||
@ -5250,11 +5271,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;
|
||||
}
|
||||
|
||||
@ -5499,6 +5522,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
|
||||
// ********************************************************************************
|
||||
@ -5538,7 +5771,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 }
|
||||
};
|
||||
|
||||
|
||||
@ -5734,7 +5968,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}
|
||||
|
||||
};
|
||||
|
||||
|
@ -435,10 +435,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);
|
||||
@ -701,6 +700,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 {
|
||||
@ -1060,7 +1180,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;
|
||||
}
|
||||
|
||||
@ -1091,9 +1211,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;
|
||||
@ -1104,6 +1224,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);
|
||||
|
||||
|
@ -943,7 +943,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;
|
||||
@ -1018,6 +1018,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;
|
||||
|
@ -52,7 +52,7 @@
|
||||
//
|
||||
//---------------------------------------------------------------------------------
|
||||
//
|
||||
// Version 2.15
|
||||
// Version 2.16
|
||||
//
|
||||
|
||||
#ifndef _lcms2_H
|
||||
@ -105,12 +105,15 @@
|
||||
|
||||
#ifndef CMS_USE_CPP_API
|
||||
# ifdef __cplusplus
|
||||
# if __cplusplus >= 201703L
|
||||
# define CMS_NO_REGISTER_KEYWORD 1
|
||||
# endif
|
||||
extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Version/release
|
||||
#define LCMS_VERSION 2150
|
||||
#define LCMS_VERSION 2160
|
||||
|
||||
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
|
||||
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
|
||||
@ -354,7 +357,8 @@ typedef enum {
|
||||
cmsSigUInt8ArrayType = 0x75693038, // 'ui08'
|
||||
cmsSigVcgtType = 0x76636774, // 'vcgt'
|
||||
cmsSigViewingConditionsType = 0x76696577, // 'view'
|
||||
cmsSigXYZType = 0x58595A20 // 'XYZ '
|
||||
cmsSigXYZType = 0x58595A20, // 'XYZ '
|
||||
cmsSigMHC2Type = 0x4D484332 // 'MHC2'
|
||||
|
||||
|
||||
} cmsTagTypeSignature;
|
||||
@ -432,7 +436,8 @@ typedef enum {
|
||||
cmsSigVcgtTag = 0x76636774, // 'vcgt'
|
||||
cmsSigMetaTag = 0x6D657461, // 'meta'
|
||||
cmsSigcicpTag = 0x63696370, // 'cicp'
|
||||
cmsSigArgyllArtsTag = 0x61727473 // 'arts'
|
||||
cmsSigArgyllArtsTag = 0x61727473, // 'arts'
|
||||
cmsSigMHC2Tag = 0x4D484332 // 'MHC2'
|
||||
|
||||
} cmsTagSignature;
|
||||
|
||||
@ -977,6 +982,7 @@ typedef void* cmsHTRANSFORM;
|
||||
#define TYPE_RGB_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0))
|
||||
#define TYPE_BGR_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0)|DOSWAP_SH(1))
|
||||
#define TYPE_CMYK_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(0))
|
||||
#define TYPE_OKLAB_DBL (FLOAT_SH(1)|COLORSPACE_SH(PT_MCH3)|CHANNELS_SH(3)|BYTES_SH(0))
|
||||
|
||||
// IEEE 754-2008 "half"
|
||||
#define TYPE_GRAY_HALF_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
|
||||
@ -1077,6 +1083,19 @@ typedef struct {
|
||||
|
||||
} cmsVideoSignalType;
|
||||
|
||||
typedef struct {
|
||||
cmsUInt32Number CurveEntries;
|
||||
cmsFloat64Number* RedCurve;
|
||||
cmsFloat64Number* GreenCurve;
|
||||
cmsFloat64Number* BlueCurve;
|
||||
|
||||
cmsFloat64Number MinLuminance; // ST.2086 min luminance in nits
|
||||
cmsFloat64Number PeakLuminance; // ST.2086 peak luminance in nits
|
||||
|
||||
cmsFloat64Number XYZ2XYZmatrix[3][4];
|
||||
|
||||
} cmsMHC2Type;
|
||||
|
||||
|
||||
|
||||
// Get LittleCMS version (for shared objects) -----------------------------------------------------------------------------
|
||||
@ -1249,7 +1268,8 @@ CMSAPI cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t
|
||||
CMSAPI cmsBool CMSEXPORT cmsIsToneCurveDescending(const cmsToneCurve* t);
|
||||
CMSAPI cmsInt32Number CMSEXPORT cmsGetToneCurveParametricType(const cmsToneCurve* t);
|
||||
CMSAPI cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision);
|
||||
CMSAPI cmsFloat64Number* CMSEXPORT cmsGetToneCurveParams(const cmsToneCurve* t);
|
||||
|
||||
CMSAPI const cmsCurveSegment* CMSEXPORT cmsGetToneCurveSegment(cmsInt32Number n, const cmsToneCurve* t);
|
||||
|
||||
// Tone curve tabular estimation
|
||||
CMSAPI cmsUInt32Number CMSEXPORT cmsGetToneCurveEstimatedTableEntries(const cmsToneCurve* t);
|
||||
@ -1343,8 +1363,11 @@ CMSAPI cmsBool CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, c
|
||||
|
||||
typedef struct _cms_MLU_struct cmsMLU;
|
||||
|
||||
#define cmsNoLanguage "\0\0"
|
||||
#define cmsNoCountry "\0\0"
|
||||
#define cmsNoLanguage "\0\0"
|
||||
#define cmsNoCountry "\0\0"
|
||||
|
||||
// Special language/country to retrieve unicode field for description in V2 profiles. Use with care.
|
||||
#define cmsV2Unicode "\xff\xff"
|
||||
|
||||
CMSAPI cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems);
|
||||
CMSAPI void CMSEXPORT cmsMLUfree(cmsMLU* mlu);
|
||||
@ -1356,6 +1379,9 @@ CMSAPI cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu,
|
||||
CMSAPI cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
const wchar_t* WideString);
|
||||
CMSAPI cmsBool CMSEXPORT cmsMLUsetUTF8(cmsMLU* mlu,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
const char* UTF8String);
|
||||
|
||||
CMSAPI cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
@ -1364,6 +1390,10 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
|
||||
CMSAPI cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
wchar_t* Buffer, cmsUInt32Number BufferSize);
|
||||
CMSAPI cmsUInt32Number CMSEXPORT cmsMLUgetUTF8(const cmsMLU* mlu,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
char* Buffer, cmsUInt32Number BufferSize);
|
||||
|
||||
|
||||
CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
@ -1588,6 +1618,10 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
char* Buffer, cmsUInt32Number BufferSize);
|
||||
|
||||
CMSAPI cmsUInt32Number CMSEXPORT cmsGetProfileInfoUTF8(cmsHPROFILE hProfile, cmsInfoType Info,
|
||||
const char LanguageCode[3], const char CountryCode[3],
|
||||
char* Buffer, cmsUInt32Number BufferSize);
|
||||
|
||||
// IO handlers ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
typedef struct _cms_io_handler cmsIOHANDLER;
|
||||
@ -1650,6 +1684,9 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext C
|
||||
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLink(cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit);
|
||||
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateDeviceLinkFromCubeFile(const char* cFileName);
|
||||
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateDeviceLinkFromCubeFileTHR(cmsContext ContextID, const char* cFileName);
|
||||
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint);
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateLab2Profile(const cmsCIExyY* WhitePoint);
|
||||
@ -1662,6 +1699,8 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void);
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID);
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void);
|
||||
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreate_OkLabProfile(cmsContext ctx);
|
||||
|
||||
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
|
||||
cmsUInt32Number nLUTPoints,
|
||||
cmsFloat64Number Bright,
|
||||
|
@ -288,6 +288,7 @@ typedef CRITICAL_SECTION _cmsMutex;
|
||||
#ifdef _MSC_VER
|
||||
# if (_MSC_VER >= 1800)
|
||||
# pragma warning(disable : 26135)
|
||||
# pragma warning(disable : 4127)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -545,7 +546,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
|
||||
@ -839,6 +840,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;
|
||||
@ -846,6 +850,7 @@ typedef struct _cms_iccprofile_struct {
|
||||
cmsColorSpaceSignature PCS;
|
||||
cmsUInt32Number RenderingIntent;
|
||||
|
||||
cmsPlatformSignature platform;
|
||||
cmsUInt32Number flags;
|
||||
cmsUInt32Number manufacturer, model;
|
||||
cmsUInt64Number attributes;
|
||||
|
Loading…
x
Reference in New Issue
Block a user