8297089: [BACKOUT] JDK-8297088 Update LCMS to 2.14

Reviewed-by: dholmes
This commit is contained in:
Daniel D. Daugherty 2022-11-15 23:02:42 +00:00
parent 6a60d318b6
commit bd3acbea8c
31 changed files with 592 additions and 2004 deletions

@ -1,107 +1,27 @@
## Little Color Management System (LCMS) v2.14
## Little Color Management System (LCMS) v2.12
### LCMS License
<pre>
README.1ST file information
LittleCMS core is released under MIT License
---------------------------------
Little CMS
Copyright (c) 1998-2022 Marti Maria Saguer
Little Color Management System
Copyright (c) 1998-2020 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.
---------------------------------
The below license applies to the following files:
liblcms/cmssm.c
Copyright 2001, softSurfer (www.softsurfer.com)
This code may be freely used and modified for any purpose
providing that this copyright notice is included with it.
SoftSurfer makes no warranty for this code, and cannot be held
liable for any real or imagined damage resulting from its use.
Users of this code must verify correctness for their application.
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.
</pre>
### AUTHORS File Information
```
Main Author
------------
Marti Maria
Contributors
------------
Bob Friesenhahn
Kai-Uwe Behrmann
Stuart Nixon
Jordi Vilar
Richard Hughes
Auke Nauta
Chris Evans (Google)
Lorenzo Ridolfi
Robin Watts (Artifex)
Shawn Pedersen
Andrew Brygin
Samuli Suominen
Florian Hˆch
Aurelien Jarno
Claudiu Cebuc
Michael Vhrel (Artifex)
Michal Cihar
Daniel Kaneider
Mateusz Jurczyk (Google)
Paul Miller
SÈbastien LÈon
Christian Schmitz
XhmikosR
Stanislav Brabec (SuSe)
Leonhard Gruenschloss (Google)
Patrick Noffke
Christopher James Halse Rogers
John Hein
Thomas Weber (Debian)
Mark Allen
Noel Carboni
Sergei Trofimovic
Philipp Knechtges
Special Thanks
--------------
Artifex software
AlienSkin software
Jan Morovic
Jos Vernon (WebSupergoo)
Harald Schneider (Maxon)
Christian Albrecht
Dimitrios Anastassakis
Lemke Software
Tim Zaman
```

