diff options
| author | Matthieu Darbois <mayeut@users.noreply.github.com> | 2016-04-30 17:58:04 +0200 |
|---|---|---|
| committer | Matthieu Darbois <mayeut@users.noreply.github.com> | 2016-04-30 17:58:04 +0200 |
| commit | 9a20f8e8d1a91bd032e81ac53bf9a48dbb92bc29 (patch) | |
| tree | d5387a97517acf7e8f5880a9f44bda772a0022dd /thirdparty/liblcms2/src | |
| parent | 72deb588cbc8d5f56f8b0db3a2d120913e792cb8 (diff) | |
Update lcms (#544)
Update to mm2/Little-CMS@0e8234e090d6aab33f90e2eb0296f30aa0705e57
Diffstat (limited to 'thirdparty/liblcms2/src')
27 files changed, 1523 insertions, 920 deletions
diff --git a/thirdparty/liblcms2/src/cmsalpha.c b/thirdparty/liblcms2/src/cmsalpha.c new file mode 100644 index 00000000..904ce715 --- /dev/null +++ b/thirdparty/liblcms2/src/cmsalpha.c @@ -0,0 +1,481 @@ +//--------------------------------------------------------------------------------- +// +// Little Color Management System +// Copyright (c) 1998-2016 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: +// +// 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. +// +//--------------------------------------------------------------------------------- +// + +#include "lcms2_internal.h" + + +// Alpha copy ------------------------------------------------------------------------------------------------------------------ + +// Floor to byte, taking care of saturation +cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d) +{ + d += 0.5; + if (d <= 0) return 0; + if (d >= 255.0) return 255; + + return (cmsUInt8Number) _cmsQuickFloorWord(d); +} + + +// Return the size in bytes of a given formatter +static +int trueBytesSize(cmsUInt32Number Format) +{ + int fmt_bytes = T_BYTES(Format); + + // For double, the T_BYTES field returns zero + if (fmt_bytes == 0) + return sizeof(double); + + // Otherwise, it is already correct for all formats + return fmt_bytes; +} + + +// Several format converters + +typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src); + + +// From 8 + +static +void copy8(void* dst, const void* src) +{ + memmove(dst, src, 1); +} + +static +void from8to16(void* dst, const void* src) +{ + cmsUInt8Number n = *(cmsUInt8Number*)src; + *(cmsUInt16Number*) dst = FROM_8_TO_16(n); +} + +static +void from8toFLT(void* dst, const void* src) +{ + *(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f; +} + +static +void from8toDBL(void* dst, const void* src) +{ + *(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0; +} + +static +void from8toHLF(void* dst, const void* src) +{ + cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + +// From 16 + +static +void from16to8(void* dst, const void* src) +{ + cmsUInt16Number n = *(cmsUInt16Number*)src; + *(cmsUInt8Number*) dst = FROM_16_TO_8(n); +} + +static +void copy16(void* dst, const void* src) +{ + memmove(dst, src, 2); +} + +void from16toFLT(void* dst, const void* src) +{ + *(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; +} + +void from16toDBL(void* dst, const void* src) +{ + *(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f; +} + +static +void from16toHLF(void* dst, const void* src) +{ + cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + +// From Float + +static +void fromFLTto8(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); +} + +static +void fromFLTto16(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +} + +static +void copy32(void* dst, const void* src) +{ + memmove(dst, src, sizeof(cmsFloat32Number)); +} + +static +void fromFLTtoDBL(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsFloat64Number*)dst = (cmsFloat64Number)n; +} + +static +void fromFLTtoHLF(void* dst, const void* src) +{ + cmsFloat32Number n = *(cmsFloat32Number*)src; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + + +// From HALF + +static +void fromHLFto8(void* dst, const void* src) +{ + cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); + *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f); +} + +static +void fromHLFto16(void* dst, const void* src) +{ + cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src); + *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +} + +static +void fromHLFtoFLT(void* dst, const void* src) +{ + *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src); +} + +static +void fromHLFtoDBL(void* dst, const void* src) +{ + *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src); +} + +// From double +static +void fromDBLto8(void* dst, const void* src) +{ + cmsFloat64Number n = *(cmsFloat64Number*)src; + *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0); +} + +static +void fromDBLto16(void* dst, const void* src) +{ + cmsFloat64Number n = *(cmsFloat64Number*)src; + *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f); +} + +static +void fromDBLtoFLT(void* dst, const void* src) +{ + cmsFloat64Number n = *(cmsFloat64Number*)src; + *(cmsFloat32Number*)dst = (cmsFloat32Number) n; +} + +static +void fromDBLtoHLF(void* dst, const void* src) +{ + cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src; + *(cmsUInt16Number*)dst = _cmsFloat2Half(n); +} + +static +void copy64(void* dst, const void* src) +{ + memmove(dst, src, sizeof(cmsFloat64Number)); +} + + +// Returns the position (x or y) of the formatter in the table of functions +static +int FormatterPos(cmsUInt32Number frm) +{ + int b = T_BYTES(frm); + + if (b == 0 && T_FLOAT(frm)) + return 4; // DBL + if (b == 2 && T_FLOAT(frm)) + return 2; // HLF + if (b == 4 && T_FLOAT(frm)) + return 3; // FLT + if (b == 2 && !T_FLOAT(frm)) + return 1; // 16 + if (b == 1 && !T_FLOAT(frm)) + return 0; // 8 + + return -1; // not recognized + +} + +// Obtains a alpha-to-alpha funmction formatter +static +cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out) +{ +static cmsFormatterAlphaFn FormattersAlpha[5][5] = { + + /* from 8 */ { copy8, from8to16, from8toHLF, from8toFLT, from8toDBL }, + /* from 16*/ { from16to8, copy16, from16toHLF, from16toFLT, from16toDBL }, + /* from HLF*/ { fromHLFto8, fromHLFto16, copy16, fromHLFtoFLT, fromHLFtoDBL }, + /* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTtoHLF, copy32, fromFLTtoDBL }, + /* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLtoHLF, fromDBLtoFLT, copy64 }}; + + int in_n = FormatterPos(in); + int out_n = FormatterPos(out); + + if (in_n < 0 || out_n < 0 || in_n > 4 || out_n > 4) { + + cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width"); + return NULL; + } + + return FormattersAlpha[in_n][out_n]; +} + + + +// This function computes the distance from each component to the next one in bytes. +static +void ComputeIncrementsForChunky(cmsUInt32Number Format, + cmsUInt32Number ComponentStartingOrder[], + cmsUInt32Number ComponentPointerIncrements[]) +{ + cmsUInt32Number channels[cmsMAXCHANNELS]; + int extra = T_EXTRA(Format); + int nchannels = T_CHANNELS(Format); + int total_chans = nchannels + extra; + int i; + int channelSize = trueBytesSize(Format); + int pixelSize = channelSize * total_chans; + + // Sanity check + if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) + return; + + memset(channels, 0, sizeof(channels)); + + // Separation is independent of starting point and only depends on channel size + for (i = 0; i < extra; i++) + ComponentPointerIncrements[i] = pixelSize; + + // Handle do swap + for (i = 0; i < total_chans; i++) + { + if (T_DOSWAP(Format)) { + channels[i] = total_chans - i - 1; + } + else { + channels[i] = i; + } + } + + // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 + if (T_SWAPFIRST(Format) && total_chans > 1) { + + cmsUInt32Number tmp = channels[0]; + for (i = 0; i < total_chans-1; i++) + channels[i] = channels[i + 1]; + + channels[total_chans - 1] = tmp; + } + + // Handle size + if (channelSize > 1) + for (i = 0; i < total_chans; i++) { + channels[i] *= channelSize; + } + + for (i = 0; i < extra; i++) + ComponentStartingOrder[i] = channels[i + nchannels]; +} + + + +// On planar configurations, the distance is the stride added to any non-negative +static +void ComputeIncrementsForPlanar(cmsUInt32Number Format, + cmsUInt32Number BytesPerPlane, + cmsUInt32Number ComponentStartingOrder[], + cmsUInt32Number ComponentPointerIncrements[]) +{ + cmsUInt32Number channels[cmsMAXCHANNELS]; + int extra = T_EXTRA(Format); + int nchannels = T_CHANNELS(Format); + int total_chans = nchannels + extra; + int i; + int channelSize = trueBytesSize(Format); + + // Sanity check + if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS) + return; + + memset(channels, 0, sizeof(channels)); + + // Separation is independent of starting point and only depends on channel size + for (i = 0; i < extra; i++) + ComponentPointerIncrements[i] = channelSize; + + // Handle do swap + for (i = 0; i < total_chans; i++) + { + if (T_DOSWAP(Format)) { + channels[i] = total_chans - i - 1; + } + else { + channels[i] = i; + } + } + + // Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012 + if (T_SWAPFIRST(Format) && total_chans > 0) { + + cmsUInt32Number tmp = channels[0]; + for (i = 0; i < total_chans - 1; i++) + channels[i] = channels[i + 1]; + + channels[total_chans - 1] = tmp; + } + + // Handle size + for (i = 0; i < total_chans; i++) { + channels[i] *= BytesPerPlane; + } + + for (i = 0; i < extra; i++) + ComponentStartingOrder[i] = channels[i + nchannels]; +} + + + +// Dispatcher por chunky and planar RGB +static +void ComputeComponentIncrements(cmsUInt32Number Format, + cmsUInt32Number BytesPerPlane, + cmsUInt32Number ComponentStartingOrder[], + cmsUInt32Number ComponentPointerIncrements[]) +{ + if (T_PLANAR(Format)) { + + ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements); + } + else { + ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements); + } + +} + + + +// Handles extra channels copying alpha if requested by the flags +void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + size_t i, j, k; + cmsUInt32Number nExtra; + cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS]; + cmsUInt32Number SourceIncrements[cmsMAXCHANNELS]; + cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS]; + cmsUInt32Number DestIncrements[cmsMAXCHANNELS]; + cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS]; + cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS]; + + cmsUInt8Number* SourcePtr[cmsMAXCHANNELS]; + cmsUInt8Number* DestPtr[cmsMAXCHANNELS]; + + cmsFormatterAlphaFn copyValueFn; + + // Make sure we need some copy + if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA)) + return; + + // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time. + nExtra = T_EXTRA(p->InputFormat); + if (nExtra != T_EXTRA(p->OutputFormat)) + return; + + // Anything to do? + if (nExtra == 0) + return; + + // Compute the increments + ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements); + ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements); + + // Check for conversions 8, 16, half, float, dbl + copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat); + + memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements)); + memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements)); + + // The loop itself + for (i = 0; i < LineCount; i++) { + + // Prepare pointers for the loop + for (j = 0; j < nExtra; j++) { + + SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j]; + DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j]; + } + + for (j = 0; j < PixelsPerLine; j++) { + + for (k = 0; k < nExtra; k++) { + + copyValueFn(DestPtr[k], SourcePtr[k]); + + SourcePtr[k] += SourceIncrements[k]; + DestPtr[k] += DestIncrements[k]; + } + } + + for (j = 0; j < nExtra; j++) { + + SourceStrideIncrements[j] += Stride->BytesPerLineIn; + DestStrideIncrements[j] += Stride->BytesPerLineOut; + } + } +} + diff --git a/thirdparty/liblcms2/src/cmscam02.c b/thirdparty/liblcms2/src/cmscam02.c index 9d874aa2..5f0ac1f8 100644 --- a/thirdparty/liblcms2/src/cmscam02.c +++ b/thirdparty/liblcms2/src/cmscam02.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), diff --git a/thirdparty/liblcms2/src/cmscgats.c b/thirdparty/liblcms2/src/cmscgats.c index 099b07bb..591e4caa 100644 --- a/thirdparty/liblcms2/src/cmscgats.c +++ b/thirdparty/liblcms2/src/cmscgats.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 Marti Maria Saguer // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the "Software"), @@ -48,7 +48,7 @@ // Symbols typedef enum { - SNONE, + SUNDEFINED, SINUM, // Integer SDNUM, // Real SIDENT, // Identifier @@ -324,7 +324,7 @@ static const char* PredefinedSampleID[] = { "XYZ_X", // X component of tristimulus data "XYZ_Y", // Y component of tristimulus data "XYZ_Z", // Z component of tristimulus data - "XYY_X" // x component of chromaticity data + "XYY_X", // x component of chromaticity data "XYY_Y", // y component of chromaticity data "XYY_CAPY", // Y component of tristimulus data "LAB_L", // L* component of Lab data @@ -521,7 +521,7 @@ SYMBOL BinSrchKey(const char *id) else l = x + 1; } - return SNONE; + return SUNDEFINED; } @@ -706,7 +706,7 @@ void InSymbol(cmsIT8* it8) key = BinSrchKey(it8->id); - if (key == SNONE) it8->sy = SIDENT; + if (key == SUNDEFINED) it8->sy = SIDENT; else it8->sy = key; } @@ -801,11 +801,11 @@ void InSymbol(cmsIT8* it8) if (it8 ->sy == SINUM) { - sprintf(it8->id, "%d", it8->inum); + snprintf(it8->id, 127, "%d", it8->inum); } else { - sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum); + snprintf(it8->id, 127, it8 ->DoubleFormatter, it8->dnum); } k = (int) strlen(it8 ->id); @@ -1297,7 +1297,7 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID) it8->ValidKeywords = NULL; it8->ValidSampleID = NULL; - it8 -> sy = SNONE; + it8 -> sy = SUNDEFINED; it8 -> ch = ' '; it8 -> Source = NULL; it8 -> inum = 0; @@ -1363,7 +1363,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFlo cmsIT8* it8 = (cmsIT8*) hIT8; char Buffer[1024]; - sprintf(Buffer, it8->DoubleFormatter, Val); + snprintf(Buffer, 1023, it8->DoubleFormatter, Val); return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL; } @@ -1373,7 +1373,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUIn cmsIT8* it8 = (cmsIT8*) hIT8; char Buffer[1024]; - sprintf(Buffer, "%u", Val); + snprintf(Buffer, 1023, "%u", Val); return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL; } @@ -2516,8 +2516,10 @@ int LocateSample(cmsIT8* it8, const char* cSample) for (i=0; i < t->nSamples; i++) { fld = GetDataFormat(it8, i); - if (cmsstrcasecmp(fld, cSample) == 0) - return i; + if (fld != NULL) { + if (cmsstrcasecmp(fld, cSample) == 0) + return i; + } } return -1; @@ -2575,7 +2577,7 @@ cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFl _cmsAssert(hIT8 != NULL); - sprintf(Buff, it8->DoubleFormatter, Val); + snprintf(Buff, 255, it8->DoubleFormatter, Val); return SetData(it8, row, col, Buff); } diff --git a/thirdparty/liblcms2/src/cmscnvrt.c b/thirdparty/liblcms2/src/cmscnvrt.c index 1a93e83f..42e5f78b 100644 --- a/thirdparty/liblcms2/src/cmscnvrt.c +++ b/thirdparty/liblcms2/src/cmscnvrt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -269,6 +269,9 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, { cmsMAT3 Scale, m1, m2, m3, m4; + // TODO: Follow Marc Mahy's recommendation to check if CHAD is same by using M1*M2 == M2*M1. If so, do nothing. + // TODO: Add support for ArgyllArts tag + // Adaptation state if (AdaptationState == 1.0) { @@ -288,7 +291,7 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState, if (AdaptationState == 0.0) { - + m1 = *ChromaticAdaptationMatrixOut; _cmsMAT3per(&m2, &m1, &Scale); // m2 holds CHAD from output white to D50 times abs. col. scaling @@ -530,7 +533,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, cmsHPROFILE hProfile; cmsMAT3 m; cmsVEC3 off; - cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace; + cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut = cmsSigLabData, CurrentColorSpace; cmsProfileClassSignature ClassSig; cmsUInt32Number i, Intent; @@ -632,6 +635,22 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID, CurrentColorSpace = ColorSpaceOut; } + // Check for non-negatives clip + if (dwFlags & cmsFLAGS_NONEGATIVES) { + + if (ColorSpaceOut == cmsSigGrayData || + ColorSpaceOut == cmsSigRgbData || + ColorSpaceOut == cmsSigCmykData) { + + cmsStage* clip = _cmsStageClipNegatives(Result->ContextID, cmsChannelsOf(ColorSpaceOut)); + if (clip == NULL) goto Error; + + if (!cmsPipelineInsertStage(Result, cmsAT_END, clip)) + goto Error; + } + + } + return Result; Error: @@ -1045,7 +1064,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID, if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) { // Force BPC for V4 profiles in perceptual and saturation - if (cmsGetProfileVersion(hProfiles[i]) >= 4.0) + if (cmsGetEncodedICCversion(hProfiles[i]) >= 0x4000000) BPC[i] = TRUE; } } diff --git a/thirdparty/liblcms2/src/cmserr.c b/thirdparty/liblcms2/src/cmserr.c index 29516db4..78a1f947 100644 --- a/thirdparty/liblcms2/src/cmserr.c +++ b/thirdparty/liblcms2/src/cmserr.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -25,6 +25,13 @@ #include "lcms2_internal.h" + +// This function is here to help applications to prevent mixing lcms versions on header and shared objects. +int CMSEXPORT cmsGetEncodedCMMversion(void) +{ + return LCMS_VERSION; +} + // I am so tired about incompatibilities on those functions that here are some replacements // that hopefully would be fully portable. diff --git a/thirdparty/liblcms2/src/cmsgmt.c b/thirdparty/liblcms2/src/cmsgmt.c index 09427650..51c2fefe 100644 --- a/thirdparty/liblcms2/src/cmsgmt.c +++ b/thirdparty/liblcms2/src/cmsgmt.c @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2012 Marti Maria Saguer
+// Copyright (c) 1998-2016 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"),
diff --git a/thirdparty/liblcms2/src/cmshalf.c b/thirdparty/liblcms2/src/cmshalf.c index 204dee96..cdd4e37b 100644 --- a/thirdparty/liblcms2/src/cmshalf.c +++ b/thirdparty/liblcms2/src/cmshalf.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), diff --git a/thirdparty/liblcms2/src/cmsintrp.c b/thirdparty/liblcms2/src/cmsintrp.c index 5d5f35d3..889b6981 100644 --- a/thirdparty/liblcms2/src/cmsintrp.c +++ b/thirdparty/liblcms2/src/cmsintrp.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -929,7 +929,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], Rest = c1 * rx + c2 * ry + c3 * rz; - Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); + Tmp1[OutChan] = (cmsUInt16Number) ( c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))); } @@ -993,7 +993,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[], Rest = c1 * rx + c2 * ry + c3 * rz; - Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)); + Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))); } diff --git a/thirdparty/liblcms2/src/cmsio0.c b/thirdparty/liblcms2/src/cmsio0.c index 4449acd4..2084c7c4 100644 --- a/thirdparty/liblcms2/src/cmsio0.c +++ b/thirdparty/liblcms2/src/cmsio0.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -453,6 +453,14 @@ cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io) // ------------------------------------------------------------------------------------------------------- +cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile) +{ + _cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile; + + if (Icc == NULL) return NULL; + return Icc->IOhandler; +} + // Creates an empty structure holding all required parameters cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID) { @@ -623,6 +631,32 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig) } + +// Enforces that the profile version is per. spec. +// Operates on the big endian bytes from the profile. +// Called before converting to platform endianness. +// Byte 0 is BCD major version, so max 9. +// Byte 1 is 2 BCD digits, one per nibble. +// Reserved bytes 2 & 3 must be 0. +static +cmsUInt32Number _validatedVersion(cmsUInt32Number DWord) +{ + cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord; + cmsUInt8Number temp1; + cmsUInt8Number temp2; + + if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09; + temp1 = *(pByte+1) & 0xf0; + temp2 = *(pByte+1) & 0x0f; + if (temp1 > 0x90) temp1 = 0x90; + if (temp2 > 0x09) temp2 = 0x09; + *(pByte+1) = (cmsUInt8Number)(temp1 | temp2); + *(pByte+2) = (cmsUInt8Number)0; + *(pByte+3) = (cmsUInt8Number)0; + + return DWord; +} + // Read profile header and validate it cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) { @@ -657,7 +691,7 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) Icc -> creator = _cmsAdjustEndianess32(Header.creator); _cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes); - Icc -> Version = _cmsAdjustEndianess32(Header.version); + Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version)); // Get size as reported in header HeaderSize = _cmsAdjustEndianess32(Header.size); @@ -773,7 +807,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) // Get true count for (i=0; i < Icc -> TagCount; i++) { - if (Icc ->TagNames[i] != 0) + if (Icc ->TagNames[i] != (cmsTagSignature) 0) Count++; } @@ -782,7 +816,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) for (i=0; i < Icc -> TagCount; i++) { - if (Icc ->TagNames[i] == 0) continue; // It is just a placeholder + if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // It is just a placeholder Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]); Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]); @@ -1132,7 +1166,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) for (i=0; i < Icc -> TagCount; i++) { - if (Icc ->TagNames[i] == 0) continue; + if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // Linked tags are not written if (Icc ->TagLinked[i] != (cmsTagSignature) 0) continue; @@ -1265,12 +1299,16 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH cmsContext ContextID; _cmsAssert(hProfile != NULL); - + + if (!_cmsLockMutex(Icc->ContextID, Icc->UsrMutex)) return 0; memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); ContextID = cmsGetProfileContextID(hProfile); PrevIO = Icc ->IOhandler = cmsOpenIOhandlerFromNULL(ContextID); - if (PrevIO == NULL) return 0; + if (PrevIO == NULL) { + _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); + return 0; + } // Pass #1 does compute offsets @@ -1290,7 +1328,10 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH } memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); - if (!cmsCloseIOhandler(PrevIO)) return 0; + if (!cmsCloseIOhandler(PrevIO)) + UsedSpace = 0; // As a error marker + + _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); return UsedSpace; @@ -1298,6 +1339,8 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH Error: cmsCloseIOhandler(PrevIO); memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); + _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); + return 0; } @@ -1794,7 +1837,7 @@ Error: // Similar to the anterior. This function allows to write directly to the ICC profile any data, without // checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading -// it as cooked without serializing does result into an error. If that is wha you want, you will need to dump +// it as cooked without serializing does result into an error. If that is what you want, you will need to dump // the profile to memry or disk and then reopen it. cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size) { @@ -1818,6 +1861,11 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons Icc ->TagSizes[i] = Size; _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); + + if (Icc->TagPtrs[i] == NULL) { + Icc->TagNames[i] = (cmsTagSignature) 0; + return FALSE; + } return TRUE; } diff --git a/thirdparty/liblcms2/src/cmsio1.c b/thirdparty/liblcms2/src/cmsio1.c index 89856e57..73ecbdc8 100644 --- a/thirdparty/liblcms2/src/cmsio1.c +++ b/thirdparty/liblcms2/src/cmsio1.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -310,8 +310,8 @@ Error: cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) { cmsTagTypeSignature OriginalType; - cmsTagSignature tag16 = Device2PCS16[Intent]; - cmsTagSignature tagFloat = Device2PCSFloat[Intent]; + cmsTagSignature tag16; + cmsTagSignature tagFloat; cmsContext ContextID = cmsGetProfileContextID(hProfile); // On named color, take the appropiate tag @@ -340,6 +340,9 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent) // matter other LUT are present and have precedence. Intent = -1 means just this. if (Intent != -1) { + tag16 = Device2PCS16[Intent]; + tagFloat = Device2PCSFloat[Intent]; + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence // Floating point LUT are always V4, but the encoding range is no @@ -582,13 +585,16 @@ Error: cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent) { cmsTagTypeSignature OriginalType; - cmsTagSignature tag16 = PCS2Device16[Intent]; - cmsTagSignature tagFloat = PCS2DeviceFloat[Intent]; - cmsContext ContextID = cmsGetProfileContextID(hProfile); + cmsTagSignature tag16; + cmsTagSignature tagFloat; + cmsContext ContextID = cmsGetProfileContextID(hProfile); if (Intent != -1) { + tag16 = PCS2Device16[Intent]; + tagFloat = PCS2DeviceFloat[Intent]; + if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence // Floating point LUT are always V4 @@ -906,7 +912,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq) { if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE; - if (cmsGetProfileVersion(hProfile) >= 4.0) { + if (cmsGetEncodedICCversion(hProfile) >= 0x4000000) { if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE; } diff --git a/thirdparty/liblcms2/src/cmslut.c b/thirdparty/liblcms2/src/cmslut.c index c491662b..df3dfc1a 100644 --- a/thirdparty/liblcms2/src/cmslut.c +++ b/thirdparty/liblcms2/src/cmslut.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -505,7 +505,7 @@ void* CLUTElemDup(cmsStage* mpe) goto Error; } else { NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number)); - if (NewElem ->Tab.TFloat == NULL) + if (NewElem ->Tab.T == NULL) goto Error; } } @@ -1125,7 +1125,23 @@ cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID) return mpe; } +// Clips values smaller than zero +static +void Clipper(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe) +{ + cmsUInt32Number i; + for (i = 0; i < mpe->InputChannels; i++) { + + cmsFloat32Number n = In[i]; + Out[i] = n < 0 ? 0 : n; + } +} +cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels) +{ + return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType, + nChannels, nChannels, Clipper, NULL, NULL, NULL); +} // ******************************************************************************** // Type cmsSigXYZ2LabElemType @@ -1437,7 +1453,8 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut) First = FALSE; } else { - Anterior ->Next = NewMPE; + if (Anterior != NULL) + Anterior ->Next = NewMPE; } Anterior = NewMPE; @@ -1482,7 +1499,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage for (pt = lut ->Elements; pt != NULL; pt = pt -> Next) Anterior = pt; - + Anterior ->Next = mpe; mpe ->Next = NULL; } diff --git a/thirdparty/liblcms2/src/cmsmd5.c b/thirdparty/liblcms2/src/cmsmd5.c index 966730cf..c7380ca8 100644 --- a/thirdparty/liblcms2/src/cmsmd5.c +++ b/thirdparty/liblcms2/src/cmsmd5.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), diff --git a/thirdparty/liblcms2/src/cmsmtrx.c b/thirdparty/liblcms2/src/cmsmtrx.c index 583b1ab2..1dbdc4c2 100644 --- a/thirdparty/liblcms2/src/cmsmtrx.c +++ b/thirdparty/liblcms2/src/cmsmtrx.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), diff --git a/thirdparty/liblcms2/src/cmsnamed.c b/thirdparty/liblcms2/src/cmsnamed.c index acfd1c8c..0da01d99 100644 --- a/thirdparty/liblcms2/src/cmsnamed.c +++ b/thirdparty/liblcms2/src/cmsnamed.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2012 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -92,7 +92,7 @@ cmsBool GrowMLUpool(cmsMLU* mlu) static cmsBool GrowMLUtable(cmsMLU* mlu) { - int AllocatedEntries; + cmsUInt32Number AllocatedEntries; _cmsMLUentry *NewPtr; // Sanity check @@ -118,7 +118,7 @@ cmsBool GrowMLUtable(cmsMLU* mlu) static int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode) { - int i; + cmsUInt32Number i; // Sanity check if (mlu == NULL) return -1; @@ -178,6 +178,33 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block, return TRUE; } +// Convert from a 3-char code to a cmsUInt16Number. It is done inthis way because some +// compilers don't properly align beginning of strings + +static +cmsUInt16Number strTo16(const char str[3]) +{ + cmsUInt16Number n = ((cmsUInt16Number) str[0] << 8) | str[1]; + + return n; // Always big endian in this case +} + +static +void strFrom16(char str[3], cmsUInt16Number n) +{ + // Assiming this would be aligned + union { + + cmsUInt16Number n; + char str[2]; + + } c; + + c.n = n; // Always big endian in this case + + str[0] = c.str[0]; str[1] = c.str[1]; str[2] = 0; + +} // Add an ASCII entry. cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString) @@ -185,8 +212,8 @@ cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1; wchar_t* WStr; cmsBool rc; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); if (mlu == NULL) return FALSE; @@ -220,8 +247,8 @@ cmsUInt32Number mywcslen(const wchar_t *s) // Add a wide entry cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString) { - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country); + cmsUInt16Number Lang = strTo16(Language); + cmsUInt16Number Cntry = strTo16(Country); cmsUInt32Number len; if (mlu == NULL) return FALSE; @@ -298,8 +325,8 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode, cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode) { - int i; - int Best = -1; + cmsUInt32Number i; + cmsInt32Number Best = -1; _cmsMLUentry* v; if (mlu == NULL) return NULL; @@ -350,8 +377,8 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu, cmsUInt32Number StrLen = 0; cmsUInt32Number ASCIIlen, i; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); // Sanitize if (mlu == NULL) return 0; @@ -394,8 +421,8 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu, const wchar_t *Wide; cmsUInt32Number StrLen = 0; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); // Sanitize if (mlu == NULL) return 0; @@ -427,8 +454,8 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, { const wchar_t *Wide; - cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode); - cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode); + cmsUInt16Number Lang = strTo16(LanguageCode); + cmsUInt16Number Cntry = strTo16(CountryCode); cmsUInt16Number ObtLang, ObtCode; // Sanitize @@ -438,10 +465,9 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu, if (Wide == NULL) return FALSE; // Get used language and code - *(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang); - *(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode); + strFrom16(ObtainedLanguage, ObtLang); + strFrom16(ObtainedCountry, ObtCode); - ObtainedLanguage[2] = ObtainedCountry[2] = 0; return TRUE; } @@ -464,12 +490,12 @@ cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu, if (mlu == NULL) return FALSE; - if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE; + if (idx >= mlu->UsedEntries) return FALSE; entry = &mlu->Entries[idx]; - *(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language); - *(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country); + strFrom16(LanguageCode, entry->Language); + strFrom16(CountryCode, entry->Country); return TRUE; } @@ -514,8 +540,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn v ->nColors = 0; v ->ContextID = ContextID; - while (v -> Allocated < n) - GrowNamedColorList(v); + while (v -> Allocated < n){ + if (!GrowNamedColorList(v)) return NULL; + } strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1); strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1); @@ -544,8 +571,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v) if (NewNC == NULL) return NULL; // For really large tables we need this - while (NewNC ->Allocated < v ->Allocated) - GrowNamedColorList(NewNC); + while (NewNC ->Allocated < v ->Allocated){ + if (!GrowNamedColorList(NewNC)) return NULL; + } memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix)); memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix)); diff --git a/thirdparty/liblcms2/src/cmsopt.c b/thirdparty/liblcms2/src/cmsopt.c index bf950917..2fba94b2 100644 --- a/thirdparty/liblcms2/src/cmsopt.c +++ b/thirdparty/liblcms2/src/cmsopt.c @@ -1,8 +1,7 @@ - //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 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,6 +162,89 @@ cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op return AnyOpt; } + +static +cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b) +{ + return fabs(b - a) < 0.00001f; +} + +static +cmsBool isFloatMatrixIdentity(const cmsMAT3* a) +{ + cmsMAT3 Identity; + int i, j; + + _cmsMAT3identity(&Identity); + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE; + + return TRUE; +} +// if two adjacent matrices are found, multiply them. +static +cmsBool _MultiplyMatrix(cmsPipeline* Lut) +{ + cmsStage** pt1; + cmsStage** pt2; + cmsStage* chain; + cmsBool AnyOpt = FALSE; + + pt1 = &Lut->Elements; + if (*pt1 == NULL) return AnyOpt; + + while (*pt1 != NULL) { + + pt2 = &((*pt1)->Next); + if (*pt2 == NULL) return AnyOpt; + + if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) { + + // Get both matrices + _cmsStageMatrixData* m1 = (_cmsStageMatrixData*) cmsStageData(*pt1); + _cmsStageMatrixData* m2 = (_cmsStageMatrixData*) cmsStageData(*pt2); + cmsMAT3 res; + + // Input offset and output offset should be zero to use this optimization + if (m1->Offset != NULL || m2 ->Offset != NULL || + cmsStageInputChannels(*pt1) != 3 || cmsStageOutputChannels(*pt1) != 3 || + cmsStageInputChannels(*pt2) != 3 || cmsStageOutputChannels(*pt2) != 3) + return FALSE; + + // Multiply both matrices to get the result + _cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double); + + // Get the next in chain afer the matrices + chain = (*pt2)->Next; + + // Remove both matrices + _RemoveElement(pt2); + _RemoveElement(pt1); + + // Now what if the result is a plain identity? + if (!isFloatMatrixIdentity(&res)) { + + // We can not get rid of full matrix + cmsStage* Multmat = cmsStageAllocMatrix(Lut->ContextID, 3, 3, (const cmsFloat64Number*) &res, NULL); + if (Multmat == NULL) return FALSE; // Should never happen + + // Recover the chain + Multmat->Next = chain; + *pt1 = Multmat; + } + + AnyOpt = TRUE; + } + else + pt1 = &((*pt1)->Next); + } + + return AnyOpt; +} + + // Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed // by a v4 to v2 and vice-versa. The elements are then discarded. static @@ -195,6 +277,9 @@ cmsBool PreOptimize(cmsPipeline* Lut) // Remove float pcs Lab conversions Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ); + // Simplify matrix. + Opt |= _MultiplyMatrix(Lut); + if (Opt) AnyOpt = TRUE; } while (Opt); @@ -251,12 +336,12 @@ static void* Prelin16dup(cmsContext ContextID, const void* ptr) { Prelin16Data* p16 = (Prelin16Data*) ptr; - Prelin16Data* Duped = _cmsDupMem(ContextID, p16, sizeof(Prelin16Data)); + Prelin16Data* Duped = (Prelin16Data*) _cmsDupMem(ContextID, p16, sizeof(Prelin16Data)); if (Duped == NULL) return NULL; - Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16)); - Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* )); + Duped->EvalCurveOut16 = (_cmsInterpFn16*) _cmsDupMem(ContextID, p16->EvalCurveOut16, p16->nOutputs * sizeof(_cmsInterpFn16)); + Duped->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16->ParamsCurveOut16, p16->nOutputs * sizeof(cmsInterpParams*)); return Duped; } @@ -269,7 +354,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID, int nOutputs, cmsToneCurve** Out ) { int i; - Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data)); + Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data)); if (p16 == NULL) return NULL; p16 ->nInputs = nInputs; @@ -590,7 +675,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 cmsStage* PreLin = cmsPipelineGetPtrToFirstStage(Src); // Check if suitable - if (PreLin ->Type == cmsSigCurveSetElemType) { + if (PreLin && PreLin ->Type == cmsSigCurveSetElemType) { // Maybe this is a linear tram, so we can avoid the whole stuff if (!AllCurvesAreLinear(PreLin)) { @@ -623,7 +708,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 cmsStage* PostLin = cmsPipelineGetPtrToLastStage(Src); // Check if suitable - if (cmsStageType(PostLin) == cmsSigCurveSetElemType) { + if (PostLin && cmsStageType(PostLin) == cmsSigCurveSetElemType) { // Maybe this is a linear tram, so we can avoid the whole stuff if (!AllCurvesAreLinear(PostLin)) { @@ -758,7 +843,7 @@ Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cms cmsS15Fixed16Number v1, v2, v3; Prelin8Data* p8; - p8 = _cmsMallocZero(ContextID, sizeof(Prelin8Data)); + p8 = (Prelin8Data*)_cmsMallocZero(ContextID, sizeof(Prelin8Data)); if (p8 == NULL) return NULL; // Since this only works for 8 bit input, values comes always as x * 257, @@ -832,7 +917,7 @@ void PrelinEval8(register const cmsUInt16Number Input[], Prelin8Data* p8 = (Prelin8Data*) D; register const cmsInterpParams* p = p8 ->p; int TotalOut = p -> nOutputs; - const cmsUInt16Number* LutTable = p -> Table; + const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table; r = Input[0] >> 8; g = Input[1] >> 8; @@ -925,8 +1010,8 @@ cmsBool IsDegenerated(const cmsToneCurve* g) } if (Zeros == 1 && Poles == 1) return FALSE; // For linear tables - if (Zeros > (nEntries / 4)) return TRUE; // Degenerated, mostly zeros - if (Poles > (nEntries / 4)) return TRUE; // Degenerated, mostly poles + if (Zeros > (nEntries / 20)) return TRUE; // Degenerated, many zeros + if (Poles > (nEntries / 20)) return TRUE; // Degenerated, many poles return FALSE; } @@ -948,17 +1033,19 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte cmsColorSpaceSignature ColorSpace, OutputColorSpace; cmsStage* OptimizedPrelinMpe; cmsStage* mpe; - cmsToneCurve** OptimizedPrelinCurves; - _cmsStageCLutData* OptimizedPrelinCLUT; + cmsToneCurve** OptimizedPrelinCurves; + _cmsStageCLutData* OptimizedPrelinCLUT; // This is a loosy optimization! does not apply in floating-point cases if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE; - // Only on RGB + // Only on chunky RGB if (T_COLORSPACE(*InputFormat) != PT_RGB) return FALSE; - if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE; + if (T_PLANAR(*InputFormat)) return FALSE; + if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE; + if (T_PLANAR(*OutputFormat)) return FALSE; // On 16 bits, user has to specify the feature if (!_cmsFormatterIs8bit(*InputFormat)) { @@ -982,6 +1069,22 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte memset(Trans, 0, sizeof(Trans)); memset(TransReverse, 0, sizeof(TransReverse)); + // If the last stage of the original lut are curves, and those curves are + // degenerated, it is likely the transform is squeezing and clipping + // the output from previous CLUT. We cannot optimize this case + { + cmsStage* last = cmsPipelineGetPtrToLastStage(OriginalLut); + + if (cmsStageType(last) == cmsSigCurveSetElemType) { + + _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*)cmsStageData(last); + for (i = 0; i < Data->nCurves; i++) { + if (IsDegenerated(Data->TheCurves[i])) + goto Error; + } + } + } + for (t = 0; t < OriginalLut ->InputChannels; t++) { Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL); if (Trans[t] == NULL) goto Error; @@ -1151,15 +1254,15 @@ void CurvesFree(cmsContext ContextID, void* ptr) static void* CurvesDup(cmsContext ContextID, const void* ptr) { - Curves16Data* Data = _cmsDupMem(ContextID, ptr, sizeof(Curves16Data)); + Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data)); int i; if (Data == NULL) return NULL; - Data ->Curves = _cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*)); + Data->Curves = (cmsUInt16Number**) _cmsDupMem(ContextID, Data->Curves, Data->nCurves * sizeof(cmsUInt16Number*)); for (i=0; i < Data -> nCurves; i++) { - Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number)); + Data->Curves[i] = (cmsUInt16Number*) _cmsDupMem(ContextID, Data->Curves[i], Data->nElements * sizeof(cmsUInt16Number)); } return (void*) Data; @@ -1172,18 +1275,18 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT int i, j; Curves16Data* c16; - c16 = _cmsMallocZero(ContextID, sizeof(Curves16Data)); + c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data)); if (c16 == NULL) return NULL; c16 ->nCurves = nCurves; c16 ->nElements = nElements; - c16 ->Curves = _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); + c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*)); if (c16 ->Curves == NULL) return NULL; for (i=0; i < nCurves; i++) { - c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); + c16->Curves[i] = (cmsUInt16Number*) _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number)); if (c16->Curves[i] == NULL) { @@ -1315,7 +1418,10 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI GammaTables[i] = NULL; } - if (GammaTables != NULL) _cmsFree(Src ->ContextID, GammaTables); + if (GammaTables != NULL) { + _cmsFree(Src->ContextID, GammaTables); + GammaTables = NULL; + } // Maybe the curves are linear at the end if (!AllCurvesAreLinear(ObtainedCurves)) { @@ -1531,49 +1637,83 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c } // 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast! -// TODO: Allow a third matrix for abs. colorimetric static cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags) { - cmsStage* Curve1, *Curve2; - cmsStage* Matrix1, *Matrix2; - _cmsStageMatrixData* Data1; - _cmsStageMatrixData* Data2; - cmsMAT3 res; - cmsBool IdentityMat; - cmsPipeline* Dest, *Src; + cmsStage* Curve1, *Curve2; + cmsStage* Matrix1, *Matrix2; + cmsMAT3 res; + cmsBool IdentityMat; + cmsPipeline* Dest, *Src; + cmsFloat64Number* Offset; - // Only works on RGB to RGB - if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE; + // Only works on RGB to RGB + if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE; - // Only works on 8 bit input - if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE; + // Only works on 8 bit input + if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE; - // Seems suitable, proceed - Src = *Lut; + // Seems suitable, proceed + Src = *Lut; - // Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for - if (!cmsPipelineCheckAndRetreiveStages(Src, 4, - cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, - &Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE; + // Check for: + // + // shaper-matrix-matrix-shaper + // shaper-matrix-shaper + // + // Both of those constructs are possible (first because abs. colorimetric). + // additionally, In the first case, the input matrix offset should be zero. - // Get both matrices - Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1); - Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2); + IdentityMat = FALSE; + if (cmsPipelineCheckAndRetreiveStages(Src, 4, + cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, + &Curve1, &Matrix1, &Matrix2, &Curve2)) { - // Input offset should be zero - if (Data1 ->Offset != NULL) return FALSE; + // Get both matrices + _cmsStageMatrixData* Data1 = (_cmsStageMatrixData*)cmsStageData(Matrix1); + _cmsStageMatrixData* Data2 = (_cmsStageMatrixData*)cmsStageData(Matrix2); - // Multiply both matrices to get the result - _cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double); + // Input offset should be zero + if (Data1->Offset != NULL) return FALSE; - // Now the result is in res + Data2 -> Offset. Maybe is a plain identity? - IdentityMat = FALSE; - if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) { + // Multiply both matrices to get the result + _cmsMAT3per(&res, (cmsMAT3*)Data2->Double, (cmsMAT3*)Data1->Double); - // We can get rid of full matrix - IdentityMat = TRUE; - } + // Only 2nd matrix has offset, or it is zero + Offset = Data2->Offset; + + // Now the result is in res + Data2 -> Offset. Maybe is a plain identity? + if (_cmsMAT3isIdentity(&res) && Offset == NULL) { + + // We can get rid of full matrix + IdentityMat = TRUE; + } + + } + else { + + if (cmsPipelineCheckAndRetreiveStages(Src, 3, + cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, + &Curve1, &Matrix1, &Curve2)) { + + _cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1); + + // Copy the matrix to our result + memcpy(&res, Data->Double, sizeof(res)); + + // Preserve the Odffset (may be NULL as a zero offset) + Offset = Data->Offset; + + if (_cmsMAT3isIdentity(&res) && Offset == NULL) { + + // We can get rid of full matrix + IdentityMat = TRUE; + } + } + else + return FALSE; // Not optimizeable this time + + } // Allocate an empty LUT Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels); @@ -1583,9 +1723,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1))) goto Error; - if (!IdentityMat) - if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset))) - goto Error; + if (!IdentityMat) { + + if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset))) + goto Error; + } + if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2))) goto Error; @@ -1603,7 +1746,7 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3 *dwFlags |= cmsFLAGS_NOCACHE; // Setup the optimizarion routines - SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat); + SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat); } cmsPipelineFree(Src); diff --git a/thirdparty/liblcms2/src/cmspack.c b/thirdparty/liblcms2/src/cmspack.c index c84fd822..12d6aae7 100644 --- a/thirdparty/liblcms2/src/cmspack.c +++ b/thirdparty/liblcms2/src/cmspack.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -2409,9 +2409,6 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, ((cmsFloat64Number*) output)[i + start] = v; } - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat64Number); - } if (Extra == 0 && SwapFirst) { @@ -2422,7 +2419,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info, if (T_PLANAR(info -> OutputFormat)) return output + sizeof(cmsFloat64Number); else - return output + nChan * sizeof(cmsFloat64Number); + return output + (nChan + Extra) * sizeof(cmsFloat64Number); } @@ -2433,50 +2430,47 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0; - cmsFloat64Number v = 0; - cmsFloat32Number* swap1 = (cmsFloat32Number*) output; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0; + cmsFloat64Number v = 0; + cmsFloat32Number* swap1 = (cmsFloat32Number*)output; + int i, start = 0; - if (ExtraFirst) - start = Extra; - - for (i=0; i < nChan; i++) { + if (ExtraFirst) + start = Extra; - int index = DoSwap ? (nChan - i - 1) : i; + for (i = 0; i < nChan; i++) { - v = (cmsFloat64Number) wOut[index] / maximum; + int index = DoSwap ? (nChan - i - 1) : i; - if (Reverse) - v = maximum - v; + v = (cmsFloat64Number)wOut[index] / maximum; - if (Planar) - ((cmsFloat32Number*) output)[(i + start ) * Stride]= (cmsFloat32Number) v; - else - ((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; - } + if (Reverse) + v = maximum - v; - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat32Number); - } + if (Planar) + ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v; + else + ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v; + } - if (Extra == 0 && SwapFirst) { + + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); - *swap1 = (cmsFloat32Number) v; - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number)); + *swap1 = (cmsFloat32Number)v; + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsFloat32Number); - else - return output + nChan * sizeof(cmsFloat32Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsFloat32Number); + else + return output + (nChan + Extra) * sizeof(cmsFloat32Number); } @@ -2489,50 +2483,47 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; - cmsFloat32Number* swap1 = (cmsFloat32Number*) output; - cmsFloat64Number v = 0; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; + cmsFloat32Number* swap1 = (cmsFloat32Number*)output; + cmsFloat64Number v = 0; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = wOut[index] * maximum; + v = wOut[index] * maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsFloat32Number*) output)[(i + start)* Stride]= (cmsFloat32Number) v; - else - ((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v; - } + if (Planar) + ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v; + else + ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v; + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat32Number); - } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number)); - *swap1 = (cmsFloat32Number) v; - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number)); + *swap1 = (cmsFloat32Number)v; + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsFloat32Number); - else - return output + nChan * sizeof(cmsFloat32Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsFloat32Number); + else + return output + (nChan + Extra) * sizeof(cmsFloat32Number); } static @@ -2541,51 +2532,47 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0; - cmsFloat64Number v = 0; - cmsFloat64Number* swap1 = (cmsFloat64Number*) output; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0; + cmsFloat64Number v = 0; + cmsFloat64Number* swap1 = (cmsFloat64Number*)output; + int i, start = 0; - if (ExtraFirst) - start = Extra; - - for (i=0; i < nChan; i++) { + if (ExtraFirst) + start = Extra; - int index = DoSwap ? (nChan - i - 1) : i; + for (i = 0; i < nChan; i++) { - v = wOut[index] * maximum; + int index = DoSwap ? (nChan - i - 1) : i; - if (Reverse) - v = maximum - v; + v = wOut[index] * maximum; - if (Planar) - ((cmsFloat64Number*) output)[(i + start) * Stride] = v; - else - ((cmsFloat64Number*) output)[i + start] = v; - } + if (Reverse) + v = maximum - v; - if (!ExtraFirst) { - output += Extra * sizeof(cmsFloat64Number); - } + if (Planar) + ((cmsFloat64Number*)output)[(i + start) * Stride] = v; + else + ((cmsFloat64Number*)output)[i + start] = v; + } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number)); - *swap1 = v; - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number)); + *swap1 = v; + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsFloat64Number); - else - return output + nChan * sizeof(cmsFloat64Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsFloat64Number); + else + return output + (nChan + Extra) * sizeof(cmsFloat64Number); } @@ -2821,50 +2808,47 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info, register cmsUInt8Number* output, register cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35F : 65535.0F; - cmsFloat32Number v = 0; - cmsUInt16Number* swap1 = (cmsUInt16Number*) output; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F; + cmsFloat32Number v = 0; + cmsUInt16Number* swap1 = (cmsUInt16Number*)output; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = (cmsFloat32Number) wOut[index] / maximum; + v = (cmsFloat32Number)wOut[index] / maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsUInt16Number*) output)[(i + start ) * Stride]= _cmsFloat2Half(v); - else - ((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half(v); - } + if (Planar) + ((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v); + else + ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v); + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsUInt16Number); - } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); - *swap1 = _cmsFloat2Half(v); - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number)); + *swap1 = _cmsFloat2Half(v); + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsUInt16Number); - else - return output + nChan * sizeof(cmsUInt16Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsUInt16Number); + else + return output + (nChan + Extra) * sizeof(cmsUInt16Number); } @@ -2875,50 +2859,47 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info, cmsUInt8Number* output, cmsUInt32Number Stride) { - int nChan = T_CHANNELS(info -> OutputFormat); - int DoSwap = T_DOSWAP(info ->OutputFormat); - int Reverse = T_FLAVOR(info ->OutputFormat); - int Extra = T_EXTRA(info -> OutputFormat); - int SwapFirst = T_SWAPFIRST(info -> OutputFormat); - int Planar = T_PLANAR(info -> OutputFormat); - int ExtraFirst = DoSwap ^ SwapFirst; - cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0F : 1.0F; - cmsUInt16Number* swap1 = (cmsUInt16Number*) output; - cmsFloat32Number v = 0; - int i, start = 0; + int nChan = T_CHANNELS(info->OutputFormat); + int DoSwap = T_DOSWAP(info->OutputFormat); + int Reverse = T_FLAVOR(info->OutputFormat); + int Extra = T_EXTRA(info->OutputFormat); + int SwapFirst = T_SWAPFIRST(info->OutputFormat); + int Planar = T_PLANAR(info->OutputFormat); + int ExtraFirst = DoSwap ^ SwapFirst; + cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F; + cmsUInt16Number* swap1 = (cmsUInt16Number*)output; + cmsFloat32Number v = 0; + int i, start = 0; - if (ExtraFirst) - start = Extra; + if (ExtraFirst) + start = Extra; - for (i=0; i < nChan; i++) { + for (i = 0; i < nChan; i++) { - int index = DoSwap ? (nChan - i - 1) : i; + int index = DoSwap ? (nChan - i - 1) : i; - v = wOut[index] * maximum; + v = wOut[index] * maximum; - if (Reverse) - v = maximum - v; + if (Reverse) + v = maximum - v; - if (Planar) - ((cmsUInt16Number*) output)[(i + start)* Stride]= _cmsFloat2Half( v ); - else - ((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half( v ); - } + if (Planar) + ((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v); + else + ((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v); + } - if (!ExtraFirst) { - output += Extra * sizeof(cmsUInt16Number); - } - if (Extra == 0 && SwapFirst) { + if (Extra == 0 && SwapFirst) { - memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number)); - *swap1 = (cmsUInt16Number) _cmsFloat2Half( v ); - } + memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number)); + *swap1 = (cmsUInt16Number)_cmsFloat2Half(v); + } - if (T_PLANAR(info -> OutputFormat)) - return output + sizeof(cmsUInt16Number); - else - return output + nChan * sizeof(cmsUInt16Number); + if (T_PLANAR(info->OutputFormat)) + return output + sizeof(cmsUInt16Number); + else + return output + (nChan + Extra)* sizeof(cmsUInt16Number); } #endif @@ -3178,6 +3159,8 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe cmsUInt32Number i; cmsFormatter fr; + // Optimization is only a hint + dwInput &= ~OPTIMIZED_SH(1); switch (dwFlags) { diff --git a/thirdparty/liblcms2/src/cmspcs.c b/thirdparty/liblcms2/src/cmspcs.c index 102cd7d2..a08538d3 100644 --- a/thirdparty/liblcms2/src/cmspcs.c +++ b/thirdparty/liblcms2/src/cmspcs.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -106,6 +106,15 @@ void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source) Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y; } +/* + The break point (24/116)^3 = (6/29)^3 is a very small amount of tristimulus + primary (0.008856). Generally, this only happens for + nearly ideal blacks and for some orange / amber colors in transmission mode. + For example, the Z value of the orange turn indicator lamp lens on an + automobile will often be below this value. But the Z does not + contribute to the perceived color directly. +*/ + static cmsFloat64Number f(cmsFloat64Number t) { diff --git a/thirdparty/liblcms2/src/cmsplugin.c b/thirdparty/liblcms2/src/cmsplugin.c index 317e33e2..dc13eadb 100644 --- a/thirdparty/liblcms2/src/cmsplugin.c +++ b/thirdparty/liblcms2/src/cmsplugin.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -215,22 +215,6 @@ cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n } -// Jun-21-2000: Some profiles (those that comes with W2K) comes -// with the media white (media black?) x 100. Add a sanity check - -static -void NormalizeXYZ(cmsCIEXYZ* Dest) -{ - while (Dest -> X > 2. && - Dest -> Y > 2. && - Dest -> Z > 2.) { - - Dest -> X /= 10.; - Dest -> Y /= 10.; - Dest -> Z /= 10.; - } -} - cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) { cmsEncodedXYZNumber xyz; @@ -244,8 +228,6 @@ cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X)); XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y)); XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z)); - - NormalizeXYZ(XYZ); } return TRUE; } @@ -525,6 +507,7 @@ void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size) if (ContextID == NULL) { ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024); + if (ctx->MemPool == NULL) return NULL; } else { cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context"); @@ -683,15 +666,21 @@ struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID) // Internal: get the memory area associanted with each context client -// Returns the block assigned to the specific zone. +// Returns the block assigned to the specific zone. Never return NULL. void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc) { struct _cmsContext_struct* ctx; void *ptr; - if (mc < 0 || mc >= MemoryClientMax) { - cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client"); - return NULL; + if ((int) mc < 0 || mc >= MemoryClientMax) { + + cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption"); + + // This is catastrophic. Should never reach here + _cmsAssert(0); + + // Reverts to global context + return globalContext.chunks[UserPtr]; } ctx = _cmsGetContext(ContextID); @@ -880,7 +869,7 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) } - +/* static struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) { @@ -897,6 +886,7 @@ struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) return NULL; // List is empty or only one element! } +*/ // Frees any resources associated with the given context, // and destroys the context placeholder. @@ -932,8 +922,8 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID) // Search for previous for (prev = _cmsContextPoolHead; - prev != NULL; - prev = prev ->Next) + prev != NULL; + prev = prev ->Next) { if (prev -> Next == ctx) { prev -> Next = ctx ->Next; diff --git a/thirdparty/liblcms2/src/cmsps2.c b/thirdparty/liblcms2/src/cmsps2.c index 224b44b5..0f007732 100644 --- a/thirdparty/liblcms2/src/cmsps2.c +++ b/thirdparty/liblcms2/src/cmsps2.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -1393,14 +1393,15 @@ void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[]) if (nColorant > cmsMAXCHANNELS) nColorant = cmsMAXCHANNELS; - for (j=0; j < nColorant; j++) { + for (j = 0; j < nColorant; j++) { - sprintf(Buff, "%.3f", Out[j] / 65535.0); - strcat(Colorant, Buff); - if (j < nColorant -1) - strcat(Colorant, " "); + snprintf(Buff, 31, "%.3f", Out[j] / 65535.0); + Buff[31] = 0; + strcat(Colorant, Buff); + if (j < nColorant - 1) + strcat(Colorant, " "); - } + } } diff --git a/thirdparty/liblcms2/src/cmssamp.c b/thirdparty/liblcms2/src/cmssamp.c index 70e46916..a9997fa8 100644 --- a/thirdparty/liblcms2/src/cmssamp.c +++ b/thirdparty/liblcms2/src/cmssamp.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2010 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -340,28 +340,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[] } -/* -static -cmsBool IsMonotonic(int n, const cmsFloat64Number Table[]) -{ - int i; - cmsFloat64Number last; - - last = Table[n-1]; - - for (i = n-2; i >= 0; --i) { - - if (Table[i] > last) - - return FALSE; - else - last = Table[i]; - } - - return TRUE; -} -*/ // Calculates the black point of a destination profile. // This algorithm comes from the Adobe paper disclosing its black point compensation method. @@ -486,7 +465,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF // Test for mid range straight (only on relative colorimetric) - NearlyStraightMidrange = TRUE; MinL = outRamp[0]; MaxL = outRamp[255]; if (Intent == INTENT_RELATIVE_COLORIMETRIC) { @@ -502,7 +480,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF // DestinationBlackPoint shall be the same as initialLab. // Otherwise, the DestinationBlackPoint shall be determined // using curve fitting. - if (NearlyStraightMidrange) { cmsLab2XYZ(NULL, BlackPoint, &InitialLab); @@ -513,15 +490,13 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point, - // with a corner and a nearly straight line to the white point. - + // with a corner and a nearly straight line to the white point. for (l=0; l < 256; l++) { yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL); } // find the black point using the least squares error quadratic curve fitting - if (Intent == INTENT_RELATIVE_COLORIMETRIC) { lo = 0.1; hi = 0.5; diff --git a/thirdparty/liblcms2/src/cmssm.c b/thirdparty/liblcms2/src/cmssm.c index e41cb68b..76c566b4 100644 --- a/thirdparty/liblcms2/src/cmssm.c +++ b/thirdparty/liblcms2/src/cmssm.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2011 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -218,7 +218,8 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2 { cmsFloat64Number a, b, c, d, e, D; cmsFloat64Number sc, sN, sD; - cmsFloat64Number tc, tN, tD; + //cmsFloat64Number tc; // left for future use + cmsFloat64Number tN, tD; cmsVEC3 w0; _cmsVEC3minus(&w0, &line1 ->a, &line2 ->a); @@ -286,7 +287,7 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2 } // finally do the division to get sc and tc sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD); - tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); + //tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); // left for future use. GetPointOfLine(r, line1, sc); return TRUE; diff --git a/thirdparty/liblcms2/src/cmstypes.c b/thirdparty/liblcms2/src/cmstypes.c index 60c09ef8..010996ef 100644 --- a/thirdparty/liblcms2/src/cmstypes.c +++ b/thirdparty/liblcms2/src/cmstypes.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -951,7 +951,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO cmsMLU* mlu = (cmsMLU*) Ptr; char *Text = NULL; wchar_t *Wide = NULL; - cmsUInt32Number len, len_aligned, len_filler_alignment; + cmsUInt32Number len, len_text, len_tag_requirement, len_aligned; cmsBool rc = FALSE; char Filler[68]; @@ -961,17 +961,18 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO // Get the len of string len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0); - // From ICC3.4: It has been found that textDescriptionType can contain misaligned data + // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data //(see clause 4.1 for the definition of “aligned”). Because the Unicode language // code and Unicode count immediately follow the ASCII description, their // alignment is not correct if the ASCII count is not a multiple of four. The // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and // writing software must be written carefully in order to handle these alignment // problems. - - // Compute an aligned size - len_aligned = _cmsALIGNLONG(len); - len_filler_alignment = len_aligned - len; + // + // The above last sentence suggest to handle alignment issues in the + // parser. The provided example (Table 69 on Page 60) makes this clear. + // The padding only in the ASCII count is not sufficient for a aligned tag + // size, with the same text size in ASCII and Unicode. // Null strings if (len <= 0) { @@ -992,6 +993,12 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO cmsMLUgetWide(mlu, cmsNoLanguage, cmsNoCountry, Wide, len * sizeof(wchar_t)); } + // Tell the real text len including the null terminator and padding + len_text = strlen(Text) + 1; + // Compute an total tag size requirement + len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67); + len_aligned = _cmsALIGNLONG(len_tag_requirement); + // * cmsUInt32Number count; * Description length // * cmsInt8Number desc[count] * NULL terminated ascii string // * cmsUInt32Number ucLangCode; * UniCode language code @@ -1001,20 +1008,14 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO // * cmsUInt8Number scCount; * ScriptCode count // * cmsInt8Number scDesc[67]; * ScriptCode Description - if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error; - if (!io ->Write(io, len, Text)) goto Error; - if (!io ->Write(io, len_filler_alignment, Filler)) goto Error; + if (!_cmsWriteUInt32Number(io, len_text)) goto Error; + if (!io ->Write(io, len_text, Text)) goto Error; if (!_cmsWriteUInt32Number(io, 0)) goto Error; // ucLanguageCode - // This part is tricky: we need an aligned tag size, and the ScriptCode part - // takes 70 bytes, so we need 2 extra bytes to do the alignment - - if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error; - + if (!_cmsWriteUInt32Number(io, len_text)) goto Error; // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t) - if (!_cmsWriteWCharArray(io, len, Wide)) goto Error; - if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error; + if (!_cmsWriteWCharArray(io, len_text, Wide)) goto Error; // ScriptCode Code & count (unused) if (!_cmsWriteUInt16Number(io, 0)) goto Error; @@ -1022,6 +1023,10 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO if (!io ->Write(io, 67, Filler)) goto Error; + // possibly add pad at the end of tag + if(len_aligned - len_tag_requirement > 0) + if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error; + rc = TRUE; Error: @@ -1503,7 +1508,7 @@ cmsBool Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu =(cmsMLU*) Ptr; cmsUInt32Number HeaderSize; cmsUInt32Number Len, Offset; - int i; + cmsUInt32Number i; if (Ptr == NULL) { @@ -1689,10 +1694,7 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number else for (j=0; j < 256; j++) { - if (Tables != NULL) - val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]); - else - val = (cmsUInt8Number) j; + val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]); if (!_cmsWriteUInt8Number(io, val)) return FALSE; } @@ -3107,6 +3109,8 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i memset(Colorant, 0, sizeof(Colorant)); if (io -> Read(io, Root, 32, 1) != 1) return NULL; + Root[32] = 0; // To prevent exploits + if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error; @@ -3129,8 +3133,8 @@ static cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) { cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; - char prefix[32]; // Prefix for each color name - char suffix[32]; // Suffix for each color name + char prefix[33]; // Prefix for each color name + char suffix[33]; // Suffix for each color name int i, nColors; nColors = cmsNamedColorCount(NamedColorList); @@ -3142,7 +3146,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER strncpy(prefix, (const char*) NamedColorList->Prefix, 32); strncpy(suffix, (const char*) NamedColorList->Suffix, 32); - suffix[31] = prefix[31] = 0; + suffix[32] = prefix[32] = 0; if (!io ->Write(io, 32, prefix)) return FALSE; if (!io ->Write(io, 32, suffix)) return FALSE; @@ -3154,6 +3158,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER char Root[33]; if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0; + Root[32] = 0; if (!io ->Write(io, 32 , Root)) return FALSE; if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE; if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE; @@ -3853,7 +3858,7 @@ cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIO static void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) { - return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening)); + return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsICCViewingConditions)); cmsUNUSED_PARAMETER(n); } @@ -5451,8 +5456,9 @@ static _cmsTagLinkedList SupportedTags[] = { { cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]}, { cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]}, { cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]}, - { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]}, - { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL} + { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]}, + { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]}, + { cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, NULL} }; diff --git a/thirdparty/liblcms2/src/cmsvirt.c b/thirdparty/liblcms2/src/cmsvirt.c index b324c990..2897adb3 100644 --- a/thirdparty/liblcms2/src/cmsvirt.c +++ b/thirdparty/liblcms2/src/cmsvirt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -642,7 +642,7 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID) // Create the ICC virtual profile for sRGB space cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) { - cmsCIExyY D65; + cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 }; cmsCIExyYTRIPLE Rec709Primaries = { {0.6400, 0.3300, 1.0}, {0.3000, 0.6000, 1.0}, @@ -651,7 +651,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID) cmsToneCurve* Gamma22[3]; cmsHPROFILE hsRGB; - cmsWhitePointFromTemp(&D65, 6504); + // cmsWhitePointFromTemp(&D65, 6504); Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID); if (Gamma22[0] == NULL) return NULL; @@ -679,6 +679,7 @@ typedef struct { cmsFloat64Number Contrast; cmsFloat64Number Hue; cmsFloat64Number Saturation; + cmsBool lAdjustWP; cmsCIEXYZ WPsrc, WPdest; } BCHSWADJUSTS, *LPBCHSWADJUSTS; @@ -708,9 +709,10 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O cmsLCh2Lab(&LabOut, &LChOut); // Move white point in Lab - - cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut); - cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ); + if (bchsw->lAdjustWP) { + cmsLab2XYZ(&bchsw->WPsrc, &XYZ, &LabOut); + cmsXYZ2Lab(&bchsw->WPdest, &LabOut, &XYZ); + } // Back to encoded @@ -744,18 +746,23 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID, bchsw.Contrast = Contrast; bchsw.Hue = Hue; bchsw.Saturation = Saturation; + if (TempSrc == TempDest) { - cmsWhitePointFromTemp(&WhitePnt, TempSrc ); - cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); - - cmsWhitePointFromTemp(&WhitePnt, TempDest); - cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); + bchsw.lAdjustWP = FALSE; + } + else { + bchsw.lAdjustWP = TRUE; + cmsWhitePointFromTemp(&WhitePnt, TempSrc); + cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt); + cmsWhitePointFromTemp(&WhitePnt, TempDest); + cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt); + + } hICC = cmsCreateProfilePlaceholder(ContextID); if (!hICC) // can't allocate return NULL; - cmsSetDeviceClass(hICC, cmsSigAbstractClass); cmsSetColorSpace(hICC, cmsSigLabData); cmsSetPCS(hICC, cmsSigLabData); @@ -988,12 +995,14 @@ typedef struct { } cmsAllowedLUT; +#define cmsSig0 ((cmsTagSignature) 0) + static const cmsAllowedLUT AllowedLUTTypes[] = { - { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, - { FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}}, - { FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}}, - { TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }}, + { FALSE, cmsSig0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, + { FALSE, cmsSig0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, + { FALSE, cmsSig0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType } }, + { TRUE, cmsSig0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } }, { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }}, diff --git a/thirdparty/liblcms2/src/cmswtpnt.c b/thirdparty/liblcms2/src/cmswtpnt.c index e657b132..c6b61258 100644 --- a/thirdparty/liblcms2/src/cmswtpnt.c +++ b/thirdparty/liblcms2/src/cmswtpnt.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), diff --git a/thirdparty/liblcms2/src/cmsxform.c b/thirdparty/liblcms2/src/cmsxform.c index 56afede2..0364d062 100644 --- a/thirdparty/liblcms2/src/cmsxform.c +++ b/thirdparty/liblcms2/src/cmsxform.c @@ -1,7 +1,7 @@ //--------------------------------------------------------------------------------- // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -179,12 +179,18 @@ void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform, { _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; - - p -> xform(p, InputBuffer, OutputBuffer, Size, Size); + cmsStride stride; + + stride.BytesPerLineIn = 0; // Not used + stride.BytesPerLineOut = 0; + stride.BytesPerPlaneIn = Size; + stride.BytesPerPlaneOut = Size; + + p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride); } -// Apply transform. +// This is a legacy stride for planar void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, const void* InputBuffer, void* OutputBuffer, @@ -192,10 +198,40 @@ void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, { _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; - p -> xform(p, InputBuffer, OutputBuffer, Size, Stride); + stride.BytesPerLineIn = 0; + stride.BytesPerLineOut = 0; + stride.BytesPerPlaneIn = Stride; + stride.BytesPerPlaneOut = Stride; + + p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride); } +// This is the "fast" function for plugins +void CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM Transform, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + cmsUInt32Number BytesPerLineIn, + cmsUInt32Number BytesPerLineOut, + cmsUInt32Number BytesPerPlaneIn, + cmsUInt32Number BytesPerPlaneOut) + +{ + _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform; + cmsStride stride; + + stride.BytesPerLineIn = BytesPerLineIn; + stride.BytesPerLineOut = BytesPerLineOut; + stride.BytesPerPlaneIn = BytesPerPlaneIn; + stride.BytesPerPlaneOut = BytesPerPlaneOut; + + p->xform(p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride); +} + + // Transform routines ---------------------------------------------------------------------------------------------------------- @@ -204,49 +240,64 @@ void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, static void FloatXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS]; cmsFloat32Number OutOfGamut; - cmsUInt32Number i, j; + cmsUInt32Number i, j, c, strideIn, strideOut; - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); - for (i=0; i < Size; i++) { + strideIn = 0; + strideOut = 0; - accum = p -> FromInputFloat(p, fIn, accum, Stride); + for (i = 0; i < LineCount; i++) { - // Any gamut chack to do? - if (p ->GamutCheck != NULL) { + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; - // Evaluate gamut marker. - cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck); + for (j = 0; j < PixelsPerLine; j++) { - // Is current color out of gamut? - if (OutOfGamut > 0.0) { + accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn); - // Certainly, out of gamut - for (j=0; j < cmsMAXCHANNELS; j++) - fOut[j] = -1.0; + // Any gamut chack to do? + if (p->GamutCheck != NULL) { + // Evaluate gamut marker. + cmsPipelineEvalFloat(fIn, &OutOfGamut, p->GamutCheck); + + // Is current color out of gamut? + if (OutOfGamut > 0.0) { + + // Certainly, out of gamut + for (c = 0; c < cmsMAXCHANNELS; c++) + fOut[c] = -1.0; + + } + else { + // No, proceed normally + cmsPipelineEvalFloat(fIn, fOut, p->Lut); + } } else { - // No, proceed normally - cmsPipelineEvalFloat(fIn, fOut, p -> Lut); + + // No gamut check at all + cmsPipelineEvalFloat(fIn, fOut, p->Lut); } - } - else { - // No gamut check at all - cmsPipelineEvalFloat(fIn, fOut, p -> Lut); + + output = p->ToOutputFloat(p, fOut, output, Stride->BytesPerPlaneOut); } - // Back to asked representation - output = p -> ToOutputFloat(p, fOut, output, Stride); + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; } + } @@ -254,22 +305,34 @@ static void NullFloatXFORM(_cmsTRANSFORM* p, const void* in, void* out, - cmsUInt32Number Size, - cmsUInt32Number Stride) + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) + { cmsUInt8Number* accum; cmsUInt8Number* output; cmsFloat32Number fIn[cmsMAXCHANNELS]; - cmsUInt32Number i, n; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; + accum = (cmsUInt8Number*) in + strideIn; + output = (cmsUInt8Number*) out + strideOut; - for (i=0; i < n; i++) { + for (j = 0; j < PixelsPerLine; j++) { - accum = p -> FromInputFloat(p, fIn, accum, Stride); - output = p -> ToOutputFloat(p, fIn, output, Stride); + accum = p->FromInputFloat(p, fIn, accum, Stride ->BytesPerPlaneIn); + output = p->ToOutputFloat(p, fIn, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; } } @@ -279,23 +342,36 @@ void NullFloatXFORM(_cmsTRANSFORM* p, static void NullXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size, - cmsUInt32Number Stride) + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; cmsUInt16Number wIn[cmsMAXCHANNELS]; - cmsUInt32Number i, n; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; - for (i=0; i < n; i++) { + for (j = 0; j < PixelsPerLine; j++) { - accum = p -> FromInput(p, wIn, accum, Stride); - output = p -> ToOutput(p, wIn, output, Stride); + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut); } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } + } @@ -303,23 +379,37 @@ void NullXFORM(_cmsTRANSFORM* p, static void PrecalculatedXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) { register cmsUInt8Number* accum; register cmsUInt8Number* output; cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; + cmsUInt32Number i, j, strideIn, strideOut; - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); - for (i=0; i < n; i++) { + strideIn = 0; + strideOut = 0; - accum = p -> FromInput(p, wIn, accum, Stride); - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); - output = p -> ToOutput(p, wOut, output, Stride); + for (i = 0; i < LineCount; i++) { + + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; + + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data); + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; } + } @@ -350,22 +440,35 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p, static void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len + for (i = 0; i < LineCount; i++) { - for (i=0; i < n; i++) { + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; - accum = p -> FromInput(p, wIn, accum, Stride); - TransformOnePixelWithGamutCheck(p, wIn, wOut); - output = p -> ToOutput(p, wOut, output, Stride); + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + TransformOnePixelWithGamutCheck(p, wIn, wOut); + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; } } @@ -374,94 +477,120 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p, static void CachedXFORM(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) { cmsUInt8Number* accum; cmsUInt8Number* output; cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; _cmsCACHE Cache; + cmsUInt32Number i, j, strideIn, strideOut; - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); // Empty buffers for quick memcmp - memset(wIn, 0, sizeof(wIn)); + memset(wIn, 0, sizeof(wIn)); memset(wOut, 0, sizeof(wOut)); // Get copy of zero cache - memcpy(&Cache, &p ->Cache, sizeof(Cache)); + memcpy(&Cache, &p->Cache, sizeof(Cache)); - for (i=0; i < n; i++) { + strideIn = 0; + strideOut = 0; - accum = p -> FromInput(p, wIn, accum, Stride); + for (i = 0; i < LineCount; i++) { - if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; - memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); - } - else { + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); + + if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { - p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data); + memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); + } + else { + p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data); - memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); - memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); + memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + } + + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); } - output = p -> ToOutput(p, wOut, output, Stride); + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; } - } - // All those nice features together static void CachedXFORMGamutCheck(_cmsTRANSFORM* p, const void* in, - void* out, cmsUInt32Number Size, cmsUInt32Number Stride) + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) { - cmsUInt8Number* accum; - cmsUInt8Number* output; - cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; - cmsUInt32Number i, n; - _cmsCACHE Cache; + cmsUInt8Number* accum; + cmsUInt8Number* output; + cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS]; + _cmsCACHE Cache; + cmsUInt32Number i, j, strideIn, strideOut; + + _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride); + + // Empty buffers for quick memcmp + memset(wIn, 0, sizeof(wIn)); + memset(wOut, 0, sizeof(wOut)); - accum = (cmsUInt8Number*) in; - output = (cmsUInt8Number*) out; - n = Size; // Buffer len + // Get copy of zero cache + memcpy(&Cache, &p->Cache, sizeof(Cache)); - // Empty buffers for quick memcmp - memset(wIn, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); - memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS); + strideIn = 0; + strideOut = 0; - // Get copy of zero cache - memcpy(&Cache, &p ->Cache, sizeof(Cache)); + for (i = 0; i < LineCount; i++) { - for (i=0; i < n; i++) { + accum = (cmsUInt8Number*)in + strideIn; + output = (cmsUInt8Number*)out + strideOut; - accum = p -> FromInput(p, wIn, accum, Stride); + for (j = 0; j < PixelsPerLine; j++) { + + accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn); if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) { - memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); + + memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut)); } else { - TransformOnePixelWithGamutCheck(p, wIn, wOut); - memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); - memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); + TransformOnePixelWithGamutCheck(p, wIn, wOut); + + memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn)); + memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut)); } - output = p -> ToOutput(p, wOut, output, Stride); - } + output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut); + } + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } } -// ------------------------------------------------------------------------------------------------------------- +// Transform plug-ins ---------------------------------------------------------------------------------------------------- // List of used-defined transform factories typedef struct _cmsTransformCollection_st { - _cmsTransformFactory Factory; + _cmsTransform2Factory Factory; + cmsBool OldXform; // Factory returns xform function in the old style + struct _cmsTransformCollection_st *Next; } _cmsTransformCollection; @@ -504,6 +633,7 @@ void DupPluginTransformList(struct _cmsContext_struct* ctx, ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType)); } +// Allocates memory for transform plugin factory void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src) { @@ -518,6 +648,35 @@ void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx, } } +// Adaptor for old versions of plug-in +static +void _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo, + const void* InputBuffer, + void* OutputBuffer, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride) +{ + + cmsUInt32Number i, strideIn, strideOut; + + _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride); + + strideIn = 0; + strideOut = 0; + + for (i = 0; i < LineCount; i++) { + + void *accum = (cmsUInt8Number*)InputBuffer + strideIn; + void *output = (cmsUInt8Number*)OutputBuffer + strideOut; + + CMMcargo->OldXform(CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn); + + strideIn += Stride->BytesPerLineIn; + strideOut += Stride->BytesPerLineOut; + } +} + // Register new ways to transform @@ -535,14 +694,22 @@ cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data) } // Factory callback is required - if (Plugin ->Factory == NULL) return FALSE; + if (Plugin->factories.xform == NULL) return FALSE; fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection)); if (fl == NULL) return FALSE; + // Check for full xform plug-ins previous to 2.8, we would need an adapter in that case + if (Plugin->base.ExpectedVersion < 2080) { + + fl->OldXform = TRUE; + } + else + fl->OldXform = FALSE; + // Copy the parameters - fl ->Factory = Plugin ->Factory; + fl->Factory = Plugin->factories.xform; // Keep linked list fl ->Next = ctx->TransformCollection; @@ -592,46 +759,54 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut, _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin); _cmsTransformCollection* Plugin; - // Allocate needed memory - _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); - if (!p) return NULL; - - // Store the proposed pipeline - p ->Lut = lut; - - // Let's see if any plug-in want to do the transform by itself - for (Plugin = ctx ->TransformCollection; - Plugin != NULL; - Plugin = Plugin ->Next) { - - if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) { - - // Last plugin in the declaration order takes control. We just keep - // the original parameters as a logging. - // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default - // an optimized transform is not reusable. The plug-in can, however, change - // the flags and make it suitable. - - p ->ContextID = ContextID; - p ->InputFormat = *InputFormat; - p ->OutputFormat = *OutputFormat; - p ->dwOriginalFlags = *dwFlags; - - // Fill the formatters just in case the optimized routine is interested. - // No error is thrown if the formatter doesn't exist. It is up to the optimization - // factory to decide what to do in those cases. - p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; - p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; - - return p; - } - } - - // Not suitable for the transform plug-in, let's check the pipeline plug-in - if (p ->Lut != NULL) - _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + // Allocate needed memory + _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM)); + if (!p) return NULL; + + // Store the proposed pipeline + p->Lut = lut; + + // Let's see if any plug-in want to do the transform by itself + if (p->Lut != NULL) { + + for (Plugin = ctx->TransformCollection; + Plugin != NULL; + Plugin = Plugin->Next) { + + if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) { + + // Last plugin in the declaration order takes control. We just keep + // the original parameters as a logging. + // Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default + // an optimized transform is not reusable. The plug-in can, however, change + // the flags and make it suitable. + + p->ContextID = ContextID; + p->InputFormat = *InputFormat; + p->OutputFormat = *OutputFormat; + p->dwOriginalFlags = *dwFlags; + + // Fill the formatters just in case the optimized routine is interested. + // No error is thrown if the formatter doesn't exist. It is up to the optimization + // factory to decide what to do in those cases. + p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16; + p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16; + p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat; + + // Save the day? + if (Plugin->OldXform) { + p->OldXform = (_cmsTransformFn) p->xform; + p->xform = _cmsTransform2toTransformAdaptor; + } + + return p; + } + } + + // Not suitable for the transform plug-in, let's check the pipeline plug-in + _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags); + } // Check whatever this is a true floating point transform if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) { @@ -785,6 +960,22 @@ cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwForm // ---------------------------------------------------------------------------------------------------------------- +// Jun-21-2000: Some profiles (those that comes with W2K) comes +// with the media white (media black?) x 100. Add a sanity check + +static +void NormalizeXYZ(cmsCIEXYZ* Dest) +{ + while (Dest -> X > 2. && + Dest -> Y > 2. && + Dest -> Z > 2.) { + + Dest -> X /= 10.; + Dest -> Y /= 10.; + Dest -> Z /= 10.; + } +} + static void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) { @@ -797,6 +988,8 @@ void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src) wtPt ->X = src->X; wtPt ->Y = src->Y; wtPt ->Z = src->Z; + + NormalizeXYZ(wtPt); } } @@ -1107,7 +1300,6 @@ cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat) { - _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform; cmsFormatter16 FromInput, ToOutput; diff --git a/thirdparty/liblcms2/src/lcms2.def b/thirdparty/liblcms2/src/lcms2.def deleted file mode 100644 index a1f69c42..00000000 --- a/thirdparty/liblcms2/src/lcms2.def +++ /dev/null @@ -1,341 +0,0 @@ -LIBRARY LCMS2.DLL
-
-EXPORTS
-
-_cms15Fixed16toDouble = _cms15Fixed16toDouble
-_cms8Fixed8toDouble = _cms8Fixed8toDouble
-cmsAdaptToIlluminant = cmsAdaptToIlluminant
-_cmsAdjustEndianess16 = _cmsAdjustEndianess16
-_cmsAdjustEndianess32 = _cmsAdjustEndianess32
-_cmsAdjustEndianess64 = _cmsAdjustEndianess64
-cmsAllocNamedColorList = cmsAllocNamedColorList
-cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription
-cmsAppendNamedColor = cmsAppendNamedColor
-cmsBFDdeltaE = cmsBFDdeltaE
-cmsBuildGamma = cmsBuildGamma
-cmsBuildParametricToneCurve = cmsBuildParametricToneCurve
-cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve
-cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16
-cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat
-_cmsCalloc = _cmsCalloc
-cmsChannelsOf = cmsChannelsOf
-cmsCIE2000DeltaE = cmsCIE2000DeltaE
-cmsCIE94DeltaE = cmsCIE94DeltaE
-cmsCIECAM02Done = cmsCIECAM02Done
-cmsCIECAM02Forward = cmsCIECAM02Forward
-cmsCIECAM02Init = cmsCIECAM02Init
-cmsCIECAM02Reverse = cmsCIECAM02Reverse
-cmsCloseIOhandler = cmsCloseIOhandler
-cmsCloseProfile = cmsCloseProfile
-cmsCMCdeltaE = cmsCMCdeltaE
-cmsCreate_sRGBProfile = cmsCreate_sRGBProfile
-cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR
-cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile
-cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR
-cmsCreateExtendedTransform = cmsCreateExtendedTransform
-cmsCreateGrayProfile = cmsCreateGrayProfile
-cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR
-cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink
-cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR
-cmsCreateLab2Profile = cmsCreateLab2Profile
-cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR
-cmsCreateLab4Profile = cmsCreateLab4Profile
-cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR
-cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink
-cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR
-cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform
-cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR
-cmsCreateNULLProfile = cmsCreateNULLProfile
-cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR
-cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder
-cmsCreateProofingTransform = cmsCreateProofingTransform
-cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR
-cmsCreateRGBProfile = cmsCreateRGBProfile
-cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR
-cmsCreateTransform = cmsCreateTransform
-cmsCreateTransformTHR = cmsCreateTransformTHR
-cmsCreateXYZProfile = cmsCreateXYZProfile
-cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR
-cmsD50_xyY = cmsD50_xyY
-cmsD50_XYZ = cmsD50_XYZ
-_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber
-_cmsDefaultICCintents = _cmsDefaultICCintents
-cmsDeleteTransform = cmsDeleteTransform
-cmsDeltaE = cmsDeltaE
-cmsDetectBlackPoint = cmsDetectBlackPoint
-cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint
-cmsDetectTAC = cmsDetectTAC
-cmsDesaturateLab = cmsDesaturateLab
-cmsDoTransform = cmsDoTransform
-cmsDoTransformStride = cmsDoTransformStride
-_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16
-_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8
-_cmsDupMem = _cmsDupMem
-cmsDupNamedColorList = cmsDupNamedColorList
-cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription
-cmsDupToneCurve = cmsDupToneCurve
-_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber
-cmsEstimateGamma = cmsEstimateGamma
-cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries
-cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable
-cmsEvalToneCurve16 = cmsEvalToneCurve16
-cmsEvalToneCurveFloat = cmsEvalToneCurveFloat
-cmsfilelength = cmsfilelength
-cmsFloat2LabEncoded = cmsFloat2LabEncoded
-cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2
-cmsFloat2XYZEncoded = cmsFloat2XYZEncoded
-cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile
-cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile
-_cmsFree = _cmsFree
-cmsFreeNamedColorList = cmsFreeNamedColorList
-cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription
-cmsFreeToneCurve = cmsFreeToneCurve
-cmsFreeToneCurveTriple = cmsFreeToneCurveTriple
-cmsGBDAlloc = cmsGBDAlloc
-cmsGBDFree = cmsGBDFree
-cmsGDBAddPoint = cmsGDBAddPoint
-cmsGDBCheckPoint = cmsGDBCheckPoint
-cmsGDBCompute = cmsGDBCompute
-cmsGetAlarmCodes = cmsGetAlarmCodes
-cmsGetColorSpace = cmsGetColorSpace
-cmsGetDeviceClass = cmsGetDeviceClass
-cmsGetEncodedICCversion = cmsGetEncodedICCversion
-cmsGetHeaderAttributes = cmsGetHeaderAttributes
-cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime
-cmsGetHeaderFlags = cmsGetHeaderFlags
-cmsGetHeaderManufacturer = cmsGetHeaderManufacturer
-cmsGetHeaderModel = cmsGetHeaderModel
-cmsGetHeaderProfileID = cmsGetHeaderProfileID
-cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent
-cmsGetNamedColorList = cmsGetNamedColorList
-cmsGetPCS = cmsGetPCS
-cmsGetPostScriptColorResource = cmsGetPostScriptColorResource
-cmsGetPostScriptCRD = cmsGetPostScriptCRD
-cmsGetPostScriptCSA = cmsGetPostScriptCSA
-cmsGetProfileInfo = cmsGetProfileInfo
-cmsGetProfileInfoASCII = cmsGetProfileInfoASCII
-cmsGetProfileContextID = cmsGetProfileContextID
-cmsGetProfileVersion = cmsGetProfileVersion
-cmsGetSupportedIntents = cmsGetSupportedIntents
-cmsGetTagCount = cmsGetTagCount
-cmsGetTagSignature = cmsGetTagSignature
-cmsGetTransformContextID = cmsGetTransformContextID
-_cmsICCcolorSpace = _cmsICCcolorSpace
-_cmsIOPrintf = _cmsIOPrintf
-cmsIsCLUT = cmsIsCLUT
-cmsIsIntentSupported = cmsIsIntentSupported
-cmsIsMatrixShaper = cmsIsMatrixShaper
-cmsIsTag = cmsIsTag
-cmsIsToneCurveDescending = cmsIsToneCurveDescending
-cmsIsToneCurveLinear = cmsIsToneCurveLinear
-cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic
-cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment
-cmsGetToneCurveParametricType = cmsGetToneCurveParametricType
-cmsIT8Alloc = cmsIT8Alloc
-cmsIT8DefineDblFormat = cmsIT8DefineDblFormat
-cmsIT8EnumDataFormat = cmsIT8EnumDataFormat
-cmsIT8EnumProperties = cmsIT8EnumProperties
-cmsIT8EnumPropertyMulti = cmsIT8EnumPropertyMulti
-cmsIT8Free = cmsIT8Free
-cmsIT8GetData = cmsIT8GetData
-cmsIT8GetDataDbl = cmsIT8GetDataDbl
-cmsIT8FindDataFormat = cmsIT8FindDataFormat
-cmsIT8GetDataRowCol = cmsIT8GetDataRowCol
-cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl
-cmsIT8GetPatchName = cmsIT8GetPatchName
-cmsIT8GetPatchByName = cmsIT8GetPatchByName
-cmsIT8GetProperty = cmsIT8GetProperty
-cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl
-cmsIT8GetPropertyMulti = cmsIT8GetPropertyMulti
-cmsIT8GetSheetType = cmsIT8GetSheetType
-cmsIT8LoadFromFile = cmsIT8LoadFromFile
-cmsIT8LoadFromMem = cmsIT8LoadFromMem
-cmsIT8SaveToFile = cmsIT8SaveToFile
-cmsIT8SaveToMem = cmsIT8SaveToMem
-cmsIT8SetComment = cmsIT8SetComment
-cmsIT8SetData = cmsIT8SetData
-cmsIT8SetDataDbl = cmsIT8SetDataDbl
-cmsIT8SetDataFormat = cmsIT8SetDataFormat
-cmsIT8SetDataRowCol = cmsIT8SetDataRowCol
-cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl
-cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl
-cmsIT8SetPropertyHex = cmsIT8SetPropertyHex
-cmsIT8SetPropertyStr = cmsIT8SetPropertyStr
-cmsIT8SetPropertyMulti = cmsIT8SetPropertyMulti
-cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked
-cmsIT8SetSheetType = cmsIT8SetSheetType
-cmsIT8SetTable = cmsIT8SetTable
-cmsIT8SetTableByLabel = cmsIT8SetTableByLabel
-cmsIT8SetIndexColumn = cmsIT8SetIndexColumn
-cmsIT8TableCount = cmsIT8TableCount
-cmsJoinToneCurve = cmsJoinToneCurve
-cmsLab2LCh = cmsLab2LCh
-cmsLab2XYZ = cmsLab2XYZ
-cmsLabEncoded2Float = cmsLabEncoded2Float
-cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2
-cmsLCh2Lab = cmsLCh2Lab
-_cmsLCMScolorSpace = _cmsLCMScolorSpace
-cmsLinkTag = cmsLinkTag
-cmsTagLinkedTo = cmsTagLinkedTo
-cmsPipelineAlloc = cmsPipelineAlloc
-cmsPipelineCat = cmsPipelineCat
-cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages
-cmsPipelineDup = cmsPipelineDup
-cmsPipelineStageCount = cmsPipelineStageCount
-cmsPipelineEval16 = cmsPipelineEval16
-cmsPipelineEvalFloat = cmsPipelineEvalFloat
-cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat
-cmsPipelineFree = cmsPipelineFree
-cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage
-cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage
-cmsPipelineInputChannels = cmsPipelineInputChannels
-cmsPipelineInsertStage = cmsPipelineInsertStage
-cmsPipelineOutputChannels = cmsPipelineOutputChannels
-cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag
-_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters
-cmsPipelineUnlinkStage = cmsPipelineUnlinkStage
-_cmsMalloc = _cmsMalloc
-_cmsMallocZero = _cmsMallocZero
-_cmsMAT3eval = _cmsMAT3eval
-_cmsMAT3identity = _cmsMAT3identity
-_cmsMAT3inverse = _cmsMAT3inverse
-_cmsMAT3isIdentity = _cmsMAT3isIdentity
-_cmsMAT3per = _cmsMAT3per
-_cmsMAT3solve = _cmsMAT3solve
-cmsMD5computeID = cmsMD5computeID
-cmsMLUalloc = cmsMLUalloc
-cmsMLUdup = cmsMLUdup
-cmsMLUfree = cmsMLUfree
-cmsMLUgetASCII = cmsMLUgetASCII
-cmsMLUgetTranslation = cmsMLUgetTranslation
-cmsMLUgetWide = cmsMLUgetWide
-cmsMLUsetASCII = cmsMLUsetASCII
-cmsMLUsetWide = cmsMLUsetWide
-cmsStageAllocCLut16bit = cmsStageAllocCLut16bit
-cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular
-cmsStageAllocCLutFloat = cmsStageAllocCLutFloat
-cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular
-cmsStageAllocToneCurves = cmsStageAllocToneCurves
-cmsStageAllocIdentity = cmsStageAllocIdentity
-cmsStageAllocMatrix = cmsStageAllocMatrix
-_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder
-cmsStageDup = cmsStageDup
-cmsStageFree = cmsStageFree
-cmsStageNext = cmsStageNext
-cmsStageInputChannels = cmsStageInputChannels
-cmsStageOutputChannels = cmsStageOutputChannels
-cmsStageSampleCLut16bit = cmsStageSampleCLut16bit
-cmsStageSampleCLutFloat = cmsStageSampleCLutFloat
-cmsStageType = cmsStageType
-cmsStageData = cmsStageData
-cmsNamedColorCount = cmsNamedColorCount
-cmsNamedColorIndex = cmsNamedColorIndex
-cmsNamedColorInfo = cmsNamedColorInfo
-cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile
-cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem
-cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL
-cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream
-cmsOpenProfileFromFile = cmsOpenProfileFromFile
-cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR
-cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR
-cmsOpenProfileFromMem = cmsOpenProfileFromMem
-cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR
-cmsOpenProfileFromStream = cmsOpenProfileFromStream
-cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR
-cmsPlugin = cmsPlugin
-_cmsRead15Fixed16Number = _cmsRead15Fixed16Number
-_cmsReadAlignment = _cmsReadAlignment
-_cmsReadFloat32Number = _cmsReadFloat32Number
-cmsReadRawTag = cmsReadRawTag
-cmsReadTag = cmsReadTag
-_cmsReadTypeBase = _cmsReadTypeBase
-_cmsReadUInt16Array = _cmsReadUInt16Array
-_cmsReadUInt16Number = _cmsReadUInt16Number
-_cmsReadUInt32Number = _cmsReadUInt32Number
-_cmsReadUInt64Number = _cmsReadUInt64Number
-_cmsReadUInt8Number = _cmsReadUInt8Number
-_cmsReadXYZNumber = _cmsReadXYZNumber
-_cmsRealloc = _cmsRealloc
-cmsReverseToneCurve = cmsReverseToneCurve
-cmsReverseToneCurveEx = cmsReverseToneCurveEx
-cmsSaveProfileToFile = cmsSaveProfileToFile
-cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler
-cmsSaveProfileToMem = cmsSaveProfileToMem
-cmsSaveProfileToStream = cmsSaveProfileToStream
-cmsSetAdaptationState = cmsSetAdaptationState
-cmsSetAlarmCodes = cmsSetAlarmCodes
-cmsSetColorSpace = cmsSetColorSpace
-cmsSetDeviceClass = cmsSetDeviceClass
-cmsSetEncodedICCversion = cmsSetEncodedICCversion
-cmsSetHeaderAttributes = cmsSetHeaderAttributes
-cmsSetHeaderFlags = cmsSetHeaderFlags
-cmsSetHeaderManufacturer = cmsSetHeaderManufacturer
-cmsSetHeaderModel = cmsSetHeaderModel
-cmsSetHeaderProfileID = cmsSetHeaderProfileID
-cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent
-cmsSetLogErrorHandler = cmsSetLogErrorHandler
-cmsSetPCS = cmsSetPCS
-cmsSetProfileVersion = cmsSetProfileVersion
-cmsSignalError = cmsSignalError
-cmsSmoothToneCurve = cmsSmoothToneCurve
-cmsstrcasecmp = cmsstrcasecmp
-cmsTempFromWhitePoint = cmsTempFromWhitePoint
-cmsTransform2DeviceLink = cmsTransform2DeviceLink
-cmsUnregisterPlugins = cmsUnregisterPlugins
-_cmsVEC3cross = _cmsVEC3cross
-_cmsVEC3distance = _cmsVEC3distance
-_cmsVEC3dot = _cmsVEC3dot
-_cmsVEC3init = _cmsVEC3init
-_cmsVEC3length = _cmsVEC3length
-_cmsVEC3minus = _cmsVEC3minus
-cmsWhitePointFromTemp = cmsWhitePointFromTemp
-_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number
-_cmsWriteAlignment = _cmsWriteAlignment
-_cmsWriteFloat32Number = _cmsWriteFloat32Number
-cmsWriteRawTag = cmsWriteRawTag
-cmsWriteTag = cmsWriteTag
-_cmsWriteTypeBase = _cmsWriteTypeBase
-_cmsWriteUInt16Array = _cmsWriteUInt16Array
-_cmsWriteUInt16Number = _cmsWriteUInt16Number
-_cmsWriteUInt32Number = _cmsWriteUInt32Number
-_cmsWriteUInt64Number = _cmsWriteUInt64Number
-_cmsWriteUInt8Number = _cmsWriteUInt8Number
-_cmsWriteXYZNumber = _cmsWriteXYZNumber
-cmsxyY2XYZ = cmsxyY2XYZ
-cmsXYZ2Lab = cmsXYZ2Lab
-cmsXYZ2xyY = cmsXYZ2xyY
-cmsXYZEncoded2Float = cmsXYZEncoded2Float
-cmsSliceSpace16 = cmsSliceSpace16
-cmsSliceSpaceFloat = cmsSliceSpaceFloat
-cmsChangeBuffersFormat = cmsChangeBuffersFormat
-cmsDictAlloc = cmsDictAlloc
-cmsDictFree = cmsDictFree
-cmsDictDup = cmsDictDup
-cmsDictAddEntry = cmsDictAddEntry
-cmsDictGetEntryList = cmsDictGetEntryList
-cmsDictNextEntry = cmsDictNextEntry
-_cmsGetTransformUserData = _cmsGetTransformUserData
-_cmsSetTransformUserData = _cmsSetTransformUserData
-_cmsGetTransformFormatters16 = _cmsGetTransformFormatters16
-_cmsGetTransformFormattersFloat = _cmsGetTransformFormattersFloat
-cmsGetHeaderCreator = cmsGetHeaderCreator
-cmsPluginTHR = cmsPluginTHR
-cmsGetPipelineContextID = cmsGetPipelineContextID
-cmsGetTransformInputFormat = cmsGetTransformInputFormat
-cmsGetTransformOutputFormat = cmsGetTransformOutputFormat
-cmsCreateContext = cmsCreateContext
-cmsDupContext = cmsDupContext
-cmsDeleteContext = cmsDeleteContext
-cmsGetContextUserData = cmsGetContextUserData
-cmsUnregisterPluginsTHR = cmsUnregisterPluginsTHR
-cmsSetAlarmCodesTHR = cmsSetAlarmCodesTHR
-cmsGetAlarmCodesTHR = cmsGetAlarmCodesTHR
-cmsSetAdaptationStateTHR = cmsSetAdaptationStateTHR
-cmsSetLogErrorHandlerTHR = cmsSetLogErrorHandlerTHR
-cmsGetSupportedIntentsTHR = cmsGetSupportedIntentsTHR
-cmsMLUtranslationsCount = cmsMLUtranslationsCount
-cmsMLUtranslationsCodes = cmsMLUtranslationsCodes
-_cmsCreateMutex = _cmsCreateMutex
-_cmsDestroyMutex = _cmsDestroyMutex
-_cmsLockMutex = _cmsLockMutex
-_cmsUnlockMutex = _cmsUnlockMutex
\ No newline at end of file diff --git a/thirdparty/liblcms2/src/lcms2_internal.h b/thirdparty/liblcms2/src/lcms2_internal.h index 1a648302..e1219036 100644 --- a/thirdparty/liblcms2/src/lcms2_internal.h +++ b/thirdparty/liblcms2/src/lcms2_internal.h @@ -1,7 +1,7 @@ // // Little Color Management System -// Copyright (c) 1998-2014 Marti Maria Saguer +// Copyright (c) 1998-2016 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"), @@ -57,7 +57,15 @@ #define _cmsALIGNLONG(x) (((x)+(sizeof(cmsUInt32Number)-1)) & ~(sizeof(cmsUInt32Number)-1)) // Alignment to memory pointer -#define _cmsALIGNMEM(x) (((x)+(sizeof(void *) - 1)) & ~(sizeof(void *) - 1)) + +// (Ultra)SPARC with gcc requires ptr alignment of 8 bytes +// even though sizeof(void *) is only four: for greatest flexibility +// allow the build to specify ptr alignment. +#ifndef CMS_PTR_ALIGNMENT +# define CMS_PTR_ALIGNMENT sizeof(void *) +#endif + +#define _cmsALIGNMEM(x) (((x)+(CMS_PTR_ALIGNMENT - 1)) & ~(CMS_PTR_ALIGNMENT - 1)) // Maximum encodeable values in floating point #define MAX_ENCODEABLE_XYZ (1.0 + 32767.0/32768.0) @@ -194,11 +202,17 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d) // Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical // section, even when they changed the underlying algorithm to be more scalable. // The final parts of the critical section object are unimportant, and can be set -// to zero for their defaults. This yields an initialization macro: +// to zero for their defaults. This yields to an initialization macro: typedef CRITICAL_SECTION _cmsMutex; -#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0} +#define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0} + +#ifdef _MSC_VER +# if (_MSC_VER >= 1800) +# pragma warning(disable : 26135) +# endif +#endif cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) { @@ -284,38 +298,38 @@ typedef int _cmsMutex; cmsINLINE int _cmsLockPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m) { - return 0; cmsUNUSED_PARAMETER(m); + return 0; } #endif @@ -656,8 +670,8 @@ struct _cms_MLU_struct { cmsContext ContextID; // The directory - int AllocatedEntries; - int UsedEntries; + cmsUInt32Number AllocatedEntries; + cmsUInt32Number UsedEntries; _cmsMLUentry* Entries; // Array of pointers to strings allocated in MemPool // The Pool @@ -823,6 +837,8 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID); cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID); +cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels); + // For curve set only cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe); @@ -951,7 +967,7 @@ typedef struct _cmstransform_struct { cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference // Points to transform code - _cmsTransformFn xform; + _cmsTransform2Fn xform; // Formatters, cannot be embedded into LUT because cache cmsFormatter16 FromInput; @@ -997,9 +1013,20 @@ typedef struct _cmstransform_struct { void* UserData; _cmsFreeUserDataFn FreeUserData; + // A way to provide backwards compatibility with full xform plugins + _cmsTransformFn OldXform; + } _cmsTRANSFORM; -// -------------------------------------------------------------------------------------------------- +// Copies extra channels from input to output if the original flags in the transform structure +// instructs to do so. This function is called on all standard transform functions. +void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in, + void* out, + cmsUInt32Number PixelsPerLine, + cmsUInt32Number LineCount, + const cmsStride* Stride); + +// ----------------------------------------------------------------------------------------------------------------------- cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID, cmsUInt32Number nProfiles, |