@ -1,23 +0,0 @@
# Tips and tasks when updating LittleCMS sources to a newer version.
Download and unzip latest release from https://sourceforge.net/projects/lcms/files/
Replace files in src/java.desktop/share/native/liblcms with files from unzipped src and include folders
Replace is important because the lcms sources here are just the subset needed by JDK.
This is deliberate, so when updating be sure to import only the same files.
If a file has been removed from upstream you will notice it during the copy.
It should then be removed from the JDK sources.
If a new file is needed then the build will fail. Manually copy that in.
Some re-editing of these updated files will be needed.
Use "expand" and "sed" to remove tabs and trailing white space from the imported files.
Re-apply the GPL headers used by the JDK. If done correctly these should then not
show up in the PR diff.
Update src/java.desktop/share/legal/lcms.md per the current license/copyrights/attributions etc.
Build on all platforms.
If there are compiler warnings causing build failures, update the disabled warnings in
make/modules/java.desktop/lib/Awt2dLibraries.gmk
Run all automated client tests on all platforms.
Also run J2Ddemo and pay particular attention to the "color" tab.
Visually verify the color transforms against the same with the current/previous JDK

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -220,21 +220,21 @@ static
void fromFLTto8(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
}
static
void fromFLTto16(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0);
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
}
static
void fromFLTto16SE(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0);
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
}
@ -272,7 +272,7 @@ void fromHLFto8(void* dst, const void* src)
{
#ifndef CMS_NO_HALF_SUPPORT
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
#else
cmsUNUSED_PARAMETER(dst);
cmsUNUSED_PARAMETER(src);
@ -285,7 +285,7 @@ void fromHLFto16(void* dst, const void* src)
{
#ifndef CMS_NO_HALF_SUPPORT
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0);
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
#else
cmsUNUSED_PARAMETER(dst);
cmsUNUSED_PARAMETER(src);
@ -297,7 +297,7 @@ void fromHLFto16SE(void* dst, const void* src)
{
#ifndef CMS_NO_HALF_SUPPORT
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0);
cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
*(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
#else
cmsUNUSED_PARAMETER(dst);
@ -443,9 +443,9 @@ void ComputeIncrementsForChunky(cmsUInt32Number Format,
cmsUInt32Number channelSize = trueBytesSize(Format);
cmsUInt32Number pixelSize = channelSize * total_chans;
// Sanity check
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
return;
// Sanity check
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
return;
memset(channels, 0, sizeof(channels));

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -162,18 +162,9 @@ typedef struct _FileContext {
FILE* Stream; // File stream or NULL if holded in memory
} FILECTX;
//Very simple string
// This struct hold all information about an open IT8 handler.
typedef struct {
struct struct_it8* it8;
cmsInt32Number max;
cmsInt32Number len;
char* begin;
} string;
// This struct hold all information about an open IT8 handler.
typedef struct struct_it8 {
cmsUInt32Number TablesCount; // How many tables in this stream
cmsUInt32Number nTable; // The actual table
@ -191,8 +182,8 @@ typedef struct struct_it8 {
cmsInt32Number inum; // integer value
cmsFloat64Number dnum; // real value
string* id; // identifier
string* str; // string
char id[MAXID]; // identifier
char str[MAXSTR]; // string
// Allowed keywords & datasets. They have visibility on whole stream
KEYVALUE* ValidKeywords;
@ -277,7 +268,7 @@ static PROPERTY PredefinedProperties[] = {
{"MATERIAL", WRITE_STRINGIFY}, // Identifies the material on which the target was produced using a code
// uniquely identifying th e material. This is intend ed to be used for IT8.7
// physical targets only (i.e . IT8.7/1 and IT8.7/2).
// physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
{"INSTRUMENTATION", WRITE_STRINGIFY}, // Used to report the specific instrumentation used (manufacturer and
// model number) to generate the data reported. This data will often
@ -392,65 +383,6 @@ static const char* PredefinedSampleID[] = {
//Forward declaration of some internal functions
static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
static
string* StringAlloc(cmsIT8* it8, int max)
{
string* s = (string*) AllocChunk(it8, sizeof(string));
if (s == NULL) return NULL;
s->it8 = it8;
s->max = max;
s->len = 0;
s->begin = (char*) AllocChunk(it8, s->max);
return s;
}
static
void StringClear(string* s)
{
s->len = 0;
}
static
void StringAppend(string* s, char c)
{
if (s->len + 1 >= s->max)
{
char* new_ptr;
s->max *= 10;
new_ptr = (char*) AllocChunk(s->it8, s->max);
if (new_ptr != NULL && s->begin != NULL)
memcpy(new_ptr, s->begin, s->len);
s->begin = new_ptr;
}
if (s->begin != NULL)
{
s->begin[s->len++] = c;
s->begin[s->len] = 0;
}
}
static
char* StringPtr(string* s)
{
return s->begin;
}
static
void StringCat(string* s, const char* c)
{
while (*c)
{
StringAppend(s, *c);
c++;
}
}
// Checks whatever c is a separator
static
cmsBool isseparator(int c)
@ -776,44 +708,14 @@ cmsFloat64Number ParseFloatNumber(const char *Buffer)
}
// Reads a string, special case to avoid infinite resursion on .include
static
void InStringSymbol(cmsIT8* it8)
{
while (isseparator(it8->ch))
NextCh(it8);
if (it8->ch == '\'' || it8->ch == '\"')
{
int sng;
sng = it8->ch;
StringClear(it8->str);
NextCh(it8);
while (it8->ch != sng) {
if (it8->ch == '\n' || it8->ch == '\r' || it8->ch == 0) break;
else {
StringAppend(it8->str, (char)it8->ch);
NextCh(it8);
}
}
it8->sy = SSTRING;
NextCh(it8);
}
else
SynError(it8, "String expected");
}
// Reads next symbol
static
void InSymbol(cmsIT8* it8)
{
CMSREGISTER char *idptr;
CMSREGISTER int k;
SYMBOL key;
int sng;
do {
@ -822,18 +724,21 @@ void InSymbol(cmsIT8* it8)
if (isfirstidchar(it8->ch)) { // Identifier
StringClear(it8->id);
k = 0;
idptr = it8->id;
do {
StringAppend(it8->id, (char) it8->ch);
if (++k < MAXID) *idptr++ = (char) it8->ch;
NextCh(it8);
} while (isidchar(it8->ch));
*idptr = '\0';
key = BinSrchKey(StringPtr(it8->id));
key = BinSrchKey(it8->id);
if (key == SUNDEFINED) it8->sy = SIDENT;
else it8->sy = key;
@ -868,7 +773,6 @@ void InSymbol(cmsIT8* it8)
if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0)
{
SynError(it8, "Invalid hexadecimal number");
it8->sy = SEOF;
return;
}
@ -890,7 +794,6 @@ void InSymbol(cmsIT8* it8)
if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0)
{
SynError(it8, "Invalid binary number");
it8->sy = SEOF;
return;
}
@ -931,27 +834,26 @@ void InSymbol(cmsIT8* it8)
if (isidchar(it8 ->ch)) {
char buffer[127];
if (it8 ->sy == SINUM) {
snprintf(buffer, sizeof(buffer), "%d", it8->inum);
snprintf(it8->id, 127, "%d", it8->inum);
}
else {
snprintf(buffer, sizeof(buffer), it8 ->DoubleFormatter, it8->dnum);
snprintf(it8->id, 127, it8 ->DoubleFormatter, it8->dnum);
}
StringCat(it8->id, buffer);
k = (int) strlen(it8 ->id);
idptr = it8 ->id + k;
do {
StringAppend(it8->id, (char) it8->ch);
if (++k < MAXID) *idptr++ = (char) it8->ch;
NextCh(it8);
} while (isidchar(it8->ch));
*idptr = '\0';
it8->sy = SIDENT;
}
return;
@ -960,8 +862,12 @@ void InSymbol(cmsIT8* it8)
else
switch ((int) it8->ch) {
// Eof stream markers
// EOF marker -- ignore it
case '\x1a':
NextCh(it8);
break;
// Eof stream markers
case 0:
case -1:
it8->sy = SEOF;
@ -995,13 +901,29 @@ void InSymbol(cmsIT8* it8)
// String.
case '\'':
case '\"':
InStringSymbol(it8);
idptr = it8->str;
sng = it8->ch;
k = 0;
NextCh(it8);
while (k < (MAXSTR-1) && it8->ch != sng) {
if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1;
else {
*idptr++ = (char) it8->ch;
NextCh(it8);
k++;
}
}
it8->sy = SSTRING;
*idptr = '\0';
NextCh(it8);
break;
default:
SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
it8->sy = SEOF;
return;
}
@ -1016,33 +938,24 @@ void InSymbol(cmsIT8* it8)
if(it8 -> IncludeSP >= (MAXINCLUDE-1)) {
SynError(it8, "Too many recursion levels");
it8->sy = SEOF;
return;
}
InStringSymbol(it8);
if (!Check(it8, SSTRING, "Filename expected"))
{
it8->sy = SEOF;
return;
}
InSymbol(it8);
if (!Check(it8, SSTRING, "Filename expected")) return;
FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
if(FileNest == NULL) {
FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
if (FileNest == NULL) {
SynError(it8, "Out of memory");
it8->sy = SEOF;
return;
}
//if(FileNest == NULL)
// TODO: how to manage out-of-memory conditions?
}
if (BuildAbsolutePath(StringPtr(it8->str),
if (BuildAbsolutePath(it8->str,
it8->FileStack[it8->IncludeSP]->FileName,
FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
SynError(it8, "File path too long");
it8->sy = SEOF;
return;
}
@ -1050,7 +963,6 @@ void InSymbol(cmsIT8* it8)
if (FileNest->Stream == NULL) {
SynError(it8, "File %s not found", FileNest->FileName);
it8->sy = SEOF;
return;
}
it8->IncludeSP++;
@ -1101,12 +1013,12 @@ cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* Error
case SEOLN: // Empty value
Buffer[0]=0;
break;
case SIDENT: strncpy(Buffer, StringPtr(it8->id), max);
case SIDENT: strncpy(Buffer, it8->id, max);
Buffer[max-1]=0;
break;
case SINUM: snprintf(Buffer, max, "%d", it8 -> inum); break;
case SDNUM: snprintf(Buffer, max, it8->DoubleFormatter, it8 -> dnum); break;
case SSTRING: strncpy(Buffer, StringPtr(it8->str), max);
case SSTRING: strncpy(Buffer, it8->str, max);
Buffer[max-1] = 0;
break;
@ -1211,12 +1123,9 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
it8 ->Allocator.BlockSize = size;
it8 ->Allocator.Used = 0;
it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
}
if (it8->Allocator.Block == NULL)
return NULL;
ptr = it8 ->Allocator.Block + it8 ->Allocator.Used;
it8 ->Allocator.Used += size;
@ -1234,7 +1143,7 @@ char *AllocString(cmsIT8* it8, const char* str)
ptr = (char *) AllocChunk(it8, Size);
if (ptr) memcpy(ptr, str, Size-1);
if (ptr) strncpy (ptr, str, Size-1);
return ptr;
}
@ -1433,9 +1342,6 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
it8->IncludeSP = 0;
it8 -> lineno = 1;
it8->id = StringAlloc(it8, MAXSTR);
it8->str = StringAlloc(it8, MAXSTR);
strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
cmsIT8SetSheetType((cmsHANDLE) it8, "CGATS.17");
@ -1557,45 +1463,28 @@ const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, co
// ----------------------------------------------------------------- Datasets
// A safe atoi that returns 0 when NULL input is given
static
cmsInt32Number satoi(const char* b)
{
int n;
if (b == NULL) return 0;
n = atoi(b);
if (n > 0x7fffffffL) return 0x7fffffffL;
if (n < -0x7ffffffeL) return -0x7ffffffeL;
return (cmsInt32Number)n;
}
static
cmsBool AllocateDataFormat(cmsIT8* it8)
void AllocateDataFormat(cmsIT8* it8)
{
TABLE* t = GetTable(it8);
if (t -> DataFormat) return TRUE; // Already allocated
if (t -> DataFormat) return; // Already allocated
t -> nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t -> nSamples = (int) cmsIT8GetPropertyDbl(it8, "NUMBER_OF_FIELDS");
if (t -> nSamples <= 0) {
SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS");
return FALSE;
t -> nSamples = 10;
}
t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
if (t->DataFormat == NULL) {
SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
return FALSE;
}
return TRUE;
}
static
@ -1614,11 +1503,8 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
{
TABLE* t = GetTable(it8);
if (!t->DataFormat) {
if (!AllocateDataFormat(it8))
return FALSE;
}
if (!t->DataFormat)
AllocateDataFormat(it8);
if (n > t -> nSamples) {
SynError(it8, "More than NUMBER_OF_FIELDS fields.");
@ -1627,7 +1513,6 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
if (t->DataFormat) {
t->DataFormat[n] = AllocString(it8, label);
if (t->DataFormat[n] == NULL) return FALSE;
}
return TRUE;
@ -1640,31 +1525,20 @@ cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE h, int n, const char *Sample)
return SetDataFormat(it8, n, Sample);
}
// Convert to binary
// A safe atoi that returns 0 when NULL input is given
static
const char* satob(const char* v)
cmsInt32Number satoi(const char* b)
{
cmsUInt32Number x;
static char buf[33];
char *s = buf + 33;
if (v == NULL) return "0";
x = atoi(v);
*--s = 0;
if (!x) *--s = '0';
for (; x; x /= 2) *--s = '0' + x%2;
return s;
if (b == NULL) return 0;
return atoi(b);
}
static
cmsBool AllocateDataSet(cmsIT8* it8)
void AllocateDataSet(cmsIT8* it8)
{
TABLE* t = GetTable(it8);
if (t -> Data) return TRUE; // Already allocated
if (t -> Data) return; // Already allocated
t-> nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
t-> nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
@ -1672,7 +1546,6 @@ cmsBool AllocateDataSet(cmsIT8* it8)
if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
{
SynError(it8, "AllocateDataSet: too much data");
return FALSE;
}
else {
// Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
@ -1680,11 +1553,9 @@ cmsBool AllocateDataSet(cmsIT8* it8)
if (t->Data == NULL) {
SynError(it8, "AllocateDataSet: Unable to allocate data array");
return FALSE;
}
}
return TRUE;
}
static
@ -1706,9 +1577,8 @@ cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
{
TABLE* t = GetTable(it8);
if (!t->Data) {
if (!AllocateDataSet(it8)) return FALSE;
}
if (!t->Data)
AllocateDataSet(it8);
if (!t->Data) return FALSE;
@ -1848,7 +1718,7 @@ void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
break;
case WRITE_BINARY:
Writef(fp, "\t0b%s", satob(p ->Value));
Writef(fp, "\t0x%B", satoi(p ->Value));
break;
case WRITE_PAIR:
@ -2018,7 +1888,7 @@ cmsBool DataFormatSection(cmsIT8* it8)
return SynError(it8, "Sample type expected");
}
if (!SetDataFormat(it8, iField, StringPtr(it8->id))) return FALSE;
if (!SetDataFormat(it8, iField, it8->id)) return FALSE;
iField++;
InSymbol(it8);
@ -2051,9 +1921,8 @@ cmsBool DataSection (cmsIT8* it8)
InSymbol(it8); // Eats "BEGIN_DATA"
CheckEOLN(it8);
if (!t->Data) {
if (!AllocateDataSet(it8)) return FALSE;
}
if (!t->Data)
AllocateDataSet(it8);
while (it8->sy != SEND_DATA && it8->sy != SEOF)
{
@ -2065,28 +1934,11 @@ cmsBool DataSection (cmsIT8* it8)
if (it8->sy != SEND_DATA && it8->sy != SEOF) {
switch (it8->sy)
{
// To keep very long data
case SIDENT:
if (!SetData(it8, iSet, iField, StringPtr(it8->id)))
return FALSE;
break;
case SSTRING:
if (!SetData(it8, iSet, iField, StringPtr(it8->str)))
return FALSE;
break;
default:
if (!GetVal(it8, Buffer, 255, "Sample data expected"))
return FALSE;
if (!SetData(it8, iSet, iField, Buffer))
return FALSE;
}
iField++;
@ -2142,7 +1994,7 @@ cmsBool HeaderSection(cmsIT8* it8)
case SIDENT:
strncpy(VarName, StringPtr(it8->id), MAXID - 1);
strncpy(VarName, it8->id, MAXID - 1);
VarName[MAXID - 1] = 0;
if (!IsAvailableOnList(it8->ValidKeywords, VarName, NULL, &Key)) {
@ -2286,7 +2138,7 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
// If a newline is found, then this is a type string
if (it8 ->ch == '\n' || it8->ch == '\r') {
cmsIT8SetSheetType(it8, StringPtr(it8 ->id));
cmsIT8SetSheetType(it8, it8 ->id);
InSymbol(it8);
}
else
@ -2298,7 +2150,7 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
else
// Validate quoted strings
if (it8 ->sy == SSTRING) {
cmsIT8SetSheetType(it8, StringPtr(it8 ->str));
cmsIT8SetSheetType(it8, it8 ->str);
InSymbol(it8);
}
}
@ -2600,18 +2452,15 @@ cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyN
}
Props = (char**)AllocChunk(it8, sizeof(char*) * n);
if (Props != NULL) {
Props = (char **) AllocChunk(it8, sizeof(char *) * n);
// Pass#2 - Fill pointers
n = 0;
for (p = t->HeaderList; p != NULL; p = p->Next) {
Props[n++] = p->Keyword;
}
}
*PropertyNames = Props;
// Pass#2 - Fill pointers
n = 0;
for (p = t -> HeaderList; p != NULL; p = p->Next) {
Props[n++] = p -> Keyword;
}
*PropertyNames = Props;
return n;
}
@ -2643,14 +2492,12 @@ cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cP
Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
if (Props != NULL) {
// Pass#2 - Fill pointers
n = 0;
for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) {
if (tmp->Subkey != NULL)
Props[n++] = p->Subkey;
}
// Pass#2 - Fill pointers
n = 0;
for (tmp = p; tmp != NULL; tmp = tmp->NextSubkey) {
if(tmp->Subkey != NULL)
Props[n++] = p ->Subkey;
}
*SubpropertyNames = Props;
@ -2826,12 +2673,8 @@ cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char*
if (t-> nPatches == 0) {
if (!AllocateDataFormat(it8))
return FALSE;
if (!AllocateDataSet(it8))
return FALSE;
AllocateDataFormat(it8);
AllocateDataSet(it8);
CookPointers(it8);
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -415,7 +415,7 @@ cmsBool ComputeConversion(cmsUInt32Number i,
if (BPC) {
cmsCIEXYZ BlackPointIn = { 0, 0, 0}, BlackPointOut = { 0, 0, 0 };
cmsCIEXYZ BlackPointIn, BlackPointOut;
cmsDetectBlackPoint(&BlackPointIn, hProfiles[i-1], Intent, 0);
cmsDetectDestinationBlackPoint(&BlackPointOut, hProfiles[i], Intent, 0);
@ -659,7 +659,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
ColorSpaceOut == cmsSigRgbData ||
ColorSpaceOut == cmsSigCmykData) {
cmsStage* clip = _cmsStageClipNegatives(Result->ContextID, cmsChannelsOfColorSpace(ColorSpaceOut));
cmsStage* clip = _cmsStageClipNegatives(Result->ContextID, cmsChannelsOf(ColorSpaceOut));
if (clip == NULL) goto Error;
if (!cmsPipelineInsertStage(Result, cmsAT_END, clip))

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -108,7 +108,7 @@ long int CMSEXPORT cmsfilelength(FILE* f)
// User may override this behaviour by using a memory plug-in, which basically replaces
// the default memory management functions. In this case, no check is performed and it
// is up to the plug-in writer to keep in the safe side. There are only three functions
// is up to the plug-in writter to keep in the safe side. There are only three functions
// required to be implemented: malloc, realloc and free, although the user may want to
// replace the optional mallocZero, calloc and dup as well.
@ -337,7 +337,7 @@ void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Numbe
// Sub allocation takes care of many pointers of small size. The memory allocated in
// this way have be freed at once. Next function allocates a single chunk for linked list
// I prefer this method over realloc due to the big impact on xput realloc may have if
// I prefer this method over realloc due to the big inpact on xput realloc may have if
// memory is being swapped to disk. This approach is safer (although that may not be true on all platforms)
static
_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial)
@ -642,6 +642,7 @@ cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data)
if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL ||
Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE;
ctx->CreateMutexPtr = Plugin->CreateMutexPtr;
ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr;
ctx ->LockMutexPtr = Plugin ->LockMutexPtr;
@ -689,47 +690,3 @@ void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx)
ptr ->UnlockMutexPtr(ContextID, mtx);
}
}
// The global Context0 storage for parallelization plug-in
_cmsParallelizationPluginChunkType _cmsParallelizationPluginChunk = { 0 };
// Allocate parallelization container.
void _cmsAllocParallelizationPluginChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src)
{
if (src != NULL) {
void* from = src->chunks[ParallelizationPlugin];
ctx->chunks[ParallelizationPlugin] = _cmsSubAllocDup(ctx->MemPool, from, sizeof(_cmsParallelizationPluginChunkType));
}
else {
_cmsParallelizationPluginChunkType ParallelizationPluginChunk = { 0 };
ctx->chunks[ParallelizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &ParallelizationPluginChunk, sizeof(_cmsParallelizationPluginChunkType));
}
}
// Register parallel processing
cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginParalellization* Plugin = (cmsPluginParalellization*)Data;
_cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(ContextID, ParallelizationPlugin);
if (Data == NULL) {
// No parallelization routines
ctx->MaxWorkers = 0;
ctx->WorkerFlags = 0;
ctx->SchedulerFn = NULL;
return TRUE;
}
// callback is required
if (Plugin->SchedulerFn == NULL) return FALSE;
ctx->MaxWorkers = Plugin->MaxWorkers;
ctx->WorkerFlags = Plugin->WorkerFlags;
ctx->SchedulerFn = Plugin->SchedulerFn;
// All is ok
return TRUE;
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -236,7 +236,7 @@ _cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, i
}
// Low level allocate, which takes care of memory details. nEntries may be zero, and in this case
// no optimization curve is computed. nSegments may also be zero in the inverse case, where only the
// no optimation curve is computed. nSegments may also be zero in the inverse case, where only the
// optimization curve is given. Both features simultaneously is an error
static
cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsUInt32Number nEntries,
@ -456,8 +456,8 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// IEC 61966-3
// Y = (aX + b)^Gamma + c | X <= -b/a
// Y = c | else
// Y = (aX + b)^Gamma | X <= -b/a
// Y = c | else
case 3:
{
if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
@ -491,8 +491,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// X=-b/a | (Y<c)
case -3:
{
if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
fabs(Params[1]) < MATRIX_DET_TOLERANCE)
if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
{
Val = 0;
}
@ -537,31 +536,28 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// X=Y/c | Y< (ad+b)^g
case -4:
{
e = Params[1] * Params[4] + Params[2];
if (e < 0)
disc = 0;
if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
fabs(Params[1]) < MATRIX_DET_TOLERANCE ||
fabs(Params[3]) < MATRIX_DET_TOLERANCE)
{
Val = 0;
}
else
disc = pow(e, Params[0]);
if (R >= disc) {
if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
fabs(Params[1]) < MATRIX_DET_TOLERANCE)
Val = 0;
{
e = Params[1] * Params[4] + Params[2];
if (e < 0)
disc = 0;
else
disc = pow(e, Params[0]);
if (R >= disc) {
Val = (pow(R, 1.0 / Params[0]) - Params[2]) / Params[1];
}
else {
if (fabs(Params[3]) < MATRIX_DET_TOLERANCE)
Val = 0;
else
}
else {
Val = R / Params[3];
}
}
}
break;
@ -588,29 +584,26 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// X=(Y-f)/c | else
case -5:
{
disc = Params[3] * Params[4] + Params[6];
if (R >= disc) {
e = R - Params[5];
if (e < 0)
Val = 0;
else
{
if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
fabs(Params[1]) < MATRIX_DET_TOLERANCE)
if (fabs(Params[1]) < MATRIX_DET_TOLERANCE ||
fabs(Params[3]) < MATRIX_DET_TOLERANCE)
{
Val = 0;
}
else
{
disc = Params[3] * Params[4] + Params[6];
if (R >= disc) {
e = R - Params[5];
if (e < 0)
Val = 0;
else
Val = (pow(e, 1.0 / Params[0]) - Params[2]) / Params[1];
}
}
else {
if (fabs(Params[3]) < MATRIX_DET_TOLERANCE)
Val = 0;
else
else {
Val = (R - Params[6]) / Params[3];
}
}
}
break;
@ -631,8 +624,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
// ((Y - c) ^1/Gamma - b) / a
case -6:
{
if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
fabs(Params[1]) < MATRIX_DET_TOLERANCE)
if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
{
Val = 0;
}
@ -1504,9 +1496,6 @@ cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Num
}
}
// We need enough valid samples
if (n <= 1) return -1.0;
// Take a look on SD to see if gamma isn't exponential at all
Std = sqrt((n * sum2 - sum * sum) / (n*(n-1)));

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2021 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -228,15 +228,15 @@ typedef struct {
cmsHTRANSFORM hInput; // From whatever input color space. 16 bits to DBL
cmsHTRANSFORM hForward, hReverse; // Transforms going from Lab to colorant and back
cmsFloat64Number Threshold; // The threshold after which is considered out of gamut
cmsFloat64Number Thereshold; // The thereshold after which is considered out of gamut
} GAMUTCHAIN;
// This sampler does compute gamut boundaries by comparing original
// values with a transform going back and forth. Values above ERR_THRESHOLD
// values with a transform going back and forth. Values above ERR_THERESHOLD
// of maximum are considered out of gamut.
#define ERR_THRESHOLD 5
#define ERR_THERESHOLD 5
static
@ -275,17 +275,17 @@ int GamutSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Nu
// if dE1 is small and dE2 is small, value is likely to be in gamut
if (dE1 < t->Threshold && dE2 < t->Threshold)
if (dE1 < t->Thereshold && dE2 < t->Thereshold)
Out[0] = 0;
else {
// if dE1 is small and dE2 is big, undefined. Assume in gamut
if (dE1 < t->Threshold && dE2 > t->Threshold)
if (dE1 < t->Thereshold && dE2 > t->Thereshold)
Out[0] = 0;
else
// dE1 is big and dE2 is small, clearly out of gamut
if (dE1 > t->Threshold && dE2 < t->Threshold)
Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Threshold) + .5);
if (dE1 > t->Thereshold && dE2 < t->Thereshold)
Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5);
else {
// dE1 is big and dE2 is also big, could be due to perceptual mapping
@ -295,8 +295,8 @@ int GamutSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Nu
else
ErrorRatio = dE1 / dE2;
if (ErrorRatio > t->Threshold)
Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Threshold) + .5);
if (ErrorRatio > t->Thereshold)
Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5);
else
Out[0] = 0;
}
@ -326,8 +326,7 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
cmsStage* CLUT;
cmsUInt32Number dwFormat;
GAMUTCHAIN Chain;
cmsUInt32Number nGridpoints;
cmsInt32Number nChannels;
cmsUInt32Number nChannels, nGridpoints;
cmsColorSpaceSignature ColorSpace;
cmsUInt32Number i;
cmsHPROFILE ProfileList[256];
@ -353,10 +352,10 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
if (cmsIsMatrixShaper(hGamut)) {
Chain.Threshold = 1.0;
Chain.Thereshold = 1.0;
}
else {
Chain.Threshold = ERR_THRESHOLD;
Chain.Thereshold = ERR_THERESHOLD;
}
@ -376,7 +375,8 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
ColorSpace = cmsGetColorSpace(hGamut);
nChannels = cmsChannelsOfColorSpace(ColorSpace);
nChannels = cmsChannelsOf(ColorSpace);
nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2));
@ -501,9 +501,6 @@ cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile)
// Create a fake formatter for result
dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE);
// Unsupported color space?
if (dwFormatter == 0) return 0;
bp.nOutputChans = T_CHANNELS(dwFormatter);
bp.MaxTAC = 0; // Initial TAC is 0
@ -620,69 +617,3 @@ cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,
return TRUE;
}
// Detect whatever a given ICC profile works in linear (gamma 1.0) space
// 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.
// For gamma close to 1.0, RGB is linear. On profiles not supported, -1 is returned.
cmsFloat64Number CMSEXPORT cmsDetectRGBProfileGamma(cmsHPROFILE hProfile, cmsFloat64Number threshold)
{
cmsContext ContextID;
cmsHPROFILE hXYZ;
cmsHTRANSFORM xform;
cmsToneCurve* Y_curve;
cmsUInt16Number rgb[256][3];
cmsCIEXYZ XYZ[256];
cmsFloat32Number Y_normalized[256];
cmsFloat64Number gamma;
cmsProfileClassSignature cl;
int i;
if (cmsGetColorSpace(hProfile) != cmsSigRgbData)
return -1;
cl = cmsGetDeviceClass(hProfile);
if (cl != cmsSigInputClass && cl != cmsSigDisplayClass &&
cl != cmsSigOutputClass && cl != cmsSigColorSpaceClass)
return -1;
ContextID = cmsGetProfileContextID(hProfile);
hXYZ = cmsCreateXYZProfileTHR(ContextID);
if (hXYZ == NULL)
return -1;
xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_RGB_16, hXYZ, TYPE_XYZ_DBL,
INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE);
if (xform == NULL) { // If not RGB or forward direction is not supported, regret with the previous error
cmsCloseProfile(hXYZ);
return -1;
}
for (i = 0; i < 256; i++) {
rgb[i][0] = rgb[i][1] = rgb[i][2] = FROM_8_TO_16(i);
}
cmsDoTransform(xform, rgb, XYZ, 256);
cmsDeleteTransform(xform);
cmsCloseProfile(hXYZ);
for (i = 0; i < 256; i++) {
Y_normalized[i] = (cmsFloat32Number) XYZ[i].Y;
}
Y_curve = cmsBuildTabulatedToneCurveFloat(ContextID, 256, Y_normalized);
if (Y_curve == NULL)
return -1;
gamma = cmsEstimateGamma(Y_curve, threshold);
cmsFreeToneCurve(Y_curve);
return gamma;
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -406,7 +406,7 @@ static const cmsUInt32Number Mantissa[2048] = {
0x387fc000, 0x387fe000
};
static const cmsUInt16Number Offset[64] = {
static cmsUInt16Number Offset[64] = {
0x0000, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,
0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400,

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -229,8 +229,8 @@ void LinLerp1D(CMSREGISTER const cmsUInt16Number Value[],
int val3;
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
// if last value or just one point
if (Value[0] == 0xffff || p->Domain[0] == 0) {
// if last value...
if (Value[0] == 0xffff) {
Output[0] = LutTable[p -> Domain[0]];
}
@ -269,7 +269,7 @@ void LinLerp1Dfloat(const cmsFloat32Number Value[],
val2 = fclamp(Value[0]);
// if last value...
if (val2 == 1.0 || p->Domain[0] == 0) {
if (val2 == 1.0) {
Output[0] = LutTable[p -> Domain[0]];
}
else
@ -303,34 +303,20 @@ void Eval1Input(CMSREGISTER const cmsUInt16Number Input[],
cmsUInt32Number OutChan;
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
v = Input[0] * p16 -> Domain[0];
fk = _cmsToFixedDomain(v);
// if last value...
if (Input[0] == 0xffff || p16->Domain[0] == 0) {
k0 = FIXED_TO_INT(fk);
rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
cmsUInt32Number y0 = p16->Domain[0] * p16->opta[0];
k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
Output[OutChan] = LutTable[y0 + OutChan];
}
}
else
{
K0 = p16 -> opta[0] * k0;
K1 = p16 -> opta[0] * k1;
v = Input[0] * p16->Domain[0];
fk = _cmsToFixedDomain(v);
for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
k0 = FIXED_TO_INT(fk);
rk = (cmsUInt16Number)FIXED_REST_TO_INT(fk);
k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
K0 = p16->opta[0] * k0;
K1 = p16->opta[0] * k1;
for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
Output[OutChan] = LinearInterp(rk, LutTable[K0 + OutChan], LutTable[K1 + OutChan]);
}
Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
}
}
@ -351,12 +337,12 @@ void Eval1InputFloat(const cmsFloat32Number Value[],
val2 = fclamp(Value[0]);
// if last value...
if (val2 == 1.0 || p->Domain[0] == 0) {
if (val2 == 1.0) {
cmsUInt32Number start = p->Domain[0] * p->opta[0];
y0 = LutTable[p->Domain[0]];
for (OutChan = 0; OutChan < p->nOutputs; OutChan++) {
Output[OutChan] = LutTable[start + OutChan];
Output[OutChan] = y0;
}
}
else

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -404,7 +404,6 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha
cmsIOHANDLER* iohandler = NULL;
FILE* fm = NULL;
cmsInt32Number fileLen;
char mode[4] = { 0,0,0,0 };
_cmsAssert(FileName != NULL);
_cmsAssert(AccessMode != NULL);
@ -412,49 +411,16 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha
iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
if (iohandler == NULL) return NULL;
// Validate access mode
while (*AccessMode) {
switch (*AccessMode)
{
case 'r':
case 'w':
if (mode[0] == 0) {
mode[0] = *AccessMode;
mode[1] = 'b';
}
else {
_cmsFree(ContextID, iohandler);
cmsSignalError(ContextID, cmsERROR_FILE, "Access mode already specified '%c'", *AccessMode);
return NULL;
}
break;
// Close on exec. Not all runtime supports that. Up to the caller to decide.
case 'e':
mode[2] = 'e';
break;
default:
_cmsFree(ContextID, iohandler);
cmsSignalError(ContextID, cmsERROR_FILE, "Wrong access mode '%c'", *AccessMode);
return NULL;
}
AccessMode++;
}
switch (mode[0]) {
switch (*AccessMode) {
case 'r':
fm = fopen(FileName, mode);
fm = fopen(FileName, "rb");
if (fm == NULL) {
_cmsFree(ContextID, iohandler);
cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName);
return NULL;
}
fileLen = (cmsInt32Number)cmsfilelength(fm);
fileLen = cmsfilelength(fm);
if (fileLen < 0)
{
fclose(fm);
@ -462,11 +428,12 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha
cmsSignalError(ContextID, cmsERROR_FILE, "Cannot get size of file '%s'", FileName);
return NULL;
}
iohandler -> ReportedSize = (cmsUInt32Number) fileLen;
break;
case 'w':
fm = fopen(FileName, mode);
fm = fopen(FileName, "wb");
if (fm == NULL) {
_cmsFree(ContextID, iohandler);
cmsSignalError(ContextID, cmsERROR_FILE, "Couldn't create '%s'", FileName);
@ -476,7 +443,8 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const cha
break;
default:
_cmsFree(ContextID, iohandler); // Would never reach
_cmsFree(ContextID, iohandler);
cmsSignalError(ContextID, cmsERROR_FILE, "Unknown access mode '%c'", *AccessMode);
return NULL;
}
@ -503,7 +471,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* S
cmsIOHANDLER* iohandler = NULL;
cmsInt32Number fileSize;
fileSize = (cmsInt32Number)cmsfilelength(Stream);
fileSize = cmsfilelength(Stream);
if (fileSize < 0)
{
cmsSignalError(ContextID, cmsERROR_FILE, "Cannot get size of stream");
@ -540,15 +508,16 @@ cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io)
cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile;
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile;
if (Icc == NULL) return NULL;
return Icc->IOhandler;
if (Icc == NULL) return NULL;
return Icc->IOhandler;
}
// Creates an empty structure holding all required parameters
cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
{
time_t now = time(NULL);
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) _cmsMallocZero(ContextID, sizeof(_cmsICCPROFILE));
if (Icc == NULL) return NULL;
@ -560,22 +529,14 @@ cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
// Set default version
Icc ->Version = 0x02100000;
// Set default device class
Icc->DeviceClass = cmsSigDisplayClass;
// Set creation date/time
if (!_cmsGetTime(&Icc->Created))
goto Error;
memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created));
// Create a mutex if the user provided proper plugin. NULL otherwise
Icc ->UsrMutex = _cmsCreateMutex(ContextID);
// Return the handle
return (cmsHPROFILE) Icc;
Error:
_cmsFree(ContextID, Icc);
return NULL;
}
cmsContext CMSEXPORT cmsGetProfileContextID(cmsHPROFILE hProfile)
@ -721,27 +682,6 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig)
return _cmsSearchTag(Icc, sig, FALSE) >= 0;
}
// Checks for link compatibility
static
cmsBool CompatibleTypes(const cmsTagDescriptor* desc1, const cmsTagDescriptor* desc2)
{
cmsUInt32Number i;
if (desc1 == NULL || desc2 == NULL) return FALSE;
if (desc1->nSupportedTypes != desc2->nSupportedTypes) return FALSE;
if (desc1->ElemCount != desc2->ElemCount) return FALSE;
for (i = 0; i < desc1->nSupportedTypes; i++)
{
if (desc1->SupportedTypes[i] != desc2->SupportedTypes[i]) return FALSE;
}
return TRUE;
}
// Enforces that the profile version is per. spec.
// Operates on the big endian bytes from the profile.
// Called before converting to platform endianness.
@ -767,29 +707,6 @@ cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
return DWord;
}
// Check device class
static
cmsBool validDeviceClass(cmsProfileClassSignature cl)
{
if ((int)cl == 0) return TRUE; // We allow zero because older lcms versions defaulted to that.
switch (cl)
{
case cmsSigInputClass:
case cmsSigDisplayClass:
case cmsSigOutputClass:
case cmsSigLinkClass:
case cmsSigAbstractClass:
case cmsSigColorSpaceClass:
case cmsSigNamedColorClass:
return TRUE;
default:
return FALSE;
}
}
// Read profile header and validate it
cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
{
@ -826,16 +743,6 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
_cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes);
Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version));
if (Icc->Version > 0x5000000) {
cmsSignalError(Icc->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported profile version '0x%x'", Icc->Version);
return FALSE;
}
if (!validDeviceClass(Icc->DeviceClass)) {
cmsSignalError(Icc->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported device class '0x%x'", Icc->DeviceClass);
return FALSE;
}
// Get size as reported in header
HeaderSize = _cmsAdjustEndianess32(Header.size);
@ -869,7 +776,6 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
if (!_cmsReadUInt32Number(io, &Tag.size)) return FALSE;
// Perform some sanity check. Offset + size should fall inside file.
if (Tag.size == 0 || Tag.offset == 0) continue;
if (Tag.offset + Tag.size > HeaderSize ||
Tag.offset + Tag.size < Tag.offset)
continue;
@ -884,12 +790,7 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
if ((Icc ->TagOffsets[j] == Tag.offset) &&
(Icc ->TagSizes[j] == Tag.size)) {
// Check types.
if (CompatibleTypes(_cmsGetTagDescriptor(Icc->ContextID, Icc->TagNames[j]),
_cmsGetTagDescriptor(Icc->ContextID, Tag.sig))) {
Icc->TagLinked[Icc->TagCount] = Icc->TagNames[j];
}
Icc ->TagLinked[Icc ->TagCount] = Icc ->TagNames[j];
}
}
@ -897,19 +798,6 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
Icc ->TagCount++;
}
for (i = 0; i < Icc->TagCount; i++) {
for (j = 0; j < Icc->TagCount; j++) {
// Tags cannot be duplicate
if ((i != j) && (Icc->TagNames[i] == Icc->TagNames[j])) {
cmsSignalError(Icc->ContextID, cmsERROR_RANGE, "Duplicate tag found");
return FALSE;
}
}
}
return TRUE;
}
@ -1571,25 +1459,7 @@ cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUIn
return rc;
}
// Free one tag contents
static
void freeOneTag(_cmsICCPROFILE* Icc, cmsUInt32Number i)
{
if (Icc->TagPtrs[i]) {
cmsTagTypeHandler* TypeHandler = Icc->TagTypeHandlers[i];
if (TypeHandler != NULL) {
cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
LocalTypeHandler.ContextID = Icc->ContextID;
LocalTypeHandler.ICCVersion = Icc->Version;
LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc->TagPtrs[i]);
}
else
_cmsFree(Icc->ContextID, Icc->TagPtrs[i]);
}
}
// Closes a profile freeing any involved resources
cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
@ -1609,7 +1479,20 @@ cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
for (i=0; i < Icc -> TagCount; i++) {
freeOneTag(Icc, i);
if (Icc -> TagPtrs[i]) {
cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
if (TypeHandler != NULL) {
cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameters
LocalTypeHandler.ICCVersion = Icc ->Version;
LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
}
else
_cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
}
}
if (Icc ->IOhandler != NULL) {
@ -1661,12 +1544,8 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL;
n = _cmsSearchTag(Icc, sig, TRUE);
if (n < 0)
{
// Not found, return NULL
_cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex);
return NULL;
}
if (n < 0) goto Error; // Not found, return NULL
// If the element is already in memory, return the pointer
if (Icc -> TagPtrs[n]) {
@ -1695,13 +1574,6 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
if (TagSize < 8) goto Error;
io = Icc ->IOhandler;
if (io == NULL) { // This is a built-in profile that has been manipulated, abort early
cmsSignalError(Icc->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted built-in profile.");
goto Error;
}
// Seek to its location
if (!io -> Seek(io, Offset))
goto Error;
@ -1769,12 +1641,8 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
return Icc -> TagPtrs[n];
// Return error and unlock the data
// Return error and unlock tha data
Error:
freeOneTag(Icc, n);
Icc->TagPtrs[n] = NULL;
_cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return NULL;
}
@ -1913,9 +1781,11 @@ Error:
}
// Read and write raw data. Read/Write Raw/cooked pairs try to maintain consistency within the pair. Some sequences
// raw/cooked would work, but at a cost. Data "cooked" may be converted to "raw" by using the "write" serialization logic.
// In general it is better to avoid mixing pairs.
// Read and write raw data. The only way those function would work and keep consistence with normal read and write
// is to do an additional step of serialization. That means, readRaw would issue a normal read and then convert the obtained
// data to raw bytes by using the "write" serialization logic. And vice-versa. I know this may end in situations where
// raw data written does not exactly correspond with the raw data proposed to cmsWriteRaw data, but this approach allows
// to write a tag as raw data and the read it as handled.
cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize)
{
@ -1929,29 +1799,24 @@ cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature si
cmsUInt32Number rc;
cmsUInt32Number Offset, TagSize;
// Sanity check
if (data != NULL && BufferSize == 0) return 0;
if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
// Search for given tag in ICC profile directory
i = _cmsSearchTag(Icc, sig, TRUE);
if (i < 0) goto Error; // Not found,
// It is already read?
if (Icc -> TagPtrs[i] == NULL) {
// Not yet, get original position
// No yet, get original position
Offset = Icc ->TagOffsets[i];
TagSize = Icc ->TagSizes[i];
// read the data directly, don't keep copy
if (data != NULL) {
if (BufferSize < TagSize)
goto Error;
TagSize = BufferSize;
if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) goto Error;
if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) goto Error;
@ -1966,14 +1831,13 @@ cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature si
// The data has been already read, or written. But wait!, maybe the user chose to save as
// raw data. In this case, return the raw data directly
if (Icc ->TagSaveAsRaw[i]) {
if (data != NULL) {
TagSize = Icc ->TagSizes[i];
if (BufferSize < TagSize)
goto Error;
TagSize = BufferSize;
memmove(data, Icc ->TagPtrs[i], TagSize);
@ -1986,7 +1850,7 @@ cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature si
}
// Already read, or previously set by cmsWriteTag(). We need to serialize that
// data to raw to get something that makes sense
// data to raw in order to maintain consistency.
_cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
Object = cmsReadTag(hProfile, sig);

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -289,7 +289,7 @@ Error:
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if needed
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
static
cmsPipeline* _cmsReadFloatInputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
@ -351,8 +351,10 @@ cmsPipeline* CMSEXPORT _cmsReadInputLUT(cmsHPROFILE hProfile, cmsUInt32Number In
if (nc == NULL) return NULL;
Lut = cmsPipelineAlloc(ContextID, 0, 0);
if (Lut == NULL)
if (Lut == NULL) {
cmsFreeNamedColorList(nc);
return NULL;
}
if (!cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocNamedColor(nc, TRUE)) ||
!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID))) {
@ -563,7 +565,7 @@ void ChangeInterpolationToTrilinear(cmsPipeline* Lut)
}
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if needed
// Read the DToAX tag, adjusting the encoding of Lab or XYZ if neded
static
cmsPipeline* _cmsReadFloatOutputTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
@ -688,7 +690,7 @@ Error:
// ---------------------------------------------------------------------------------------------------------------
// Read the AToD0 tag, adjusting the encoding of Lab or XYZ if needed
// Read the AToD0 tag, adjusting the encoding of Lab or XYZ if neded
static
cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
{
@ -767,6 +769,7 @@ cmsPipeline* CMSEXPORT _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, cmsUInt32Numb
return Lut;
Error:
cmsPipelineFree(Lut);
cmsFreeNamedColorList(nc);
return NULL;
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -496,7 +496,7 @@ cmsUInt32Number CubeSize(const cmsUInt32Number Dims[], cmsUInt32Number b)
for (rv = 1; b > 0; b--) {
dim = Dims[b-1];
if (dim <= 1) return 0; // Error
if (dim == 0) return 0; // Error
rv *= dim;
@ -1255,11 +1255,6 @@ void* CMSEXPORT cmsStageData(const cmsStage* mpe)
return mpe -> Data;
}
cmsContext CMSEXPORT cmsGetStageContextID(const cmsStage* mpe)
{
return mpe -> ContextID;
}
cmsStage* CMSEXPORT cmsStageNext(const cmsStage* mpe)
{
return mpe -> Next;

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -233,7 +233,7 @@ void strFrom16(char str[3], cmsUInt16Number n)
}
// 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
// In the case the user explicitely 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);
@ -571,12 +571,8 @@ cmsBool GrowNamedColorList(cmsNAMEDCOLORLIST* v)
// Allocate a list for n elements
cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUInt32Number n, cmsUInt32Number ColorantCount, const char* Prefix, const char* Suffix)
{
cmsNAMEDCOLORLIST* v;
cmsNAMEDCOLORLIST* v = (cmsNAMEDCOLORLIST*) _cmsMallocZero(ContextID, sizeof(cmsNAMEDCOLORLIST));
if (ColorantCount > cmsMAXCHANNELS)
return NULL;
v = (cmsNAMEDCOLORLIST*)_cmsMallocZero(ContextID, sizeof(cmsNAMEDCOLORLIST));
if (v == NULL) return NULL;
v ->List = NULL;
@ -674,7 +670,7 @@ cmsUInt32Number CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* NamedColor
return NamedColorList ->nColors;
}
// Info about a given color
// Info aboout a given color
cmsBool CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor,
char* Name,
char* Prefix,

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -676,6 +676,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
{
cmsPipeline* Src = NULL;
cmsPipeline* Dest = NULL;
cmsStage* mpe;
cmsStage* CLUT;
cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
cmsUInt32Number nGridPoints;
@ -697,7 +698,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
if (ColorSpace == (cmsColorSpaceSignature)0 ||
OutputColorSpace == (cmsColorSpaceSignature)0) return FALSE;
nGridPoints = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);
nGridPoints = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);
// For empty LUTs, 2 points are enough
if (cmsPipelineStageCount(*Lut) == 0)
@ -705,6 +706,13 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
Src = *Lut;
// Named color pipelines cannot be optimized either
for (mpe = cmsPipelineGetPtrToFirstStage(Src);
mpe != NULL;
mpe = cmsStageNext(mpe)) {
if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
}
// Allocate an empty LUT
Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
if (!Dest) return FALSE;
@ -1072,6 +1080,7 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
cmsStage* OptimizedCLUTmpe;
cmsColorSpaceSignature ColorSpace, OutputColorSpace;
cmsStage* OptimizedPrelinMpe;
cmsStage* mpe;
cmsToneCurve** OptimizedPrelinCurves;
_cmsStageCLutData* OptimizedPrelinCLUT;
@ -1093,6 +1102,13 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
OriginalLut = *Lut;
// Named color pipelines cannot be optimized either
for (mpe = cmsPipelineGetPtrToFirstStage(OriginalLut);
mpe != NULL;
mpe = cmsStageNext(mpe)) {
if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
}
ColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*InputFormat));
OutputColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*OutputFormat));
@ -1546,10 +1562,10 @@ void* DupMatShaper(cmsContext ContextID, const void* Data)
}
// A fast matrix-shaper evaluator for 8 bits. This is a bit tricky since I'm using 1.14 signed fixed point
// A fast matrix-shaper evaluator for 8 bits. This is a bit ticky since I'm using 1.14 signed fixed point
// to accomplish some performance. Actually it takes 256x3 16 bits tables and 16385 x 3 tables of 8 bits,
// in total about 50K, and the performance boost is huge!
static CMS_NO_SANITIZE
static
void MatShaperEval16(CMSREGISTER const cmsUInt16Number In[],
CMSREGISTER cmsUInt16Number Out[],
CMSREGISTER const void* D)
@ -1931,7 +1947,6 @@ cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
_cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
_cmsOptimizationCollection* Opts;
cmsBool AnySuccess = FALSE;
cmsStage* mpe;
// A CLUT is being asked, so force this specific optimization
if (*dwFlags & cmsFLAGS_FORCE_CLUT) {
@ -1946,13 +1961,6 @@ cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
return TRUE;
}
// Named color pipelines cannot be optimized
for (mpe = cmsPipelineGetPtrToFirstStage(*PtrLut);
mpe != NULL;
mpe = cmsStageNext(mpe)) {
if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
}
// Try to get rid of identities and trivial conversions.
AnySuccess = PreOptimize(*PtrLut);

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -108,7 +108,6 @@ typedef struct {
#define ANYSWAP DOSWAP_SH(1)
#define ANYSWAPFIRST SWAPFIRST_SH(1)
#define ANYFLAVOR FLAVOR_SH(1)
#define ANYPREMUL PREMUL_SH(1)
// Suppress waning about info never being used
@ -132,40 +131,20 @@ cmsUInt8Number* UnrollChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number v;
cmsUInt16Number v;
cmsUInt32Number i;
cmsUInt32Number alpha_factor = 1;
if (ExtraFirst) {
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));
accum += Extra;
}
else
{
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan]));
}
for (i=0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
v = FROM_8_TO_16(*accum);
v = Reverse ? REVERSE_FLAVOR_16(v) : v;
if (Premul && alpha_factor > 0)
{
v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
if (v > 0xffff) v = 0xffff;
}
wIn[index] = (cmsUInt16Number) v;
wIn[index] = v;
accum++;
}
@ -187,7 +166,6 @@ cmsUInt8Number* UnrollChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
}
// Extra channels are just ignored because come in the next planes
static
cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
@ -200,47 +178,24 @@ cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
cmsUInt32Number i;
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
cmsUInt8Number* Init = accum;
cmsUInt32Number alpha_factor = 1;
if (ExtraFirst) {
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[0]));
accum += Extra * Stride;
}
else
{
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
if (DoSwap ^ SwapFirst) {
accum += T_EXTRA(info -> InputFormat) * Stride;
}
for (i=0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
cmsUInt32Number v = FROM_8_TO_16(*accum);
cmsUInt16Number v = FROM_8_TO_16(*accum);
v = Reverse ? REVERSE_FLAVOR_16(v) : v;
if (Premul && alpha_factor > 0)
{
v = ((cmsUInt32Number)((cmsUInt32Number)v << 16) / alpha_factor);
if (v > 0xffff) v = 0xffff;
}
wIn[index] = (cmsUInt16Number) v;
wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
accum += Stride;
}
return (Init + 1);
}
// Special cases, provided for performance
static
cmsUInt8Number* Unroll4Bytes(CMSREGISTER _cmsTRANSFORM* info,
@ -591,58 +546,6 @@ cmsUInt8Number* UnrollAnyWords(CMSREGISTER _cmsTRANSFORM* info,
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* UnrollAnyWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wIn[],
CMSREGISTER cmsUInt8Number* accum,
CMSREGISTER cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number i;
cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
if (ExtraFirst) {
accum += sizeof(cmsUInt16Number);
}
for (i=0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
cmsUInt32Number v = *(cmsUInt16Number*) accum;
if (SwapEndian)
v = CHANGE_ENDIAN(v);
if (alpha_factor > 0) {
v = (v << 16) / alpha_factor;
if (v > 0xffff) v = 0xffff;
}
wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);
accum += sizeof(cmsUInt16Number);
}
if (!ExtraFirst) {
accum += sizeof(cmsUInt16Number);
}
return accum;
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* UnrollPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wIn[],
@ -676,49 +579,6 @@ cmsUInt8Number* UnrollPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
return (Init + sizeof(cmsUInt16Number));
}
static
cmsUInt8Number* UnrollPlanarWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wIn[],
CMSREGISTER cmsUInt8Number* accum,
CMSREGISTER cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
cmsUInt32Number i;
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt8Number* Init = accum;
cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
if (ExtraFirst) {
accum += Stride;
}
for (i=0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
cmsUInt32Number v = (cmsUInt32Number) *(cmsUInt16Number*) accum;
if (SwapEndian)
v = CHANGE_ENDIAN(v);
if (alpha_factor > 0) {
v = (v << 16) / alpha_factor;
if (v > 0xffff) v = 0xffff;
}
wIn[index] = (cmsUInt16Number) (Reverse ? REVERSE_FLAVOR_16(v) : v);
accum += Stride;
}
return (Init + sizeof(cmsUInt16Number));
}
static
cmsUInt8Number* Unroll4Words(CMSREGISTER _cmsTRANSFORM* info,
@ -1256,110 +1116,6 @@ cmsUInt8Number* UnrollDouble1Chan(CMSREGISTER _cmsTRANSFORM* info,
//-------------------------------------------------------------------------------------------------------------------
// For anything going from cmsUInt8Number
static
cmsUInt8Number* Unroll8ToFloat(_cmsTRANSFORM* info,
cmsFloat32Number wIn[],
cmsUInt8Number* accum,
cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
cmsFloat32Number v;
cmsUInt32Number i, start = 0;
Stride /= PixelSize(info->InputFormat);
if (ExtraFirst)
start = Extra;
for (i = 0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
if (Planar)
v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[(i + start) * Stride];
else
v = (cmsFloat32Number) ((cmsUInt8Number *)accum)[i + start];
v /= 255.0F;
wIn[index] = Reverse ? 1 - v : v;
}
if (Extra == 0 && SwapFirst) {
cmsFloat32Number tmp = wIn[0];
memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
wIn[nChan - 1] = tmp;
}
if (T_PLANAR(info->InputFormat))
return accum + sizeof(cmsUInt8Number);
else
return accum + (nChan + Extra) * sizeof(cmsUInt8Number);
}
// For anything going from cmsUInt16Number
static
cmsUInt8Number* Unroll16ToFloat(_cmsTRANSFORM* info,
cmsFloat32Number wIn[],
cmsUInt8Number* accum,
cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
cmsFloat32Number v;
cmsUInt32Number i, start = 0;
Stride /= PixelSize(info->InputFormat);
if (ExtraFirst)
start = Extra;
for (i = 0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
if (Planar)
v = (cmsFloat32Number)((cmsUInt16Number*)accum)[(i + start) * Stride];
else
v = (cmsFloat32Number)((cmsUInt16Number*)accum)[i + start];
v /= 65535.0F;
wIn[index] = Reverse ? 1 - v : v;
}
if (Extra == 0 && SwapFirst) {
cmsFloat32Number tmp = wIn[0];
memmove(&wIn[0], &wIn[1], (nChan - 1) * sizeof(cmsFloat32Number));
wIn[nChan - 1] = tmp;
}
if (T_PLANAR(info->InputFormat))
return accum + sizeof(cmsUInt16Number);
else
return accum + (nChan + Extra) * sizeof(cmsUInt16Number);
}
// For anything going from cmsFloat32Number
static
cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
@ -1368,30 +1124,19 @@ cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);
cmsFloat32Number v;
cmsUInt32Number i, start = 0;
cmsFloat32Number maximum = IsInkSpace(info->InputFormat) ? 100.0F : 1.0F;
cmsFloat32Number alpha_factor = 1.0f;
cmsFloat32Number* ptr = (cmsFloat32Number*)accum;
cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
Stride /= PixelSize(info->InputFormat);
if (Premul && Extra)
{
if (Planar)
alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
else
alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
}
if (ExtraFirst)
start = Extra;
@ -1400,12 +1145,9 @@ cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
if (Planar)
v = ptr[(i + start) * Stride];
v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
else
v = ptr[i + start];
if (Premul && alpha_factor > 0)
v /= alpha_factor;
v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[i + start];
v /= maximum;
@ -1435,30 +1177,19 @@ cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->InputFormat);
cmsUInt32Number Extra = T_EXTRA(info->InputFormat);
cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info ->InputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info ->InputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info -> InputFormat);
cmsUInt32Number Extra = T_EXTRA(info -> InputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Planar = T_PLANAR(info->InputFormat);
cmsUInt32Number Premul = T_PREMUL(info->InputFormat);
cmsUInt32Number Planar = T_PLANAR(info -> InputFormat);
cmsFloat64Number v;
cmsUInt32Number i, start = 0;
cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
cmsFloat64Number alpha_factor = 1.0;
cmsFloat64Number* ptr = (cmsFloat64Number*)accum;
Stride /= PixelSize(info->InputFormat);
if (Premul && Extra)
{
if (Planar)
alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
else
alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
}
if (ExtraFirst)
start = Extra;
@ -1471,10 +1202,6 @@ cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
else
v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[i + start];
if (Premul && alpha_factor > 0)
v /= alpha_factor;
v /= maximum;
wIn[index] = (cmsFloat32Number) (Reverse ? 1.0 - v : v);
@ -1556,6 +1283,8 @@ cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info,
}
}
// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
static
cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info,
@ -1616,132 +1345,44 @@ cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info,
}
cmsINLINE void lab4toFloat(cmsFloat32Number wIn[], cmsUInt16Number lab4[3])
{
cmsFloat32Number L = (cmsFloat32Number) lab4[0] / 655.35F;
cmsFloat32Number a = ((cmsFloat32Number) lab4[1] / 257.0F) - 128.0F;
cmsFloat32Number b = ((cmsFloat32Number) lab4[2] / 257.0F) - 128.0F;
wIn[0] = (L / 100.0F); // from 0..100 to 0..1
wIn[1] = ((a + 128.0F) / 255.0F); // form -128..+127 to 0..1
wIn[2] = ((b + 128.0F) / 255.0F);
}
static
cmsUInt8Number* UnrollLabV2_8ToFloat(_cmsTRANSFORM* info,
cmsFloat32Number wIn[],
cmsUInt8Number* accum,
cmsUInt32Number Stride)
{
cmsUInt16Number lab4[3];
lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
lab4toFloat(wIn, lab4);
return accum;
cmsUNUSED_PARAMETER(info);
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* UnrollALabV2_8ToFloat(_cmsTRANSFORM* info,
cmsFloat32Number wIn[],
cmsUInt8Number* accum,
cmsUInt32Number Stride)
{
cmsUInt16Number lab4[3];
accum++; // A
lab4[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // L
lab4[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // a
lab4[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++; // b
lab4toFloat(wIn, lab4);
return accum;
cmsUNUSED_PARAMETER(info);
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* UnrollLabV2_16ToFloat(_cmsTRANSFORM* info,
cmsFloat32Number wIn[],
cmsUInt8Number* accum,
cmsUInt32Number Stride)
{
cmsUInt16Number lab4[3];
lab4[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // L
lab4[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // a
lab4[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2; // b
lab4toFloat(wIn, lab4);
return accum;
cmsUNUSED_PARAMETER(info);
cmsUNUSED_PARAMETER(Stride);
}
// Packing routines -----------------------------------------------------------------------------------------------------------
// Generic chunky for byte
static
cmsUInt8Number* PackChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wOut[],
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER cmsUInt32Number Stride)
cmsUInt8Number* PackAnyBytes(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wOut[],
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER 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 Premul = T_PREMUL(info->OutputFormat);
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 ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt8Number* swap1;
cmsUInt16Number v = 0;
cmsUInt8Number v = 0;
cmsUInt32Number i;
cmsUInt32Number alpha_factor = 0;
swap1 = output;
if (ExtraFirst) {
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
output += Extra;
}
else
{
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan]));
}
for (i=0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
v = wOut[index];
v = FROM_16_TO_8(wOut[index]);
if (Reverse)
v = REVERSE_FLAVOR_16(v);
v = REVERSE_FLAVOR_8(v);
if (Premul && alpha_factor != 0)
{
v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
}
*output++ = FROM_16_TO_8(v);
*output++ = v;
}
if (!ExtraFirst) {
@ -1751,47 +1392,39 @@ cmsUInt8Number* PackChunkyBytes(CMSREGISTER _cmsTRANSFORM* info,
if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, nChan-1);
*swap1 = FROM_16_TO_8(v);
*swap1 = v;
}
return output;
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* PackChunkyWords(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wOut[],
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER cmsUInt32Number Stride)
cmsUInt8Number* PackAnyWords(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wOut[],
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
cmsUInt32Number SwapEndian = T_ENDIAN16(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 Premul = T_PREMUL(info->OutputFormat);
cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);
cmsUInt32Number SwapEndian = T_ENDIAN16(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 ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt16Number* swap1;
cmsUInt16Number v = 0;
cmsUInt32Number i;
cmsUInt32Number alpha_factor = 0;
swap1 = (cmsUInt16Number*) output;
if (ExtraFirst) {
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(*(cmsUInt16Number*) output);
output += Extra * sizeof(cmsUInt16Number);
}
else
{
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[nChan]);
}
for (i=0; i < nChan; i++) {
@ -1805,11 +1438,6 @@ cmsUInt8Number* PackChunkyWords(CMSREGISTER _cmsTRANSFORM* info,
if (Reverse)
v = REVERSE_FLAVOR_16(v);
if (Premul && alpha_factor != 0)
{
v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
}
*(cmsUInt16Number*) output = v;
output += sizeof(cmsUInt16Number);
@ -1825,60 +1453,38 @@ cmsUInt8Number* PackChunkyWords(CMSREGISTER _cmsTRANSFORM* info,
*swap1 = v;
}
return output;
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* PackPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wOut[],
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->OutputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);
cmsUInt32Number i;
cmsUInt8Number* Init = output;
cmsUInt32Number alpha_factor = 0;
if (ExtraFirst) {
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[0]));
output += Extra * Stride;
}
else
{
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(output[nChan * Stride]));
if (DoSwap ^ SwapFirst) {
output += T_EXTRA(info -> OutputFormat) * Stride;
}
for (i=0; i < nChan; i++) {
cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
cmsUInt16Number v = wOut[index];
if (Reverse)
v = REVERSE_FLAVOR_16(v);
if (Premul && alpha_factor != 0)
{
v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
}
*(cmsUInt8Number*)output = FROM_16_TO_8(v);
cmsUInt8Number v = FROM_16_TO_8(wOut[index]);
*(cmsUInt8Number*) output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v);
output += Stride;
}
@ -1894,30 +1500,16 @@ cmsUInt8Number* PackPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER cmsUInt32Number Stride)
{
cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
cmsUInt32Number Premul = T_PREMUL(info->OutputFormat);
cmsUInt32Number SwapEndian = T_ENDIAN16(info->OutputFormat);
cmsUInt32Number nChan = T_CHANNELS(info -> OutputFormat);
cmsUInt32Number DoSwap = T_DOSWAP(info ->OutputFormat);
cmsUInt32Number Reverse = T_FLAVOR(info ->OutputFormat);
cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat);
cmsUInt32Number i;
cmsUInt8Number* Init = output;
cmsUInt16Number v;
cmsUInt32Number alpha_factor = 0;
if (ExtraFirst) {
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*) output)[0]);
output += Extra * Stride;
}
else
{
if (Premul && Extra)
alpha_factor = _cmsToFixedDomain(((cmsUInt16Number*)output)[nChan * Stride]);
if (DoSwap) {
output += T_EXTRA(info -> OutputFormat) * Stride;
}
for (i=0; i < nChan; i++) {
@ -1932,11 +1524,6 @@ cmsUInt8Number* PackPlanarWords(CMSREGISTER _cmsTRANSFORM* info,
if (Reverse)
v = REVERSE_FLAVOR_16(v);
if (Premul && alpha_factor != 0)
{
v = (cmsUInt16Number)((cmsUInt32Number)((cmsUInt32Number)v * alpha_factor + 0x8000) >> 16);
}
*(cmsUInt16Number*) output = v;
output += Stride;
}
@ -3083,6 +2670,10 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,
}
static
cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info,
cmsFloat32Number wOut[],
@ -3467,10 +3058,10 @@ static const cmsFormatters16 InputFormatters16[] = {
{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Unroll4BytesSwap},
{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Unroll4BytesSwapSwapFirst},
{ BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYPREMUL|
{ BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|
ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes},
{ BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYPREMUL|
{ BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|
ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes},
{ CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Unroll1Word},
@ -3492,10 +3083,6 @@ static const cmsFormatters16 InputFormatters16[] = {
{ BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarWords},
{ BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollAnyWords},
{ BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE|PREMUL_SH(1), UnrollPlanarWordsPremul},
{ BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE|PREMUL_SH(1), UnrollAnyWordsPremul}
};
@ -3511,23 +3098,13 @@ static const cmsFormattersFloat InputFormattersFloat[] = {
{ TYPE_XYZ_FLT, ANYPLANAR|ANYEXTRA, UnrollXYZFloatToFloat},
{ FLOAT_SH(1)|BYTES_SH(4), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
ANYPREMUL|ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat},
ANYCHANNELS|ANYSPACE, UnrollFloatsToFloat},
{ FLOAT_SH(1)|BYTES_SH(0), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
ANYCHANNELS|ANYSPACE|ANYPREMUL, UnrollDoublesToFloat},
{ TYPE_LabV2_8, 0, UnrollLabV2_8ToFloat },
{ TYPE_ALabV2_8, 0, UnrollALabV2_8ToFloat },
{ TYPE_LabV2_16, 0, UnrollLabV2_16ToFloat },
{ BYTES_SH(1), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
ANYCHANNELS|ANYSPACE, Unroll8ToFloat},
{ BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
ANYCHANNELS|ANYSPACE, Unroll16ToFloat},
ANYCHANNELS|ANYSPACE, UnrollDoublesToFloat},
#ifndef CMS_NO_HALF_SUPPORT
{ FLOAT_SH(1)|BYTES_SH(2), ANYPLANAR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
ANYCHANNELS|ANYSPACE, UnrollHalfToFloat},
ANYCHANNELS|ANYSPACE, UnrollHalfToFloat},
#endif
};
@ -3621,20 +3198,16 @@ static const cmsFormatters16 OutputFormatters16[] = {
ANYSPACE, Pack3BytesAndSkip1SwapSwapFirst},
{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1), ANYSPACE, Pack3BytesAndSkip1Swap},
{ CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack3BytesSwap},
{ CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes},
{ CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap},
{ CHANNELS_SH(4)|BYTES_SH(1), ANYSPACE, Pack4Bytes},
{ CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1), ANYSPACE, Pack4BytesReverse},
{ CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapFirst},
{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack4BytesSwap},
{ CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE, Pack4BytesSwapSwapFirst},
{ CHANNELS_SH(6)|BYTES_SH(1), ANYSPACE, Pack6Bytes},
{ CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1), ANYSPACE, Pack6BytesSwap},
{ BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|
ANYSPACE|ANYPREMUL, PackChunkyBytes},
{ BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|
ANYCHANNELS|ANYSPACE|ANYPREMUL, PackPlanarBytes},
{ BYTES_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes},
{ BYTES_SH(1)|PLANAR_SH(1), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes},
{ CHANNELS_SH(1)|BYTES_SH(2), ANYSPACE, Pack1Word},
{ CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1), ANYSPACE, Pack1WordSkip1},
@ -3659,10 +3232,8 @@ static const cmsFormatters16 OutputFormatters16[] = {
{ CHANNELS_SH(6)|BYTES_SH(2), ANYSPACE, Pack6Words},
{ CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1), ANYSPACE, Pack6WordsSwap},
{ BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|
ANYEXTRA|ANYCHANNELS|ANYSPACE|ANYPREMUL, PackChunkyWords},
{ BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|
ANYCHANNELS|ANYSPACE|ANYPREMUL, PackPlanarWords}
{ BYTES_SH(2)|PLANAR_SH(1), ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarWords},
{ BYTES_SH(2), ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyWords}
};
@ -3834,11 +3405,6 @@ cmsFormatter CMSEXPORT _cmsGetFormatter(cmsContext ContextID,
_cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
cmsFormattersFactoryList* f;
if (T_CHANNELS(Type) == 0) {
static const cmsFormatter nullFormatter = { 0 };
return nullFormatter;
}
for (f =ctx->FactoryList; f != NULL; f = f ->Next) {
cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);
@ -3873,12 +3439,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfil
cmsColorSpaceSignature ColorSpace = cmsGetColorSpace(hProfile);
cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);
cmsInt32Number nOutputChans = cmsChannelsOfColorSpace(ColorSpace);
cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
cmsUInt32Number Float = lIsFloat ? 1U : 0;
// Unsupported color space?
if (nOutputChans < 0) return 0;
// Create a fake formatter for result
return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
}
@ -3893,9 +3456,6 @@ cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsU
cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
cmsUInt32Number Float = lIsFloat ? 1U : 0;
// Unsupported color space?
if (nOutputChans < 0) return 0;
// Create a fake formatter for result
return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -903,7 +903,7 @@ int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)
}
cmsInt32Number CMSEXPORT cmsChannelsOfColorSpace(cmsColorSpaceSignature ColorSpace)
cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
{
switch (ColorSpace) {
@ -964,16 +964,6 @@ cmsInt32Number CMSEXPORT cmsChannelsOfColorSpace(cmsColorSpaceSignature ColorSpa
case cmsSigMCHFData:
case cmsSig15colorData: return 15;
default: return -1;
default: return 3;
}
}
/**
* DEPRECATED: Provided for compatibility only
*/
cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
{
int n = cmsChannelsOfColorSpace(ColorSpace);
if (n < 0) return 3;
return (cmsUInt32Number)n;
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -197,20 +197,17 @@ cmsBool CMSEXPORT _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n)
cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
{
union typeConverter {
cmsUInt32Number integer;
cmsFloat32Number floating_point;
} tmp;
cmsUInt32Number tmp;
_cmsAssert(io != NULL);
if (io->Read(io, &tmp.integer, sizeof(cmsUInt32Number), 1) != 1)
if (io->Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
return FALSE;
if (n != NULL) {
tmp.integer = _cmsAdjustEndianess32(tmp.integer);
*n = tmp.floating_point;
tmp = _cmsAdjustEndianess32(tmp);
*n = *(cmsFloat32Number*)(void*)&tmp;
// Safeguard which covers against absurd values
if (*n > 1E+20 || *n < -1E+20) return FALSE;
@ -337,14 +334,13 @@ cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n)
cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n)
{
union typeConverter {
cmsUInt32Number integer;
cmsFloat32Number floating_point;
} tmp;
cmsUInt32Number tmp;
tmp.floating_point = n;
tmp.integer = _cmsAdjustEndianess32(tmp.integer);
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp.integer) != 1)
_cmsAssert(io != NULL);
tmp = *(cmsUInt32Number*) (void*) &n;
tmp = _cmsAdjustEndianess32(tmp);
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
return FALSE;
return TRUE;
@ -654,10 +650,6 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginParalellizationSig:
if (!_cmsRegisterParallelizationPlugin(id, Plugin)) return FALSE;
break;
default:
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
return FALSE;
@ -680,25 +672,24 @@ void CMSEXPORT cmsUnregisterPlugins(void)
// pointers structure. All global vars are referenced here.
static struct _cmsContext_struct globalContext = {
NULL, // Not in the linked list
NULL, // No suballocator
NULL, // Not in the linked list
NULL, // No suballocator
{
NULL, // UserPtr,
&_cmsLogErrorChunk, // Logger,
&_cmsAlarmCodesChunk, // AlarmCodes,
&_cmsAdaptationStateChunk, // AdaptationState,
&_cmsMemPluginChunk, // MemPlugin,
&_cmsInterpPluginChunk, // InterpPlugin,
&_cmsCurvesPluginChunk, // CurvesPlugin,
&_cmsFormattersPluginChunk, // FormattersPlugin,
&_cmsTagTypePluginChunk, // TagTypePlugin,
&_cmsTagPluginChunk, // TagPlugin,
&_cmsIntentsPluginChunk, // IntentPlugin,
&_cmsMPETypePluginChunk, // MPEPlugin,
&_cmsOptimizationPluginChunk, // OptimizationPlugin,
&_cmsTransformPluginChunk, // TransformPlugin,
&_cmsMutexPluginChunk, // MutexPlugin,
&_cmsParallelizationPluginChunk // ParallelizationPlugin
NULL, // UserPtr,
&_cmsLogErrorChunk, // Logger,
&_cmsAlarmCodesChunk, // AlarmCodes,
&_cmsAdaptationStateChunk, // AdaptationState,
&_cmsMemPluginChunk, // MemPlugin,
&_cmsInterpPluginChunk, // InterpPlugin,
&_cmsCurvesPluginChunk, // CurvesPlugin,
&_cmsFormattersPluginChunk, // FormattersPlugin,
&_cmsTagTypePluginChunk, // TagTypePlugin,
&_cmsTagPluginChunk, // TagPlugin,
&_cmsIntentsPluginChunk, // IntentPlugin,
&_cmsMPETypePluginChunk, // MPEPlugin,
&_cmsOptimizationPluginChunk, // OptimizationPlugin,
&_cmsTransformPluginChunk, // TransformPlugin,
&_cmsMutexPluginChunk // MutexPlugin
},
{ NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
@ -709,65 +700,17 @@ static struct _cmsContext_struct globalContext = {
static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;
static struct _cmsContext_struct* _cmsContextPoolHead = NULL;
// Make sure context is initialized (needed on windows)
static
cmsBool InitContextMutex(void)
{
// See the comments regarding locking in lcms2_internal.h
// for an explanation of why we need the following code.
#ifndef CMS_NO_PTHREADS
#ifdef CMS_IS_WINDOWS_
#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
static cmsBool already_initialized = FALSE;
if (!already_initialized)
{
static HANDLE _cmsWindowsInitMutex = NULL;
static volatile HANDLE* mutex = &_cmsWindowsInitMutex;
if (*mutex == NULL)
{
HANDLE p = CreateMutex(NULL, FALSE, NULL);
if (p && InterlockedCompareExchangePointer((void**)mutex, (void*)p, NULL) != NULL)
CloseHandle(p);
}
if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)
{
cmsSignalError(0, cmsERROR_INTERNAL, "Mutex lock failed");
return FALSE;
}
if (((void**)&_cmsContextPoolHeadMutex)[0] == NULL)
InitializeCriticalSection(&_cmsContextPoolHeadMutex);
if (*mutex == NULL || !ReleaseMutex(*mutex))
{
cmsSignalError(0, cmsERROR_INTERNAL, "Mutex unlock failed");
return FALSE;
}
already_initialized = TRUE;
}
#endif
#endif
#endif
return TRUE;
}
// Internal, get associated pointer, with guessing. Never returns NULL.
struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
{
struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;
struct _cmsContext_struct* ctx;
// On 0, use global settings
if (id == NULL)
return &globalContext;
InitContextMutex();
// Search
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
@ -825,8 +768,6 @@ void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
// identify which plug-in to unregister.
void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)
{
struct _cmsContext_struct* ctx = _cmsGetContext(ContextID);
_cmsRegisterMemHandlerPlugin(ContextID, NULL);
_cmsRegisterInterpPlugin(ContextID, NULL);
_cmsRegisterTagTypePlugin(ContextID, NULL);
@ -838,11 +779,6 @@ void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)
_cmsRegisterOptimizationPlugin(ContextID, NULL);
_cmsRegisterTransformPlugin(ContextID, NULL);
_cmsRegisterMutexPlugin(ContextID, NULL);
_cmsRegisterParallelizationPlugin(ContextID, NULL);
if (ctx->MemPool != NULL)
_cmsSubAllocDestroy(ctx->MemPool);
ctx->MemPool = NULL;
}
@ -877,7 +813,31 @@ cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
struct _cmsContext_struct* ctx;
struct _cmsContext_struct fakeContext;
if (!InitContextMutex()) return NULL;
// See the comments regarding locking in lcms2_internal.h
// for an explanation of why we need the following code.
#ifndef CMS_NO_PTHREADS
#ifdef CMS_IS_WINDOWS_
#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
{
static HANDLE _cmsWindowsInitMutex = NULL;
static volatile HANDLE* mutex = &_cmsWindowsInitMutex;
if (*mutex == NULL)
{
HANDLE p = CreateMutex(NULL, FALSE, NULL);
if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL)
CloseHandle(p);
}
if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)
return NULL;
if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL)
InitializeCriticalSection(&_cmsContextPoolHeadMutex);
if (*mutex == NULL || !ReleaseMutex(*mutex))
return NULL;
}
#endif
#endif
#endif
_cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
@ -926,7 +886,6 @@ cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
_cmsAllocOptimizationPluginChunk(ctx, NULL);
_cmsAllocTransformPluginChunk(ctx, NULL);
_cmsAllocMutexPluginChunk(ctx, NULL);
_cmsAllocParallelizationPluginChunk(ctx, NULL);
// Setup the plug-ins
if (!cmsPluginTHR(ctx, Plugin)) {
@ -954,8 +913,6 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
if (ctx == NULL)
return NULL; // Something very wrong happened
if (!InitContextMutex()) return NULL;
// Setup default memory allocators
memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
@ -990,7 +947,6 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
_cmsAllocOptimizationPluginChunk(ctx, src);
_cmsAllocTransformPluginChunk(ctx, src);
_cmsAllocMutexPluginChunk(ctx, src);
_cmsAllocParallelizationPluginChunk(ctx, src);
// Make sure no one failed
for (i=Logger; i < MemoryClientMax; i++) {
@ -1016,9 +972,6 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
struct _cmsContext_struct fakeContext;
struct _cmsContext_struct* prev;
InitContextMutex();
memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
@ -1065,32 +1018,3 @@ void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID)
}
// Use context mutex to provide thread-safe time
cmsBool _cmsGetTime(struct tm* ptr_time)
{
struct tm* t;
#if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME_S)
struct tm tm;
#endif
time_t now = time(NULL);
#ifdef HAVE_GMTIME_R
t = gmtime_r(&now, &tm);
#elif defined(HAVE_GMTIME_S)
t = gmtime_s(&tm, &now) == 0 ? &tm : NULL;
#else
if (!InitContextMutex()) return FALSE;
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
t = gmtime(&now);
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
#endif
if (t == NULL)
return FALSE;
else {
*ptr_time = *t;
return TRUE;
}
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -504,7 +504,7 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
_cmsIOPrintf(m, "/lcms2gammatable [");
for (i=0; i < Table->nEntries; i++) {
if (i % 10 == 0)
if (i % 10 == 0)
_cmsIOPrintf(m, "\n ");
_cmsIOPrintf(m, "%d ", Table->Table16[i]);
}
@ -583,7 +583,7 @@ void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[], const cha
}
else {
snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, (int) i);
buffer[sizeof(buffer)-1] = '\0';
buffer[sizeof(buffer)-1] = '\0';
Emit1Gamma(m, g[i], buffer);
}
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -155,7 +155,6 @@ cmsBool BlackPointAsDarkerColorant(cmsHPROFILE hInput,
// Force it to be neutral, clip to max. L* of 50
Lab.a = Lab.b = 0;
if (Lab.L > 50) Lab.L = 50;
if (Lab.L < 0) Lab.L = 0;
// Free the resources
cmsDeleteTransform(xform);
@ -352,7 +351,6 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[]
if (fabs(a) < 1.0E-10) {
if (fabs(b) < 1.0E-10) return 0;
return cmsmin(0, cmsmax(50, -c/b ));
}
else {
@ -363,11 +361,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[]
}
else {
double rt;
if (fabs(a) < 1.0E-10) return 0;
rt = (-b + sqrt(d)) / (2.0 * a);
double rt = (-b + sqrt(d)) / (2.0 * a);
return cmsmax(0, cmsmin(50, rt));
}

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -163,62 +163,15 @@ cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t*
return TRUE;
}
// Try to promote correctly to wchar_t when 32 bits
cmsINLINE cmsBool is_surrogate(cmsUInt32Number uc) { return (uc - 0xd800u) < 2048u; }
cmsINLINE cmsBool is_high_surrogate(cmsUInt32Number uc) { return (uc & 0xfffffc00) == 0xd800; }
cmsINLINE cmsBool is_low_surrogate(cmsUInt32Number uc) { return (uc & 0xfffffc00) == 0xdc00; }
cmsINLINE cmsUInt32Number surrogate_to_utf32(cmsUInt32Number high, cmsUInt32Number low)
{
return (high << 10) + low - 0x35fdc00;
}
cmsINLINE cmsBool convert_utf16_to_utf32(cmsIOHANDLER* io, cmsInt32Number n, wchar_t* output)
{
cmsUInt16Number uc;
while (n > 0)
{
if (!_cmsReadUInt16Number(io, &uc)) return FALSE;
n--;
if (!is_surrogate(uc))
{
*output++ = (wchar_t)uc;
}
else {
cmsUInt16Number low;
if (!_cmsReadUInt16Number(io, &low)) return FALSE;
n--;
if (is_high_surrogate(uc) && is_low_surrogate(low))
*output++ = (wchar_t)surrogate_to_utf32(uc, low);
else
return FALSE; // Corrupted string, just ignore
}
}
return TRUE;
}
// Auxiliary to read an array of wchar_t
static
cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
{
cmsUInt32Number i;
cmsUInt16Number tmp;
cmsBool is32 = sizeof(wchar_t) > sizeof(cmsUInt16Number);
_cmsAssert(io != NULL);
if (is32 && Array != NULL)
{
return convert_utf16_to_utf32(io, n, Array);
}
for (i=0; i < n; i++) {
if (Array != NULL) {
@ -1383,7 +1336,7 @@ void Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr)
//
// All the dateTimeNumber values in a profile shall be in Coordinated Universal Time
// (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local
// time to UTC when setting these values. Programs that display these values may show
// time to UTC when setting these values. Programmes that display these values may show
// the dateTimeNumber as UTC, show the equivalent local time (at current locale), or
// display both UTC and local versions of the dateTimeNumber.
@ -1579,10 +1532,7 @@ void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU
Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);
if (Block == NULL) goto Error;
NumOfWchar = SizeOfTag / sizeof(wchar_t);
if (!_cmsReadWCharArray(io, NumOfWchar, Block)) {
_cmsFree(self->ContextID, Block);
goto Error;
}
if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error;
}
mlu ->MemPool = Block;
@ -1825,7 +1775,7 @@ cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
// That will create a MPE LUT with Matrix, pre tables, CLUT and post tables.
// 8 bit lut may be scaled easily to v4 PCS, but we need also to properly adjust
// 8 bit lut may be scaled easely to v4 PCS, but we need also to properly adjust
// PCS on BToAxx tags and AtoB if abstract. We need to fix input direction.
static
@ -1932,7 +1882,7 @@ Error:
static
cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
cmsUInt32Number j, nTabSize, i;
cmsUInt32Number j, nTabSize, i, n;
cmsUInt8Number val;
cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
cmsStage* mpe;
@ -1967,34 +1917,28 @@ cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
// That should be all
if (mpe != NULL) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
return FALSE;
}
if (clut == NULL)
clutPoints = 0;
else {
// Lut8 only allows same CLUT points in all dimensions
clutPoints = clut->Params->nSamples[0];
for (i = 1; i < cmsPipelineInputChannels(NewLUT); i++) {
if (clut->Params->nSamples[i] != clutPoints) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT with different samples per dimension not suitable to be saved as LUT16");
return FALSE;
}
}
}
else
clutPoints = clut->Params->nSamples[0];
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number)cmsPipelineInputChannels(NewLUT))) return FALSE;
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number)cmsPipelineOutputChannels(NewLUT))) return FALSE;
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE;
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE;
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
n = NewLUT->InputChannels * NewLUT->OutputChannels;
if (MatMPE != NULL) {
for (i = 0; i < 9; i++)
{
if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
}
for (i = 0; i < 9; i++)
{
if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
}
}
else {
@ -2112,9 +2056,9 @@ cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCu
_cmsAssert(Tables != NULL);
for (i=0; i < Tables ->nCurves; i++) {
nEntries = Tables->TheCurves[0]->nEntries;
nEntries = Tables->TheCurves[i]->nEntries;
for (i=0; i < Tables ->nCurves; i++) {
for (j=0; j < nEntries; j++) {
@ -2258,7 +2202,7 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
// That should be all
if (mpe != NULL) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
return FALSE;
}
@ -2267,16 +2211,8 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
if (clut == NULL)
clutPoints = 0;
else {
// Lut16 only allows same CLUT points in all dimensions
clutPoints = clut->Params->nSamples[0];
for (i = 1; i < InputChannels; i++) {
if (clut->Params->nSamples[i] != clutPoints) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT with different samples per dimension not suitable to be saved as LUT16");
return FALSE;
}
}
}
else
clutPoints = clut->Params->nSamples[0];
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE;
if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE;
@ -2285,10 +2221,10 @@ cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
if (MatMPE != NULL) {
for (i = 0; i < 9; i++)
{
if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
}
for (i = 0; i < 9; i++)
{
if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
}
}
else {
@ -2634,31 +2570,31 @@ Error:
static
cmsBool WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
{
cmsUInt32Number i, n;
cmsUInt32Number i, n;
_cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
n = mpe->InputChannels * mpe->OutputChannels;
n = mpe->InputChannels * mpe->OutputChannels;
// Write the Matrix
for (i = 0; i < n; i++)
{
if (!_cmsWrite15Fixed16Number(io, m->Double[i])) return FALSE;
}
if (m->Offset != NULL) {
for (i = 0; i < mpe->OutputChannels; i++)
// Write the Matrix
for (i = 0; i < n; i++)
{
if (!_cmsWrite15Fixed16Number(io, m->Offset[i])) return FALSE;
if (!_cmsWrite15Fixed16Number(io, m->Double[i])) return FALSE;
}
}
else {
for (i = 0; i < mpe->OutputChannels; i++)
{
if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
if (m->Offset != NULL) {
for (i = 0; i < mpe->OutputChannels; i++)
{
if (!_cmsWrite15Fixed16Number(io, m->Offset[i])) return FALSE;
}
}
else {
for (i = 0; i < mpe->OutputChannels; i++)
{
if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
}
}
}
return TRUE;
@ -3189,6 +3125,7 @@ void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
static
void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
cmsUInt32Number vendorFlag; // Bottom 16 bits for ICC use
cmsUInt32Number count; // Count of named colors
cmsUInt32Number nDeviceCoords; // Num of device coordinates
@ -3260,8 +3197,8 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER
if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
memcpy(prefix, (const char*) NamedColorList->Prefix, sizeof(prefix));
memcpy(suffix, (const char*) NamedColorList->Suffix, sizeof(suffix));
strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
suffix[32] = prefix[32] = 0;
@ -3274,10 +3211,6 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER
cmsUInt16Number Colorant[cmsMAXCHANNELS];
char Root[cmsMAX_PATH];
memset(Root, 0, sizeof(Root));
memset(PCS, 0, sizeof(PCS));
memset(Colorant, 0, sizeof(Colorant));
if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
Root[32] = 0;
if (!io ->Write(io, 32 , Root)) return FALSE;
@ -3518,6 +3451,7 @@ void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHAN
// Get table count
if (!_cmsReadUInt32Number(io, &Count)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
// Allocate an empty structure
OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
@ -3535,7 +3469,6 @@ void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHAN
*nItems = 1;
return OutSeq;
cmsUNUSED_PARAMETER(SizeOfTag);
}
@ -3611,68 +3544,47 @@ void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
{
cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
cmsUInt32Number CountUcr, CountBg;
cmsInt32Number SignedSizeOfTag = (cmsInt32Number)SizeOfTag;
char* ASCIIString;
*nItems = 0;
if (n == NULL) return NULL;
// First curve is Under color removal
if (SignedSizeOfTag < (cmsInt32Number) sizeof(cmsUInt32Number)) return NULL;
if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL;
SignedSizeOfTag -= sizeof(cmsUInt32Number);
if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL);
if (n ->Ucr == NULL) goto error;
if (n ->Ucr == NULL) return NULL;
if (SignedSizeOfTag < (cmsInt32Number)(CountUcr * sizeof(cmsUInt16Number))) goto error;
if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) goto error;
SignedSizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL;
if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
SizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
// Second curve is Black generation
if (SignedSizeOfTag < (cmsInt32Number)sizeof(cmsUInt32Number)) goto error;
if (!_cmsReadUInt32Number(io, &CountBg)) goto error;
SignedSizeOfTag -= sizeof(cmsUInt32Number);
if (!_cmsReadUInt32Number(io, &CountBg)) return NULL;
if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL);
if (n ->Bg == NULL) goto error;
if (SignedSizeOfTag < (cmsInt32Number) (CountBg * sizeof(cmsUInt16Number))) goto error;
if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) goto error;
SignedSizeOfTag -= CountBg * sizeof(cmsUInt16Number);
if (SignedSizeOfTag < 0 || SignedSizeOfTag > 32000) goto error;
if (n ->Bg == NULL) return NULL;
if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL;
if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL;
SizeOfTag -= CountBg * sizeof(cmsUInt16Number);
if (SizeOfTag == UINT_MAX) return NULL;
// Now comes the text. The length is specified by the tag size
n ->Desc = cmsMLUalloc(self ->ContextID, 1);
if (n ->Desc == NULL) goto error;
if (n ->Desc == NULL) return NULL;
ASCIIString = (char*) _cmsMalloc(self ->ContextID, SignedSizeOfTag + 1);
if (io->Read(io, ASCIIString, sizeof(char), SignedSizeOfTag) != (cmsUInt32Number)SignedSizeOfTag)
{
_cmsFree(self->ContextID, ASCIIString);
goto error;
}
ASCIIString[SignedSizeOfTag] = 0;
ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
ASCIIString[SizeOfTag] = 0;
cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
_cmsFree(self ->ContextID, ASCIIString);
*nItems = 1;
return (void*) n;
error:
if (n->Ucr) cmsFreeToneCurve(n->Ucr);
if (n->Bg) cmsFreeToneCurve(n->Bg);
if (n->Desc) cmsMLUfree(n->Desc);
_cmsFree(self->ContextID, n);
*nItems = 0;
return NULL;
}
static
@ -3753,7 +3665,7 @@ country varies for each element:
// Auxiliary, read an string specified as count + string
static
cmsBool ReadCountAndString(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
cmsBool ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
{
cmsUInt32Number Count;
char* Text;
@ -3783,7 +3695,7 @@ cmsBool ReadCountAndString(struct _cms_typehandler_struct* self, cmsIOHANDLER*
}
static
cmsBool WriteCountAndString(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section)
cmsBool WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section)
{
cmsUInt32Number TextSize;
char* Text;
@ -3807,11 +3719,11 @@ void *Type_CrdInfo_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
cmsMLU* mlu = cmsMLUalloc(self ->ContextID, 5);
*nItems = 0;
if (!ReadCountAndString(self, io, mlu, &SizeOfTag, "nm")) goto Error;
if (!ReadCountAndString(self, io, mlu, &SizeOfTag, "#0")) goto Error;
if (!ReadCountAndString(self, io, mlu, &SizeOfTag, "#1")) goto Error;
if (!ReadCountAndString(self, io, mlu, &SizeOfTag, "#2")) goto Error;
if (!ReadCountAndString(self, io, mlu, &SizeOfTag, "#3")) goto Error;
if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "nm")) goto Error;
if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#0")) goto Error;
if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#1")) goto Error;
if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#2")) goto Error;
if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#3")) goto Error;
*nItems = 1;
return (void*) mlu;
@ -3828,11 +3740,11 @@ cmsBool Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER*
cmsMLU* mlu = (cmsMLU*) Ptr;
if (!WriteCountAndString(self, io, mlu, "nm")) goto Error;
if (!WriteCountAndString(self, io, mlu, "#0")) goto Error;
if (!WriteCountAndString(self, io, mlu, "#1")) goto Error;
if (!WriteCountAndString(self, io, mlu, "#2")) goto Error;
if (!WriteCountAndString(self, io, mlu, "#3")) goto Error;
if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error;
if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error;
if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error;
if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error;
if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error;
return TRUE;
@ -4086,44 +3998,41 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND
switch (ElementSig) {
case cmsSigFormulaCurveSeg: {
case cmsSigFormulaCurveSeg: {
cmsUInt16Number Type;
cmsUInt32Number ParamsByType[] = { 4, 5, 5 };
cmsUInt16Number Type;
cmsUInt32Number ParamsByType[] = {4, 5, 5 };
if (!_cmsReadUInt16Number(io, &Type)) goto Error;
if (!_cmsReadUInt16Number(io, NULL)) goto Error;
if (!_cmsReadUInt16Number(io, &Type)) goto Error;
if (!_cmsReadUInt16Number(io, NULL)) goto Error;
Segments[i].Type = Type + 6;
if (Type > 2) goto Error;
Segments[i].Type = Type + 6;
if (Type > 2) goto Error;
for (j = 0; j < ParamsByType[Type]; j++) {
for (j=0; j < ParamsByType[Type]; j++) {
cmsFloat32Number f;
if (!_cmsReadFloat32Number(io, &f)) goto Error;
Segments[i].Params[j] = f;
}
}
break;
cmsFloat32Number f;
if (!_cmsReadFloat32Number(io, &f)) goto Error;
Segments[i].Params[j] = f;
}
}
break;
case cmsSigSampledCurveSeg: {
cmsUInt32Number Count;
case cmsSigSampledCurveSeg: {
cmsUInt32Number Count;
if (!_cmsReadUInt32Number(io, &Count)) goto Error;
if (!_cmsReadUInt32Number(io, &Count)) goto Error;
// The first point is implicit in the last stage, we allocate an extra note to be populated latter on
Count++;
Segments[i].nGridPoints = Count;
Segments[i].SampledPoints = (cmsFloat32Number*)_cmsCalloc(self->ContextID, Count, sizeof(cmsFloat32Number));
if (Segments[i].SampledPoints == NULL) goto Error;
Segments[i].nGridPoints = Count;
Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number));
if (Segments[i].SampledPoints == NULL) goto Error;
Segments[i].SampledPoints[0] = 0;
for (j = 1; j < Count; j++) {
if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error;
}
}
break;
for (j=0; j < Count; j++) {
if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error;
}
}
break;
default:
{
@ -4143,17 +4052,6 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND
if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints);
}
_cmsFree(self ->ContextID, Segments);
// Explore for missing implicit points
for (i = 0; i < nSegments; i++) {
// If sampled curve, fix it
if (Curve->Segments[i].Type == 0) {
Curve->Segments[i].SampledPoints[0] = cmsEvalToneCurveFloat(Curve, Curve->Segments[i].x0);
}
}
return Curve;
Error:
@ -4248,12 +4146,12 @@ cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g)
if (ActualSeg -> Type == 0) {
// This is a sampled curve. First point is implicit in the ICC format, but not in our representation
// This is a sampled curve
if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigSampledCurveSeg)) goto Error;
if (!_cmsWriteUInt32Number(io, 0)) goto Error;
if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints - 1)) goto Error;
if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints)) goto Error;
for (j=1; j < g ->Segments[i].nGridPoints; j++) {
for (j=0; j < g ->Segments[i].nGridPoints; j++) {
if (!_cmsWriteFloat32Number(io, ActualSeg -> SampledPoints[j])) goto Error;
}
@ -4630,7 +4528,7 @@ Error:
// This one is a little bit more complex, so we don't use position tables this time.
// This one is a liitle bit more complex, so we don't use position tables this time.
static
cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
@ -5062,7 +4960,7 @@ cmsBool ReadOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsUIn
if (!_cmsReadUInt32Number(io, &e->Offsets[i])) return FALSE;
if (!_cmsReadUInt32Number(io, &e ->Sizes[i])) return FALSE;
// An offset of zero has special meaning and shall be preserved
// An offset of zero has special meaning and shal be preserved
if (e ->Offsets[i] > 0)
e ->Offsets[i] += BaseOffset;
return TRUE;
@ -5070,41 +4968,27 @@ cmsBool ReadOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsUIn
static
cmsBool ReadOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a,
cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset,
cmsInt32Number* SignedSizeOfTagPtr)
cmsBool ReadOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset)
{
cmsUInt32Number i;
cmsInt32Number SignedSizeOfTag = *SignedSizeOfTagPtr;
// Read column arrays
for (i=0; i < Count; i++) {
if (SignedSizeOfTag < 4 * (cmsInt32Number) sizeof(cmsUInt32Number)) return FALSE;
SignedSizeOfTag -= 4 * sizeof(cmsUInt32Number);
if (!ReadOneElem(io, &a -> Name, i, BaseOffset)) return FALSE;
if (!ReadOneElem(io, &a -> Value, i, BaseOffset)) return FALSE;
if (Length > 16) {
if (SignedSizeOfTag < 2 * (cmsInt32Number) sizeof(cmsUInt32Number)) return FALSE;
SignedSizeOfTag -= 2 * sizeof(cmsUInt32Number);
if (!ReadOneElem(io, &a ->DisplayName, i, BaseOffset)) return FALSE;
}
if (Length > 24) {
if (SignedSizeOfTag < 2 * (cmsInt32Number) sizeof(cmsUInt32Number)) return FALSE;
SignedSizeOfTag -= 2 * (cmsInt32Number) sizeof(cmsUInt32Number);
if (!ReadOneElem(io, & a -> DisplayValue, i, BaseOffset)) return FALSE;
}
}
*SignedSizeOfTagPtr = SignedSizeOfTag;
return TRUE;
}
@ -5252,31 +5136,26 @@ cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _c
static
void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
cmsHANDLE hDict = NULL;
cmsHANDLE hDict;
cmsUInt32Number i, Count, Length;
cmsUInt32Number BaseOffset;
_cmsDICarray a;
wchar_t *NameWCS = NULL, *ValueWCS = NULL;
cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL;
cmsBool rc;
cmsInt32Number SignedSizeOfTag = (cmsInt32Number)SizeOfTag;
*nItems = 0;
memset(&a, 0, sizeof(a));
// Get actual position as a basis for element offsets
BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
// Get name-value record count
SignedSizeOfTag -= sizeof(cmsUInt32Number);
if (SignedSizeOfTag < 0) goto Error;
if (!_cmsReadUInt32Number(io, &Count)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
// Get rec length
SignedSizeOfTag -= sizeof(cmsUInt32Number);
if (SignedSizeOfTag < 0) goto Error;
if (!_cmsReadUInt32Number(io, &Length)) return NULL;
SizeOfTag -= sizeof(cmsUInt32Number);
// Check for valid lengths
if (Length != 16 && Length != 24 && Length != 32) {
@ -5292,7 +5171,7 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
if (!AllocArray(self -> ContextID, &a, Count, Length)) goto Error;
// Read column arrays
if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset, &SignedSizeOfTag)) goto Error;
if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset)) goto Error;
// Seek to each element and read it
for (i=0; i < Count; i++) {
@ -5332,7 +5211,7 @@ void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
Error:
FreeArray(&a);
if (hDict != NULL) cmsDictFree(hDict);
cmsDictFree(hDict);
return NULL;
}
@ -5430,64 +5309,6 @@ void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr)
cmsUNUSED_PARAMETER(self);
}
// cicp VideoSignalType
static
void* Type_VideoSignal_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
cmsVideoSignalType* cicp = NULL;
if (SizeOfTag != 8) return NULL;
if (!_cmsReadUInt32Number(io, NULL)) return NULL;
cicp = (cmsVideoSignalType*)_cmsCalloc(self->ContextID, 1, sizeof(cmsVideoSignalType));
if (cicp == NULL) return NULL;
if (!_cmsReadUInt8Number(io, &cicp->ColourPrimaries)) goto Error;
if (!_cmsReadUInt8Number(io, &cicp->TransferCharacteristics)) goto Error;
if (!_cmsReadUInt8Number(io, &cicp->MatrixCoefficients)) goto Error;
if (!_cmsReadUInt8Number(io, &cicp->VideoFullRangeFlag)) goto Error;
// Success
*nItems = 1;
return cicp;
Error:
if (cicp != NULL) _cmsFree(self->ContextID, cicp);
return NULL;
}
static
cmsBool Type_VideoSignal_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
cmsVideoSignalType* cicp = (cmsVideoSignalType*)Ptr;
if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
if (!_cmsWriteUInt8Number(io, cicp->ColourPrimaries)) return FALSE;
if (!_cmsWriteUInt8Number(io, cicp->TransferCharacteristics)) return FALSE;
if (!_cmsWriteUInt8Number(io, cicp->MatrixCoefficients)) return FALSE;
if (!_cmsWriteUInt8Number(io, cicp->VideoFullRangeFlag)) return FALSE;
return TRUE;
cmsUNUSED_PARAMETER(self);
cmsUNUSED_PARAMETER(nItems);
}
void* Type_VideoSignal_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
{
return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsVideoSignalType));
cmsUNUSED_PARAMETER(n);
}
static
void Type_VideoSignal_Free(struct _cms_typehandler_struct* self, void* Ptr)
{
_cmsFree(self->ContextID, Ptr);
}
// ********************************************************************************
// Type support main routines
@ -5527,7 +5348,6 @@ static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
{TYPE_HANDLER(cmsMonacoBrokenCurveType, Curve), (_cmsTagTypeLinkedList*) &SupportedTagTypes[28] },
{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 }
};
@ -5722,8 +5542,6 @@ static _cmsTagLinkedList SupportedTags[] = {
{ cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]},
{ cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]},
{ cmsSigcicpTag, { 1, 1, { cmsSigcicpType}, NULL }, &SupportedTags[64]},
{ cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, NULL}
};

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -143,7 +143,7 @@ cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
if (!hICC) // can't allocate
return NULL;
cmsSetProfileVersion(hICC, 4.4);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigDisplayClass);
cmsSetColorSpace(hICC, cmsSigRgbData);
@ -264,7 +264,7 @@ cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID,
if (!hICC) // can't allocate
return NULL;
cmsSetProfileVersion(hICC, 4.4);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigDisplayClass);
cmsSetColorSpace(hICC, cmsSigGrayData);
@ -320,13 +320,13 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
{
cmsHPROFILE hICC;
cmsPipeline* Pipeline;
cmsInt32Number nChannels;
cmsUInt32Number nChannels;
hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC)
return NULL;
cmsSetProfileVersion(hICC, 4.4);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigLinkClass);
cmsSetColorSpace(hICC, ColorSpace);
@ -335,7 +335,7 @@ cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
cmsSetHeaderRenderingIntent(hICC, INTENT_PERCEPTUAL);
// Set up channels
nChannels = cmsChannelsOfColorSpace(ColorSpace);
nChannels = cmsChannelsOf(ColorSpace);
// Creates a Pipeline with prelinearization step only
Pipeline = cmsPipelineAlloc(ContextID, nChannels, nChannels);
@ -397,7 +397,7 @@ int InkLimitingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUI
InkLimit = (InkLimit * 655.35);
SumCMY = (cmsFloat64Number) In[0] + In[1] + In[2];
SumCMY = In[0] + In[1] + In[2];
SumCMYK = SumCMY + In[3];
if (SumCMYK > InkLimit) {
@ -426,7 +426,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
cmsHPROFILE hICC;
cmsPipeline* LUT;
cmsStage* CLUT;
cmsInt32Number nChannels;
cmsUInt32Number nChannels;
if (ColorSpace != cmsSigCmykData) {
cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
@ -445,7 +445,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
if (!hICC) // can't allocate
return NULL;
cmsSetProfileVersion(hICC, 4.4);
cmsSetProfileVersion(hICC, 4.3);
cmsSetDeviceClass(hICC, cmsSigLinkClass);
cmsSetColorSpace(hICC, ColorSpace);
@ -555,7 +555,7 @@ cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIE
hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetProfileVersion(hProfile, 4.4);
cmsSetProfileVersion(hProfile, 4.3);
cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
cmsSetColorSpace(hProfile, cmsSigLabData);
@ -601,7 +601,7 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID)
hProfile = cmsCreateRGBProfileTHR(ContextID, cmsD50_xyY(), NULL, NULL);
if (hProfile == NULL) return NULL;
cmsSetProfileVersion(hProfile, 4.4);
cmsSetProfileVersion(hProfile, 4.3);
cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
cmsSetColorSpace(hProfile, cmsSigXYZData);
@ -868,7 +868,7 @@ cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
if (!hProfile) // can't allocate
return NULL;
cmsSetProfileVersion(hProfile, 4.4);
cmsSetProfileVersion(hProfile, 4.3);
if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error;
@ -1003,7 +1003,7 @@ cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
// Make sure we have proper formatters
cmsChangeBuffersFormat(xform, TYPE_NAMED_COLOR_INDEX,
FLOAT_SH(0) | COLORSPACE_SH(_cmsLCMScolorSpace(v ->ExitColorSpace))
| BYTES_SH(2) | CHANNELS_SH(cmsChannelsOfColorSpace(v ->ExitColorSpace)));
| BYTES_SH(2) | CHANNELS_SH(cmsChannelsOf(v ->ExitColorSpace)));
// Apply the transfor to colorants.
for (i=0; i < nColors; i++) {
@ -1091,9 +1091,8 @@ 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, ChansIn, ChansOut;
int ColorSpaceBitsIn, ColorSpaceBitsOut;
_cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
cmsPipeline* LUT = NULL;
cmsStage* mpe;
@ -1144,8 +1143,8 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
// Optimize the LUT and precalculate a devicelink
ChansIn = cmsChannelsOfColorSpace(xform -> EntryColorSpace);
ChansOut = cmsChannelsOfColorSpace(xform -> ExitColorSpace);
ChansIn = cmsChannelsOf(xform -> EntryColorSpace);
ChansOut = cmsChannelsOf(xform -> ExitColorSpace);
ColorSpaceBitsIn = _cmsLCMScolorSpace(xform -> EntryColorSpace);
ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace);

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -293,16 +293,16 @@ cmsBool _cmsAdaptMatrixToD50(cmsMAT3* r, const cmsCIExyY* SourceWhitePt)
// Build a White point, primary chromas transfer matrix from RGB to CIE XYZ
// This is just an approximation, I am not handling all the non-linear
// aspects of the RGB to XYZ process, and assuming that the gamma correction
// aspects of the RGB to XYZ process, and assumming that the gamma correction
// has transitive property in the transformation chain.
//
// the algorithm:
// the alghoritm:
//
// - First I build the absolute conversion matrix using
// primaries in XYZ. This matrix is next inverted
// - Then I eval the source white point across this matrix
// obtaining the coefficients of the transformation
// - Then, I apply these coefficients to the original matrix
// obtaining the coeficients of the transformation
// - Then, I apply these coeficients to the original matrix
//
cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePt, const cmsCIExyYTRIPLE* Primrs)
{

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -313,7 +313,7 @@ void FloatXFORM(_cmsTRANSFORM* p,
accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn);
// Any gamut check to do?
// Any gamut chack to do?
if (p->GamutCheck != NULL) {
// Evaluate gamut marker.
@ -810,73 +810,6 @@ cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMM
return CMMcargo->dwOriginalFlags;
}
// Returns the worker callback for parallelization plug-ins
_cmsTransform2Fn CMSEXPORT _cmsGetTransformWorker(struct _cmstransform_struct* CMMcargo)
{
_cmsAssert(CMMcargo != NULL);
return CMMcargo->Worker;
}
// This field holds maximum number of workers or -1 to auto
cmsInt32Number CMSEXPORT _cmsGetTransformMaxWorkers(struct _cmstransform_struct* CMMcargo)
{
_cmsAssert(CMMcargo != NULL);
return CMMcargo->MaxWorkers;
}
// This field is actually unused and reserved
cmsUInt32Number CMSEXPORT _cmsGetTransformWorkerFlags(struct _cmstransform_struct* CMMcargo)
{
_cmsAssert(CMMcargo != NULL);
return CMMcargo->WorkerFlags;
}
// In the case there is a parallelization plug-in, let it to do its job
static
void ParalellizeIfSuitable(_cmsTRANSFORM* p)
{
_cmsParallelizationPluginChunkType* ctx = (_cmsParallelizationPluginChunkType*)_cmsContextGetClientChunk(p->ContextID, ParallelizationPlugin);
_cmsAssert(p != NULL);
if (ctx != NULL && ctx->SchedulerFn != NULL) {
p->Worker = p->xform;
p->xform = ctx->SchedulerFn;
p->MaxWorkers = ctx->MaxWorkers;
p->WorkerFlags = ctx->WorkerFlags;
}
}
/**
* An empty unroll to avoid a check with NULL on cmsDoTransform()
*/
static
cmsUInt8Number* UnrollNothing(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wIn[],
CMSREGISTER cmsUInt8Number* accum,
CMSREGISTER cmsUInt32Number Stride)
{
return accum;
cmsUNUSED_PARAMETER(info);
cmsUNUSED_PARAMETER(wIn);
cmsUNUSED_PARAMETER(Stride);
}
static
cmsUInt8Number* PackNothing(CMSREGISTER _cmsTRANSFORM* info,
CMSREGISTER cmsUInt16Number wOut[],
CMSREGISTER cmsUInt8Number* output,
CMSREGISTER cmsUInt32Number Stride)
{
return output;
cmsUNUSED_PARAMETER(info);
cmsUNUSED_PARAMETER(wOut);
cmsUNUSED_PARAMETER(Stride);
}
// Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper
// for separated transforms. If this is the case,
static
@ -932,7 +865,6 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
p->xform = _cmsTransform2toTransformAdaptor;
}
ParalellizeIfSuitable(p);
return p;
}
}
@ -943,7 +875,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;
@ -969,10 +901,8 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
}
else {
// Formats are intended to be changed before use
if (*InputFormat == 0 && *OutputFormat == 0) {
p->FromInput = UnrollNothing;
p->ToOutput = PackNothing;
p ->FromInput = p ->ToOutput = NULL;
*dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
}
else {
@ -989,7 +919,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
return NULL;
}
BytesPerPixelInput = T_BYTES(*InputFormat);
BytesPerPixelInput = T_BYTES(p ->InputFormat);
if (BytesPerPixelInput == 0 || BytesPerPixelInput >= 2)
*dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
@ -1023,7 +953,6 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
p ->dwOriginalFlags = *dwFlags;
p ->ContextID = ContextID;
p ->UserData = NULL;
ParalellizeIfSuitable(p);
return p;
}
@ -1181,15 +1110,6 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
return NULL;
}
// Check whatever the transform is 16 bits and involves linear RGB in first profile. If so, disable optimizations
if (EntryColorSpace == cmsSigRgbData && T_BYTES(InputFormat) == 2 && !(dwFlags & cmsFLAGS_NOOPTIMIZE))
{
cmsFloat64Number gamma = cmsDetectRGBProfileGamma(hProfiles[0], 0.1);
if (gamma > 0 && gamma < 1.6)
dwFlags |= cmsFLAGS_NOOPTIMIZE;
}
// Create a pipeline with all transformations
Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
if (Lut == NULL) {
@ -1198,8 +1118,8 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
}
// Check channel count
if ((cmsChannelsOfColorSpace(EntryColorSpace) != (cmsInt32Number) cmsPipelineInputChannels(Lut)) ||
(cmsChannelsOfColorSpace(ExitColorSpace) != (cmsInt32Number) cmsPipelineOutputChannels(Lut))) {
if ((cmsChannelsOf(EntryColorSpace) != cmsPipelineInputChannels(Lut)) ||
(cmsChannelsOf(ExitColorSpace) != cmsPipelineOutputChannels(Lut))) {
cmsPipelineFree(Lut);
cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Channel count doesn't match. Profile is corrupted");
return NULL;

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2021 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"),
@ -52,7 +52,7 @@
//
//---------------------------------------------------------------------------------
//
// Version 2.14
// Version 2.12
//
#ifndef _lcms2_H
@ -110,7 +110,7 @@ extern "C" {
#endif
// Version/release
#define LCMS_VERSION 2140
#define LCMS_VERSION 2120
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@ -181,7 +181,7 @@ typedef double cmsFloat64Number;
#endif
// Handle "register" keyword
#if defined(CMS_NO_REGISTER_KEYWORD)
#if defined(CMS_NO_REGISTER_KEYWORD) && !defined(CMS_DLL) && !defined(CMS_DLL_BUILD)
# define CMSREGISTER
#else
# define CMSREGISTER register
@ -319,7 +319,6 @@ typedef int cmsBool;
// Base ICC type definitions
typedef enum {
cmsSigChromaticityType = 0x6368726D, // 'chrm'
cmsSigcicpType = 0x63696370, // 'cicp'
cmsSigColorantOrderType = 0x636C726F, // 'clro'
cmsSigColorantTableType = 0x636C7274, // 'clrt'
cmsSigCrdInfoType = 0x63726469, // 'crdi'
@ -431,7 +430,6 @@ typedef enum {
cmsSigViewingConditionsTag = 0x76696577, // 'view'
cmsSigVcgtTag = 0x76636774, // 'vcgt'
cmsSigMetaTag = 0x6D657461, // 'meta'
cmsSigcicpTag = 0x63696370, // 'cicp'
cmsSigArgyllArtsTag = 0x61727473 // 'arts'
} cmsTagSignature;
@ -697,10 +695,9 @@ typedef void* cmsHTRANSFORM;
// Format of pixel is defined by one cmsUInt32Number, using bit fields as follows
//
// 2 1 0
// 4 3 2 10987 6 5 4 3 2 1 098 7654 321
// M A O TTTTT U Y F P X S EEE CCCC BBB
// 3 2 10987 6 5 4 3 2 1 098 7654 321
// A O TTTTT U Y F P X S EEE CCCC BBB
//
// M: Premultiplied alpha (only works when extra samples is 1)
// A: Floating point -- With this flag we can differentiate 16 bits as float and as int
// O: Optimized -- previous optimization already returns the final 8-bit value
// T: Pixeltype
@ -713,7 +710,6 @@ typedef void* cmsHTRANSFORM;
// B: bytes per sample
// Y: Swap first - changes ABGR to BGRA and KCMY to CMYK
#define PREMUL_SH(m) ((m) << 23)
#define FLOAT_SH(a) ((a) << 22)
#define OPTIMIZED_SH(s) ((s) << 21)
#define COLORSPACE_SH(s) ((s) << 16)
@ -727,7 +723,6 @@ typedef void* cmsHTRANSFORM;
#define BYTES_SH(b) (b)
// These macros unpack format specifiers into integers
#define T_PREMUL(m) (((m)>>23)&1)
#define T_FLOAT(a) (((a)>>22)&1)
#define T_OPTIMIZED(o) (((o)>>21)&1)
#define T_COLORSPACE(s) (((s)>>16)&31)
@ -756,6 +751,7 @@ typedef void* cmsHTRANSFORM;
#define PT_HSV 12
#define PT_HLS 13
#define PT_Yxy 14
#define PT_MCH1 15
#define PT_MCH2 16
#define PT_MCH3 17
@ -771,6 +767,7 @@ typedef void* cmsHTRANSFORM;
#define PT_MCH13 27
#define PT_MCH14 28
#define PT_MCH15 29
#define PT_LabV2 30 // Identical to PT_Lab, but using the V2 old encoding
// Some (not all!) representations
@ -784,9 +781,7 @@ typedef void* cmsHTRANSFORM;
#define TYPE_GRAY_16_REV (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1))
#define TYPE_GRAY_16_SE (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1))
#define TYPE_GRAYA_8 (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1))
#define TYPE_GRAYA_8_PREMUL (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1)|PREMUL_SH(1))
#define TYPE_GRAYA_16 (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2))
#define TYPE_GRAYA_16_PREMUL (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|PREMUL_SH(1))
#define TYPE_GRAYA_16_SE (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1))
#define TYPE_GRAYA_8_PLANAR (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1)|PLANAR_SH(1))
#define TYPE_GRAYA_16_PLANAR (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|PLANAR_SH(1))
@ -803,32 +798,24 @@ typedef void* cmsHTRANSFORM;
#define TYPE_BGR_16_SE (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
#define TYPE_RGBA_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1))
#define TYPE_RGBA_8_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|PREMUL_SH(1))
#define TYPE_RGBA_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
#define TYPE_RGBA_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
#define TYPE_RGBA_16_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|PREMUL_SH(1))
#define TYPE_RGBA_16_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
#define TYPE_RGBA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
#define TYPE_ARGB_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1))
#define TYPE_ARGB_8_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1)|PREMUL_SH(1))
#define TYPE_ARGB_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1)|PLANAR_SH(1))
#define TYPE_ARGB_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1))
#define TYPE_ARGB_16_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1)|PREMUL_SH(1))
#define TYPE_ABGR_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1))
#define TYPE_ABGR_8_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PREMUL_SH(1))
#define TYPE_ABGR_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PLANAR_SH(1))
#define TYPE_ABGR_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
#define TYPE_ABGR_16_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PREMUL_SH(1))
#define TYPE_ABGR_16_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1))
#define TYPE_ABGR_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
#define TYPE_BGRA_8 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_BGRA_8_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|PREMUL_SH(1))
#define TYPE_BGRA_8_PLANAR (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|PLANAR_SH(1))
#define TYPE_BGRA_16 (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_BGRA_16_PREMUL (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|PREMUL_SH(1))
#define TYPE_BGRA_16_SE (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_CMY_8 (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1))
@ -945,7 +932,7 @@ typedef void* cmsHTRANSFORM;
#define TYPE_HSV_16_PLANAR (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
#define TYPE_HSV_16_SE (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
// Named color index. Only 16 bits is allowed (don't check colorspace)
// Named color index. Only 16 bits allowed (don't check colorspace)
#define TYPE_NAMED_COLOR_INDEX (CHANNELS_SH(1)|BYTES_SH(2))
// Float formatters.
@ -953,19 +940,13 @@ typedef void* cmsHTRANSFORM;
#define TYPE_Lab_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_LabA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_GRAY_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(4))
#define TYPE_GRAYA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(4)|EXTRA_SH(1))
#define TYPE_GRAYA_FLT_PREMUL (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(4)|EXTRA_SH(1)|PREMUL_SH(1))
#define TYPE_RGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_RGBA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4))
#define TYPE_RGBA_FLT_PREMUL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|PREMUL_SH(1))
#define TYPE_ARGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|SWAPFIRST_SH(1))
#define TYPE_ARGB_FLT_PREMUL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|SWAPFIRST_SH(1)|PREMUL_SH(1))
#define TYPE_BGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_BGRA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_BGRA_FLT_PREMUL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|PREMUL_SH(1))
#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_ABGR_FLT_PREMUL (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|PREMUL_SH(1))
#define TYPE_CMYK_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(4))
@ -1069,16 +1050,6 @@ typedef struct {
} cmsICCViewingConditions;
typedef struct {
cmsUInt8Number ColourPrimaries; // Recommendation ITU-T H.273
cmsUInt8Number TransferCharacteristics; // (ISO/IEC 23091-2)
cmsUInt8Number MatrixCoefficients;
cmsUInt8Number VideoFullRangeFlag;
} cmsVideoSignalType;
// Get LittleCMS version (for shared objects) -----------------------------------------------------------------------------
CMSAPI int CMSEXPORT cmsGetEncodedCMMversion(void);
@ -1314,7 +1285,6 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsStageInputChannels(const cmsStage* mpe);
CMSAPI cmsUInt32Number CMSEXPORT cmsStageOutputChannels(const cmsStage* mpe);
CMSAPI cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe);
CMSAPI void* CMSEXPORT cmsStageData(const cmsStage* mpe);
CMSAPI cmsContext CMSEXPORT cmsGetStageContextID(const cmsStage* mpe);
// Sampling
typedef cmsInt32Number (* cmsSAMPLER16) (CMSREGISTER const cmsUInt16Number In[],
@ -1561,12 +1531,8 @@ CMSAPI cmsBool CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Numb
CMSAPI cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation);
CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace);
// Deprecated, use cmsChannelsOfColorSpace instead
CMSAPI cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace);
// Get number of channels of color space or -1 if color space is not listed/supported
CMSAPI cmsInt32Number CMSEXPORT cmsChannelsOfColorSpace(cmsColorSpaceSignature ColorSpace);
// Build a suitable formatter for the colorspace of this profile. nBytes=1 means 8 bits, nBytes=2 means 16 bits.
CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
@ -1969,8 +1935,6 @@ CMSAPI cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* Blac
// Estimate total area coverage
CMSAPI cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile);
// Estimate gamma space, always positive. Returns -1 on error.
CMSAPI cmsFloat64Number CMSEXPORT cmsDetectRGBProfileGamma(cmsHPROFILE hProfile, cmsFloat64Number threshold);
// Poor man's gamut mapping
CMSAPI cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,

@ -30,7 +30,7 @@
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -312,38 +312,38 @@ typedef CRITICAL_SECTION _cmsMutex;
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{
EnterCriticalSection(m);
return 0;
EnterCriticalSection(m);
return 0;
}
cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
{
LeaveCriticalSection(m);
return 0;
LeaveCriticalSection(m);
return 0;
}
cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
{
InitializeCriticalSection(m);
return 0;
InitializeCriticalSection(m);
return 0;
}
cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
{
DeleteCriticalSection(m);
return 0;
DeleteCriticalSection(m);
return 0;
}
cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
{
EnterCriticalSection(m);
return 0;
EnterCriticalSection(m);
return 0;
}
cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
{
LeaveCriticalSection(m);
return 0;
LeaveCriticalSection(m);
return 0;
}
#else
@ -357,32 +357,32 @@ typedef pthread_mutex_t _cmsMutex;
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{
return pthread_mutex_lock(m);
return pthread_mutex_lock(m);
}
cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
{
return pthread_mutex_unlock(m);
return pthread_mutex_unlock(m);
}
cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
{
return pthread_mutex_init(m, NULL);
return pthread_mutex_init(m, NULL);
}
cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
{
return pthread_mutex_destroy(m);
return pthread_mutex_destroy(m);
}
cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
{
return pthread_mutex_lock(m);
return pthread_mutex_lock(m);
}
cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
{
return pthread_mutex_unlock(m);
return pthread_mutex_unlock(m);
}
#endif
@ -395,37 +395,37 @@ typedef int _cmsMutex;
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{
cmsUNUSED_PARAMETER(m);
return 0;
return 0;
}
cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
{
cmsUNUSED_PARAMETER(m);
return 0;
return 0;
}
cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
{
cmsUNUSED_PARAMETER(m);
return 0;
return 0;
}
cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
{
cmsUNUSED_PARAMETER(m);
return 0;
return 0;
}
cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
{
cmsUNUSED_PARAMETER(m);
return 0;
return 0;
}
cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
{
cmsUNUSED_PARAMETER(m);
return 0;
return 0;
}
#endif
@ -467,9 +467,6 @@ cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin
// Mutex
cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Paralellization
cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// ---------------------------------------------------------------------------------------------------------
// Suballocators.
@ -517,7 +514,6 @@ typedef enum {
OptimizationPlugin,
TransformPlugin,
MutexPlugin,
ParallelizationPlugin,
// Last in list
MemoryClientMax
@ -753,24 +749,6 @@ extern _cmsMutexPluginChunkType _cmsMutexPluginChunk;
void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src);
// Container for parallelization plug-in
typedef struct {
cmsInt32Number MaxWorkers; // Number of workers to do as maximum
cmsInt32Number WorkerFlags; // reserved
_cmsTransform2Fn SchedulerFn; // callback to setup functions
} _cmsParallelizationPluginChunkType;
// The global Context0 storage for parallelization plug-in
extern _cmsParallelizationPluginChunkType _cmsParallelizationPluginChunk;
// Allocate parallelization container.
void _cmsAllocParallelizationPluginChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src);
// ----------------------------------------------------------------------------------
// MLU internal representation
typedef struct {
@ -1132,11 +1110,6 @@ typedef struct _cmstransform_struct {
// A way to provide backwards compatibility with full xform plugins
_cmsTransformFn OldXform;
// A one-worker transform entry for parallelization
_cmsTransform2Fn Worker;
cmsInt32Number MaxWorkers;
cmsUInt32Number WorkerFlags;
} _cmsTRANSFORM;
// Copies extra channels from input to output if the original flags in the transform structure
@ -1174,8 +1147,5 @@ cmsBool _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsC
cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePoint, const cmsCIExyYTRIPLE* Primaries);
// thread-safe gettime
cmsBool _cmsGetTime(struct tm* ptr_time);
#define _lcms_internal_H
#endif

@ -30,7 +30,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2022 Marti Maria Saguer
// Copyright (c) 1998-2020 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"),
@ -53,7 +53,7 @@
//---------------------------------------------------------------------------------
//
// This is the plug-in header file. Normal LittleCMS clients should not use it.
// It is provided for plug-in writers that may want to access the support
// It is provided for plug-in writters that may want to access the support
// functions to do low level operations. All plug-in related structures
// are defined here. Including this file forces to include the standard API too.
@ -238,7 +238,6 @@ typedef void* (* _cmsDupUserDataFn)(cmsContext ContextID, const void* Data);
#define cmsPluginOptimizationSig 0x6F707448 // 'optH'
#define cmsPluginTransformSig 0x7A666D48 // 'xfmH'
#define cmsPluginMutexSig 0x6D747A48 // 'mtxH'
#define cmsPluginParalellizationSig 0x70726C48 // 'prlH
typedef struct _cmsPluginBaseStruct {
@ -626,7 +625,7 @@ typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo, //
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number Size,
cmsUInt32Number Stride); // Stride in bytes to the next plane in planar formats
cmsUInt32Number Stride); // Stride in bytes to the next plana in planar formats
typedef void (*_cmsTransform2Fn)(struct _cmstransform_struct *CMMcargo,
@ -699,25 +698,6 @@ CMSAPI void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx);
CMSAPI cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx);
CMSAPI void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx);
//----------------------------------------------------------------------------------------------------------
// Parallelization
CMSAPI _cmsTransform2Fn CMSEXPORT _cmsGetTransformWorker(struct _cmstransform_struct* CMMcargo);
CMSAPI cmsInt32Number CMSEXPORT _cmsGetTransformMaxWorkers(struct _cmstransform_struct* CMMcargo);
CMSAPI cmsUInt32Number CMSEXPORT _cmsGetTransformWorkerFlags(struct _cmstransform_struct* CMMcargo);
// Let's plug-in to guess the best number of workers
#define CMS_GUESS_MAX_WORKERS -1
typedef struct {
cmsPluginBase base;
cmsInt32Number MaxWorkers; // Number of starts to do as maximum
cmsUInt32Number WorkerFlags; // Reserved
_cmsTransform2Fn SchedulerFn; // callback to setup functions
} cmsPluginParalellization;
#ifndef CMS_USE_CPP_API
# ifdef __cplusplus