Upgrade to lcms 2.9.

- Update patch 0000 to apply cleanly.
- Update patches 0005, 0019, and 0026 to apply.
- Update patch 0008 to use our fix. The fix upstream may not be correct.
- Update patch 0030 to remove the parts that already exists upstream.
- Remove patches that are already upstreamed.

BUG=pdfium:1128

Change-Id: Ifceae87fc659065f26ce2a5b403bd2fa8aef4b38
Reviewed-on: https://pdfium-review.googlesource.com/c/47951
Reviewed-by: Nicolás Peña Moreno <npm@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/lcms/0000-cmserr-changes.patch b/third_party/lcms/0000-cmserr-changes.patch
index baf3577..31f56fd 100644
--- a/third_party/lcms/0000-cmserr-changes.patch
+++ b/third_party/lcms/0000-cmserr-changes.patch
@@ -11,7 +11,7 @@
  
  // This function is here to help applications to prevent mixing lcms versions on header and shared objects.
  int CMSEXPORT cmsGetEncodedCMMversion(void)
-@@ -65,140 +67,75 @@ long int CMSEXPORT cmsfilelength(FILE* f)
+@@ -67,140 +67,75 @@ long int CMSEXPORT cmsfilelength(FILE* f)
      return n;
  }
  
@@ -36,7 +36,7 @@
 -// *********************************************************************************
 -
 -// This is the default memory allocation function. It does a very coarse
--// check of amout of memory, just to prevent exploits
+-// check of amount of memory, just to prevent exploits
 -static
 -void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size)
 +cmsBool  _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin)
@@ -174,7 +174,7 @@
      }
      else {
  
-         // To reset it, we use the default allocators, which cannot be overriden
+         // To reset it, we use the default allocators, which cannot be overridden
          ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager;
 -    } 
 +    }
@@ -184,7 +184,7 @@
  void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr)
  {
      if (Plugin == NULL) {
-@@ -212,94 +149,15 @@ void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkTy
+@@ -214,94 +149,15 @@ void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkTy
          ptr ->ReallocPtr = Plugin -> ReallocPtr;
  
          // Make sure we revert to defaults
diff --git a/third_party/lcms/0005-old-fix-e-with-tilde.patch b/third_party/lcms/0005-old-fix-e-with-tilde.patch
index 2fc054d..9a389bc 100644
--- a/third_party/lcms/0005-old-fix-e-with-tilde.patch
+++ b/third_party/lcms/0005-old-fix-e-with-tilde.patch
@@ -1,60 +1,60 @@
 diff --git a/third_party/lcms/src/cmsxform.c b/third_party/lcms/src/cmsxform.c
-index 4a5a4f093..9c20c49b0 100644
+index 6b2950e4e..508117bd3 100644
 --- a/third_party/lcms/src/cmsxform.c
 +++ b/third_party/lcms/src/cmsxform.c
-@@ -338,7 +338,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p,
+@@ -341,7 +341,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p,
  
  // 16 bit precision -----------------------------------------------------------------------------------------------------------
  
--// Null transformation, only applies formatters. No cach<E9>
+-// Null transformation, only applies formatters. No caché
 +// Null transformation, only applies formatters. No cache
  static
  void NullXFORM(_cmsTRANSFORM* p,
                 const void* in,
-@@ -436,7 +436,7 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
+@@ -442,7 +442,7 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
          p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
  }
  
--// Gamut check, No cach<E9>, 16 bits.
+-// Gamut check, No caché, 16 bits.
 +// Gamut check, No cache, 16 bits.
  static
  void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
                                    const void* in,
-@@ -473,7 +473,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
+@@ -481,7 +481,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
  }
  
  
--// No gamut check, Cach<E9>, 16 bits,
+-// No gamut check, Caché, 16 bits,
 +// No gamut check, Cache, 16 bits,
  static
  void CachedXFORM(_cmsTRANSFORM* p,
                   const void* in,
-@@ -828,7 +828,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
+@@ -839,7 +839,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
              p ->xform = NullFloatXFORM;
          }
          else {
--            // Float transforms don't use cach<E9>, always are non-NULL
+-            // Float transforms don't use caché, always are non-NULL
 +            // Float transforms don't use cache, always are non-NULL
              p ->xform = FloatXFORM;
          }
  
-@@ -867,16 +867,16 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
+@@ -878,16 +878,16 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
              if (*dwFlags & cmsFLAGS_NOCACHE) {
  
                  if (*dwFlags & cmsFLAGS_GAMUTCHECK)
--                    p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no cach<E9>
+-                    p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no caché
 +                    p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no cache
                  else
--                    p ->xform = PrecalculatedXFORM;  // No cach<E9>, no gamut check
+-                    p ->xform = PrecalculatedXFORM;  // No caché, no gamut check
 +                    p ->xform = PrecalculatedXFORM;  // No cache, no gamut check
              }
              else {
  
                  if (*dwFlags & cmsFLAGS_GAMUTCHECK)
--                    p ->xform = CachedXFORMGamutCheck;    // Gamut check, cach<E9>
+-                    p ->xform = CachedXFORMGamutCheck;    // Gamut check, caché
 +                    p ->xform = CachedXFORMGamutCheck;    // Gamut check, cache
                  else
--                    p ->xform = CachedXFORM;  // No gamut check, cach<E9>
+-                    p ->xform = CachedXFORM;  // No gamut check, caché
 +                    p ->xform = CachedXFORM;  // No gamut check, cache
  
              }
diff --git a/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch b/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch
index eabf6a9..26f5938 100644
--- a/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch
+++ b/third_party/lcms/0008-infinite-loop-GrowNamedColorList.patch
@@ -1,20 +1,17 @@
 diff --git a/third_party/lcms/src/cmsnamed.c b/third_party/lcms/src/cmsnamed.c
-index 9b27ca0cc..9ed4cad39 100644
+index 42bd36530..9cfd2282f 100644
 --- a/third_party/lcms/src/cmsnamed.c
 +++ b/third_party/lcms/src/cmsnamed.c
-@@ -540,7 +540,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
-     v ->ContextID  = ContextID;
+@@ -546,7 +546,7 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
  
-     while (v -> Allocated < n){
--        if (!GrowNamedColorList(v)) return NULL;
-+        if (!GrowNamedColorList(v)) {
+     while (v -> Allocated < n) {
+         if (!GrowNamedColorList(v)) {
+-            _cmsFree(ContextID, (void*) v);
 +            cmsFreeNamedColorList(v);
-+            return NULL;
-+        }
+             return NULL;
+         }
      }
- 
-     strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
-@@ -571,7 +574,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
+@@ -579,7 +579,10 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
  
      // For really large tables we need this
      while (NewNC ->Allocated < v ->Allocated){
diff --git a/third_party/lcms/0009-uninit.patch b/third_party/lcms/0009-uninit.patch
deleted file mode 100644
index e9538c1..0000000
--- a/third_party/lcms/0009-uninit.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-npm@npm0:~/pdfium/pdfium/third_party/lcms$ git diff src/cmstypes.c
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index cb618600a..2a0ea9448 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -2966,7 +2966,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER
- {
-     cmsUInt32Number i, Count;
-     cmsNAMEDCOLORLIST* List;
--    char Name[34];
-+    char Name[33];
-     cmsUInt16Number PCS[3];
- 
- 
-@@ -2981,7 +2981,7 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER
-     for (i=0; i < Count; i++) {
- 
-         if (io ->Read(io, Name, 32, 1) != 1) goto Error;
--        Name[33] = 0;
-+        Name[32] = 0;
- 
-         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
- 
diff --git a/third_party/lcms/0010-memory-leak-Type_Curve_Read.patch b/third_party/lcms/0010-memory-leak-Type_Curve_Read.patch
deleted file mode 100644
index 7edc7f9..0000000
--- a/third_party/lcms/0010-memory-leak-Type_Curve_Read.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 06742b5..9fe5e2a 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -1112,7 +1112,10 @@ void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
-                NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
-                if (!NewGamma) return NULL;
- 
--               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
-+               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) {
-+                 cmsFreeToneCurve(NewGamma);
-+                 return NULL;
-+               }
- 
-                *nItems = 1;
-                return NewGamma;
-@@ -2350,7 +2353,10 @@ cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUI
- 
-         for (i=0; i < Data ->nEntries; i++) {
- 
--            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
-+            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) {
-+              cmsStageFree(CLUT);
-+              return NULL;
-+            }
-             Data ->Tab.T[i] = FROM_8_TO_16(v);
-         }
- 
diff --git a/third_party/lcms/0011-memory-leak-AllocEmptyTransform.patch b/third_party/lcms/0011-memory-leak-AllocEmptyTransform.patch
deleted file mode 100644
index 3325196..0000000
--- a/third_party/lcms/0011-memory-leak-AllocEmptyTransform.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-diff --git a/third_party/lcms/src/cmsxform.c b/third_party/lcms/src/cmsxform.c
-index 9c20c49b0..b3802f0d5 100644
---- a/third_party/lcms/src/cmsxform.c
-+++ b/third_party/lcms/src/cmsxform.c
-@@ -761,7 +761,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
- 
-        // Allocate needed memory
-        _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
--       if (!p) return NULL;
-+       if (!p) {
-+          cmsPipelineFree(lut);
-+          return NULL;
-+      }
- 
-        // Store the proposed pipeline
-        p->Lut = lut;
-@@ -819,7 +822,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
-         if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
- 
-             cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
--            _cmsFree(ContextID, p);
-+            cmsDeleteTransform(p);
-             return NULL;
-         }
- 
-@@ -849,7 +852,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
-             if (p ->FromInput == NULL || p ->ToOutput == NULL) {
- 
-                 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
--                _cmsFree(ContextID, p);
-+                cmsDeleteTransform(p);
-                 return NULL;
-             }
- 
diff --git a/third_party/lcms/0012-memory-leak-Type_NamedColor_Read.patch b/third_party/lcms/0012-memory-leak-Type_NamedColor_Read.patch
deleted file mode 100644
index ce9e1bf..0000000
--- a/third_party/lcms/0012-memory-leak-Type_NamedColor_Read.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 941107e1a..f2119ae0a 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -3105,7 +3105,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
- 
-     if (nDeviceCoords > cmsMAXCHANNELS) {
-         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
--        return 0;
-+        goto Error;
-     }
-     for (i=0; i < count; i++) {
- 
-@@ -3114,7 +3114,7 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
-         char Root[33];
- 
-         memset(Colorant, 0, sizeof(Colorant));
--        if (io -> Read(io, Root, 32, 1) != 1) return NULL;
-+        if (io -> Read(io, Root, 32, 1) != 1) goto Error;
-         Root[32] = 0;  // To prevent exploits
- 
-         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
diff --git a/third_party/lcms/0013-memory-leak-OptimizeByResampling.patch b/third_party/lcms/0013-memory-leak-OptimizeByResampling.patch
deleted file mode 100644
index 48645d1..0000000
--- a/third_party/lcms/0013-memory-leak-OptimizeByResampling.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
-index f885ef3..684910d 100644
---- a/third_party/lcms/src/cmsopt.c
-+++ b/third_party/lcms/src/cmsopt.c
-@@ -612,7 +612,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
- 
-     // Allocate the CLUT
-     CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL);
--    if (CLUT == NULL) return FALSE;
-+    if (CLUT == NULL) goto Error;
- 
-     // Add the CLUT to the destination LUT
-     if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
diff --git a/third_party/lcms/0014-memory-leak-Type_MPEmatrix_Read.patch b/third_party/lcms/0014-memory-leak-Type_MPEmatrix_Read.patch
deleted file mode 100644
index 8cc477f..0000000
--- a/third_party/lcms/0014-memory-leak-Type_MPEmatrix_Read.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 441d6bb..15199c7 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -4203,7 +4203,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
- 
-         cmsFloat32Number v;
- 
--        if (!_cmsReadFloat32Number(io, &v)) return NULL;
-+        if (!_cmsReadFloat32Number(io, &v)) {
-+            _cmsFree(self ->ContextID, Matrix);
-+            _cmsFree(self ->ContextID, Offsets);
-+            return NULL;
-+        }
-         Matrix[i] = v;
-     }
- 
-@@ -4212,7 +4216,11 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
- 
-         cmsFloat32Number v;
- 
--        if (!_cmsReadFloat32Number(io, &v)) return NULL;
-+        if (!_cmsReadFloat32Number(io, &v)) {
-+            _cmsFree(self ->ContextID, Matrix);
-+            _cmsFree(self ->ContextID, Offsets);
-+            return NULL;
-+        }
-         Offsets[i] = v;
-     }
- 
diff --git a/third_party/lcms/0015-cmsStageAllocMatrix-param-swap.patch b/third_party/lcms/0015-cmsStageAllocMatrix-param-swap.patch
deleted file mode 100644
index 04f8543..0000000
--- a/third_party/lcms/0015-cmsStageAllocMatrix-param-swap.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c
-index 73e6726..9b0eb4b 100644
---- a/third_party/lcms/src/cmslut.c
-+++ b/third_party/lcms/src/cmslut.c
-@@ -414,13 +414,13 @@ cmsStage*  CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number R
- 
-     if (Offset != NULL) {
- 
--        NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Cols, sizeof(cmsFloat64Number));
-+        NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Rows, sizeof(cmsFloat64Number));
-         if (NewElem->Offset == NULL) {
-            MatrixElemTypeFree(NewMPE);
-            return NULL;
-         }
- 
--        for (i=0; i < Cols; i++) {
-+        for (i=0; i < Rows; i++) {
-                 NewElem ->Offset[i] = Offset[i];
-         }
- 
diff --git a/third_party/lcms/0016-reject-nan.patch b/third_party/lcms/0016-reject-nan.patch
deleted file mode 100644
index c2b5068..0000000
--- a/third_party/lcms/0016-reject-nan.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/third_party/lcms/src/cmsplugin.c b/third_party/lcms/src/cmsplugin.c
-index 79b145d2d..29ddd9a49 100644
---- a/third_party/lcms/src/cmsplugin.c
-+++ b/third_party/lcms/src/cmsplugin.c
-@@ -179,6 +179,8 @@ cmsBool CMSEXPORT  _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
- 
-         tmp = _cmsAdjustEndianess32(tmp);
-         *n = *(cmsFloat32Number*) (void*) &tmp;
-+        if (isnan(*n))
-+            return FALSE;
-     }
-     return TRUE;
- }
diff --git a/third_party/lcms/0017-memory-leak-ReadSegmentedCurve.patch b/third_party/lcms/0017-memory-leak-ReadSegmentedCurve.patch
deleted file mode 100644
index 472bcad..0000000
--- a/third_party/lcms/0017-memory-leak-ReadSegmentedCurve.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 15199c7..04dd0c4 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -3968,7 +3968,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND
-             case cmsSigSampledCurveSeg: {
-                 cmsUInt32Number Count;
- 
--                if (!_cmsReadUInt32Number(io, &Count)) return NULL;
-+                if (!_cmsReadUInt32Number(io, &Count)) goto Error;
- 
-                 Segments[i].nGridPoints = Count;
-                 Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number));
-@@ -3987,7 +3987,7 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND
-                 _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
-                 cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String);
-                 }
--                return NULL;
-+                goto Error;
- 
-          }
-      }
-@@ -4001,7 +4001,12 @@ cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHAND
-      return Curve;
- 
- Error:
--     if (Segments) _cmsFree(self ->ContextID, Segments);
-+     if (Segments) {
-+         for (i=0; i < nSegments; i++) {
-+             if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints);
-+         }
-+         _cmsFree(self ->ContextID, Segments);
-+     }
-      return NULL;
- }
- 
diff --git a/third_party/lcms/0018-backport-c0a98d86.patch b/third_party/lcms/0018-backport-c0a98d86.patch
deleted file mode 100644
index 34b5477..0000000
--- a/third_party/lcms/0018-backport-c0a98d86.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-diff --git a/third_party/lcms/src/cmsintrp.c b/third_party/lcms/src/cmsintrp.c
-index 5d5f35d..14c6856 100644
---- a/third_party/lcms/src/cmsintrp.c
-+++ b/third_party/lcms/src/cmsintrp.c
-@@ -215,7 +215,7 @@ void LinLerp1D(register const cmsUInt16Number Value[],
- // To prevent out of bounds indexing
- cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) 
- {
--    return v < 0.0f ? 0.0f : (v > 1.0f ? 1.0f : v);
-+    return ((v < 0.0f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v);
- }
- 
- // Floating-point version of 1D interpolation
-diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c
-index 5f9f08a..3ed730a 100644
---- a/third_party/lcms/src/cmsio0.c
-+++ b/third_party/lcms/src/cmsio0.c
-@@ -1475,6 +1475,17 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
-     // If the element is already in memory, return the pointer
-     if (Icc -> TagPtrs[n]) {
- 
-+        if (Icc->TagTypeHandlers[n] == NULL) goto Error;
-+
-+        // Sanity check
-+        BaseType = Icc->TagTypeHandlers[n]->Signature;
-+        if (BaseType == 0) goto Error;
-+
-+        TagDescriptor = _cmsGetTagDescriptor(Icc->ContextID, sig);
-+        if (TagDescriptor == NULL) goto Error;
-+
-+        if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error;
-+
-         if (Icc ->TagSaveAsRaw[n]) goto Error;  // We don't support read raw tags as cooked
- 
-         _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 04dd0c4..386439b 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -4297,8 +4297,12 @@ void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
- 
-     // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
-     nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;
--    for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i];
- 
-+    for (i = 0; i < nMaxGrids; i++) {
-+        if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
-+        GridPoints[i] = (cmsUInt32Number)Dimensions8[i];
-+    }
-+
-     // Allocate the true CLUT
-     mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
-     if (mpe == NULL) goto Error;
diff --git a/third_party/lcms/0019-utf8.patch b/third_party/lcms/0019-utf8.patch
index 351659d..11293c9 100644
--- a/third_party/lcms/0019-utf8.patch
+++ b/third_party/lcms/0019-utf8.patch
@@ -1,95 +1,95 @@
 diff --git a/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c
-index 6011fb201..d53360b1f 100644
+index 7df5bbc4d..49cfbbe8c 100644
 --- a/third_party/lcms/src/cmscgats.c
 +++ b/third_party/lcms/src/cmscgats.c
-@@ -255,7 +255,7 @@ static PROPERTY PredefinedProperties[] = {
-                                // needed.
+@@ -256,7 +256,7 @@ static PROPERTY PredefinedProperties[] = {
+                                                    // needed.
  
-         {"SAMPLE_BACKING",   WRITE_STRINGIFY},   // Identifies the backing material used behind the sample during
--                               // measurement. Allowed values are <93>black<94>, <93>white<94>, or {"na".
-+                               // measurement. Allowed values are "black" "white" or "na".
- 
-         {"CHISQ_DOF",        WRITE_STRINGIFY},   // Degrees of freedom associated with the Chi squared statistic
- 
+         {"SAMPLE_BACKING",   WRITE_STRINGIFY},     // Identifies the backing material used behind the sample during
+-                                                   // measurement. Allowed values are ?black?, ?white?, or {"na".
++                                                   // measurement. Allowed values are "black", "white", or {"na".
+                                                   
+         {"CHISQ_DOF",        WRITE_STRINGIFY},     // Degrees of freedom associated with the Chi squared statistic
+                                                    // below properties are new in recent specs:
 @@ -271,7 +271,7 @@ static PROPERTY PredefinedProperties[] = {
-                                // denote the use of filters such as none, D65, Red, Green or Blue.
+                                                    // denote the use of filters such as none, D65, Red, Green or Blue.
+                                                   
+        {"POLARIZATION",      WRITE_STRINGIFY},     // Identifies the use of a physical polarization filter during measurement. Allowed
+-                                                   // values are {"yes?, ?white?, ?none? or ?na?.
++                                                   // values are "yes", "white", "none" or "na".
  
-        {"POLARIZATION",      WRITE_STRINGIFY},   // Identifies the use of a physical polarization filter during measurement. Allowed
--                               // values are {"yes<94>, <93>white<94>, <93>none<94> or <93>na<94>.
-+                               // values are "yes" "white" "none" or "na".
- 
-        {"WEIGHTING_FUNCTION", WRITE_PAIR},   // Indicates such functions as: the CIE standard observer functions used in the
-                                // calculation of various data parameters (2 degree and 10 degree), CIE standard
+        {"WEIGHTING_FUNCTION", WRITE_PAIR},         // Indicates such functions as: the CIE standard observer functions used in the
+                                                    // calculation of various data parameters (2 degree and 10 degree), CIE standard
 diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 5647264a6..64845e263 100644
+index 6cb8d4be3..e95e6d910 100644
 --- a/third_party/lcms/src/cmstypes.c
 +++ b/third_party/lcms/src/cmstypes.c
-@@ -962,7 +962,7 @@ cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
+@@ -974,7 +974,7 @@ cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
      len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
  
      // 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 <93>aligned<94>). Because the Unicode language
-+    //(see clause 4.1 for the definition of 'aligned'. Because the Unicode language
+-    //(see clause 4.1 for the definition of ?aligned?). Because the Unicode language
++    //(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
-@@ -3066,10 +3066,10 @@ void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
+@@ -3091,10 +3091,10 @@ void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
  //The namedColor2Type is a count value and array of structures that provide color
  //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
  //device representation of the color are given. Both representations are 16-bit values.
--//The device representation corresponds to the header<92>s <93>color space of data<94> field.
--//This representation should be consistent with the <93>number of device components<94>
-+//The device representation corresponds to the header's 'color space of data' field.
-+//This representation should be consistent with the 'number of device components'
+-//The device representation corresponds to the header?s ?color space of data? field.
+-//This representation should be consistent with the ?number of device components?
++//The device representation corresponds to the header's "color space of data" field.
++//This representation should be consistent with the "number of device components"
  //field in the namedColor2Type. If this field is 0, device coordinates are not provided.
--//The PCS representation corresponds to the header<92>s PCS field. The PCS representation
+-//The PCS representation corresponds to the header?s PCS field. The PCS representation
 +//The PCS representation corresponds to the header's PCS field. The PCS representation
  //is always provided. Color names are fixed-length, 32-byte fields including null
  //termination. In order to maintain maximum portability, it is strongly recommended
  //that special characters of the 7-bit ASCII set not be used.
-@@ -3814,7 +3814,7 @@ void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
+@@ -3839,7 +3839,7 @@ void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
  // ********************************************************************************
  //
  //This type represents a set of viewing condition parameters including:
--//CIE <92>absolute<92> illuminant white point tristimulus values and CIE <92>absolute<92>
-+//CIE 'absolute'illuminant white point tristimulus values and CIE 'absolute'
+-//CIE ?absolute? illuminant white point tristimulus values and CIE ?absolute?
++//CIE 'absolute' illuminant white point tristimulus values and CIE 'absolute'
  //surround tristimulus values.
  
  static
-@@ -3901,7 +3901,7 @@ void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
+@@ -3926,7 +3926,7 @@ void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
  }
  
  // Each curve is stored in one or more curve segments, with break-points specified between curve segments.
--// The first curve segment always starts at <96>Infinity, and the last curve segment always ends at +Infinity. The
+-// The first curve segment always starts at ?Infinity, and the last curve segment always ends at +Infinity. The
 +// The first curve segment always starts at -Infinity, and the last curve segment always ends at +Infinity. The
  // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
  // specified either in terms of a formula, or by a sampled curve.
  
 diff --git a/third_party/lcms/src/cmsvirt.c b/third_party/lcms/src/cmsvirt.c
-index b8795be2c..9eff1f7be 100644
+index 19e0cafb1..935effc66 100644
 --- a/third_party/lcms/src/cmsvirt.c
 +++ b/third_party/lcms/src/cmsvirt.c
 @@ -612,18 +612,18 @@ cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void)
  
  //sRGB Curves are defined by:
  //
--//If  R<92>sRGB,G<92>sRGB, B<92>sRGB < 0.04045
+-//If  R?sRGB,G?sRGB, B?sRGB < 0.04045
 +//If  R'sRGB,G'sRGB, B'sRGB < 0.04045
  //
--//    R =  R<92>sRGB / 12.92
--//    G =  G<92>sRGB / 12.92
--//    B =  B<92>sRGB / 12.92
+-//    R =  R?sRGB / 12.92
+-//    G =  G?sRGB / 12.92
+-//    B =  B?sRGB / 12.92
 +//    R =  R'sRGB / 12.92
 +//    G =  G'sRGB / 12.92
 +//    B =  B'sRGB / 12.92
  //
  //
--//else if  R<92>sRGB,G<92>sRGB, B<92>sRGB >= 0.04045
+-//else if  R?sRGB,G?sRGB, B?sRGB >= 0.04045
 +//else if  R'sRGB,G'sRGB, B'sRGB >= 0.04045
  //
--//    R = ((R<92>sRGB + 0.055) / 1.055)^2.4
--//    G = ((G<92>sRGB + 0.055) / 1.055)^2.4
--//    B = ((B<92>sRGB + 0.055) / 1.055)^2.4
+-//    R = ((R?sRGB + 0.055) / 1.055)^2.4
+-//    G = ((G?sRGB + 0.055) / 1.055)^2.4
+-//    B = ((B?sRGB + 0.055) / 1.055)^2.4
 +//    R = ((R'sRGB + 0.055) / 1.055)^2.4
 +//    G = ((G'sRGB + 0.055) / 1.055)^2.4
 +//    B = ((B'sRGB + 0.055) / 1.055)^2.4
diff --git a/third_party/lcms/0020-avoid-fixed-inf.patch b/third_party/lcms/0020-avoid-fixed-inf.patch
deleted file mode 100644
index b2397d7..0000000
--- a/third_party/lcms/0020-avoid-fixed-inf.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
-index e4a7e4521..23aa54402 100644
---- a/third_party/lcms/src/cmsopt.c
-+++ b/third_party/lcms/src/cmsopt.c
-@@ -1546,7 +1546,7 @@ void MatShaperEval16(register const cmsUInt16Number In[],
- 
- // This table converts from 8 bits to 1.14 after applying the curve
- static
--void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
-+cmsBool FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
- {
-     int i;
-     cmsFloat32Number R, y;
-@@ -1555,14 +1555,17 @@ void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
- 
-         R   = (cmsFloat32Number) (i / 255.0);
-         y   = cmsEvalToneCurveFloat(Curve, R);
-+        if (isinf(y))
-+            return FALSE;
- 
-         Table[i] = DOUBLE_TO_1FIXED14(y);
-     }
-+    return TRUE;
- }
- 
- // This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve
- static
--void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput)
-+cmsBool FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput)
- {
-     int i;
-     cmsFloat32Number R, Val;
-@@ -1571,6 +1574,8 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi
- 
-         R   = (cmsFloat32Number) (i / 16384.0);
-         Val = cmsEvalToneCurveFloat(Curve, R);    // Val comes 0..1.0
-+        if (isinf(Val))
-+            return FALSE;
- 
-         if (Is8BitsOutput) {
- 
-@@ -1585,6 +1590,7 @@ void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8Bi
-         }
-         else Table[i]  = _cmsQuickSaturateWord(Val * 65535.0);
-     }
-+    return TRUE;
- }
- 
- // Compute the matrix-shaper structure
-@@ -1602,13 +1608,19 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c
-     p -> ContextID = Dest -> ContextID;
- 
-     // Precompute tables
--    FillFirstShaper(p ->Shaper1R, Curve1[0]);
--    FillFirstShaper(p ->Shaper1G, Curve1[1]);
--    FillFirstShaper(p ->Shaper1B, Curve1[2]);
-+    if (!FillFirstShaper(p ->Shaper1R, Curve1[0]))
-+        goto Error;
-+    if (!FillFirstShaper(p ->Shaper1G, Curve1[1]))
-+        goto Error;
-+    if (!FillFirstShaper(p ->Shaper1B, Curve1[2]))
-+        goto Error;
- 
--    FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits);
--    FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits);
--    FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits);
-+    if (!FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits))
-+        goto Error;
-+    if (!FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits))
-+        goto Error;
-+    if (!FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits))
-+        goto Error;
- 
-     // Convert matrix to nFixed14. Note that those values may take more than 16 bits as
-     for (i=0; i < 3; i++) {
-@@ -1634,6 +1646,9 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c
-     // Fill function pointers
-     _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper);
-     return TRUE;
-+    Error:
-+        _cmsFree(Dest->ContextID, p);
-+        return FALSE;
- }
- 
- //  8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast!
-@@ -1746,7 +1761,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
-         *dwFlags |= cmsFLAGS_NOCACHE;
- 
-         // Setup the optimizarion routines
--        SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
-+        if (!SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat))
-+            goto Error;
-     }
- 
-     cmsPipelineFree(Src);
diff --git a/third_party/lcms/0021-sanitize-float-read.patch b/third_party/lcms/0021-sanitize-float-read.patch
deleted file mode 100644
index 568fd0e..0000000
--- a/third_party/lcms/0021-sanitize-float-read.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-diff --git a/third_party/lcms/src/cmsplugin.c b/third_party/lcms/src/cmsplugin.c
-index b95befb..4ba998b 100644
---- a/third_party/lcms/src/cmsplugin.c
-+++ b/third_party/lcms/src/cmsplugin.c
-@@ -182,7 +182,9 @@ cmsBool CMSEXPORT  _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
-         if (isnan(*n))
-             return FALSE;
-     }
--    return TRUE;
-+
-+    // fpclassify() required by C99
-+    return (fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL);
- }
- 
- 
diff --git a/third_party/lcms/0022-check-LUT-and-MPE.patch b/third_party/lcms/0022-check-LUT-and-MPE.patch
deleted file mode 100644
index 04ddac8..0000000
--- a/third_party/lcms/0022-check-LUT-and-MPE.patch
+++ /dev/null
@@ -1,170 +0,0 @@
-diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c
-index 9b0eb4b54..19d43361f 100644
---- a/third_party/lcms/src/cmslut.c
-+++ b/third_party/lcms/src/cmslut.c
-@@ -1255,21 +1255,39 @@ cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe)
- // ***********************************************************************************************************
- 
- // This function sets up the channel count
--
- static
--void BlessLUT(cmsPipeline* lut)
-+cmsBool BlessLUT(cmsPipeline* lut)
- {
-     // We can set the input/ouput channels only if we have elements.
-     if (lut ->Elements != NULL) {
- 
--        cmsStage *First, *Last;
-+        cmsStage* prev;
-+        cmsStage* next;
-+        cmsStage* First;
-+        cmsStage* Last;
- 
-         First  = cmsPipelineGetPtrToFirstStage(lut);
-         Last   = cmsPipelineGetPtrToLastStage(lut);
- 
--        if (First != NULL)lut ->InputChannels = First ->InputChannels;
--        if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels;
-+        if (First == NULL || Last == NULL) return FALSE;
-+
-+        lut->InputChannels = First->InputChannels;
-+        lut->OutputChannels = Last->OutputChannels;
-+
-+        // Check chain consistency
-+        prev = First;
-+        next = prev->Next;
-+
-+        while (next != NULL)
-+        {
-+            if (next->InputChannels != prev->OutputChannels)
-+                return FALSE;
-+
-+            next = next->Next;
-+            prev = prev->Next;
-+        }
-     }
-+    return TRUE;
- }
- 
- 
-@@ -1331,6 +1349,7 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In
- {
-        cmsPipeline* NewLUT;
- 
-+       // A value of zero in channels is allowed as placeholder
-        if (InputChannels >= cmsMAXCHANNELS ||
-            OutputChannels >= cmsMAXCHANNELS) return NULL;
- 
-@@ -1348,7 +1367,11 @@ cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number In
-        NewLUT ->Data        = NewLUT;
-        NewLUT ->ContextID   = ContextID;
- 
--       BlessLUT(NewLUT);
-+       if (!BlessLUT(NewLUT))
-+       {
-+           _cmsFree(ContextID, NewLUT);
-+           return NULL;
-+       }
- 
-        return NewLUT;
- }
-@@ -1454,7 +1477,12 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut)
- 
-     NewLUT ->SaveAs8Bits    = lut ->SaveAs8Bits;
- 
--    BlessLUT(NewLUT);
-+    if (!BlessLUT(NewLUT))
-+    {
-+        _cmsFree(lut->ContextID, NewLUT);
-+        return NULL;
-+    }
-+
-     return NewLUT;
- }
- 
-@@ -1491,8 +1519,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage
-             return FALSE;
-     }
- 
--    BlessLUT(lut);
--    return TRUE;
-+    return BlessLUT(lut);
- }
- 
- // Unlink an element and return the pointer to it
-@@ -1547,6 +1574,7 @@ void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStag
-     else
-         cmsStageFree(Unlinked);
- 
-+    // May fail, but we ignore it
-     BlessLUT(lut);
- }
- 
-@@ -1573,8 +1601,7 @@ cmsBool  CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
-                 return FALSE;
-     }
- 
--    BlessLUT(l1);
--    return TRUE;
-+    return BlessLUT(l1);
- }
- 
- 
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index e5ed06c33..0256e247b 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -1755,8 +1755,8 @@ void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cms
-     if (!_cmsReadUInt8Number(io, NULL)) goto Error;
- 
-     // Do some checking
--    if (InputChannels > cmsMAXCHANNELS)  goto Error;
--    if (OutputChannels > cmsMAXCHANNELS) goto Error;
-+    if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS)  goto Error;
-+    if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error;
- 
-    // Allocates an empty Pipeline
-     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
-@@ -2048,8 +2048,8 @@ void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cm
-     if (!_cmsReadUInt8Number(io, NULL)) return NULL;
- 
-     // Do some checking
--    if (InputChannels > cmsMAXCHANNELS)  goto Error;
--    if (OutputChannels > cmsMAXCHANNELS) goto Error;
-+    if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS)  goto Error;
-+    if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error;
- 
-     // Allocates an empty LUT
-     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
-@@ -2486,7 +2486,10 @@ void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c
-     if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
-     if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;
- 
--   // Allocates an empty LUT
-+    if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL;
-+    if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL;
-+
-+    // Allocates an empty LUT
-     NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
-     if (NewLUT == NULL) return NULL;
- 
-@@ -2794,6 +2797,9 @@ void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, c
-     if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
-     if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;
- 
-+    if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL;
-+    if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL;
-+
-     // Padding
-     if (!_cmsReadUInt16Number(io, NULL)) return NULL;
- 
-@@ -4443,6 +4449,9 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU
-     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
-     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
- 
-+    if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) return NULL;
-+    if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) return NULL;
-+
-     // Allocates an empty LUT
-     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
-     if (NewLUT == NULL) return NULL;
diff --git a/third_party/lcms/0023-upstream-integer-overflow-MPEmatrix_Read.patch b/third_party/lcms/0023-upstream-integer-overflow-MPEmatrix_Read.patch
deleted file mode 100644
index 70a6bb9..0000000
--- a/third_party/lcms/0023-upstream-integer-overflow-MPEmatrix_Read.patch
+++ /dev/null
@@ -1,85 +0,0 @@
-diff --git a/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c
-index 5720c66a7..cce4cedba 100644
---- a/third_party/lcms/src/cmscgats.c
-+++ b/third_party/lcms/src/cmscgats.c
-@@ -150,23 +150,24 @@ typedef struct {
-         SUBALLOCATOR   Allocator;             // String suballocator -- just to keep it fast
- 
-         // Parser state machine
--        SYMBOL         sy;                    // Current symbol
--        int            ch;                    // Current character
-+        SYMBOL             sy;                // Current symbol
-+        int                ch;                // Current character
-+
-+        cmsInt32Number     inum;              // integer value
-+        cmsFloat64Number   dnum;              // real value
- 
--        int            inum;                  // integer value
--        cmsFloat64Number         dnum;                  // real value
-         char           id[MAXID];             // identifier
-         char           str[MAXSTR];           // string
- 
-         // Allowed keywords & datasets. They have visibility on whole stream
--        KEYVALUE*     ValidKeywords;
--        KEYVALUE*     ValidSampleID;
-+        KEYVALUE*      ValidKeywords;
-+        KEYVALUE*      ValidSampleID;
- 
-         char*          Source;                // Points to loc. being parsed
--        int            lineno;                // line counter for error reporting
-+        cmsInt32Number lineno;                // line counter for error reporting
- 
-         FILECTX*       FileStack[MAXINCLUDE]; // Stack of files being parsed
--        int            IncludeSP;             // Include Stack Pointer
-+        cmsInt32Number IncludeSP;             // Include Stack Pointer
- 
-         char*          MemoryBlock;           // The stream if holded in memory
- 
-@@ -568,8 +569,8 @@ void ReadReal(cmsIT8* it8, int inum)
-     // Exponent, example 34.00E+20
-     if (toupper(it8->ch) == 'E') {
- 
--        int e;
--        int sgn;
-+        cmsInt32Number e;
-+        cmsInt32Number sgn;
- 
-         NextCh(it8); sgn = 1;
- 
-@@ -587,7 +588,7 @@ void ReadReal(cmsIT8* it8, int inum)
-             e = 0;
-             while (isdigit(it8->ch)) {
- 
--                if ((cmsFloat64Number) e * 10L < INT_MAX)
-+                if ((cmsFloat64Number) e * 10L < (cmsFloat64Number) +2147483647.0)
-                     e = e * 10 + (it8->ch - '0');
- 
-                 NextCh(it8);
-@@ -777,7 +778,7 @@ void InSymbol(cmsIT8* it8)
- 
-                 while (isdigit(it8->ch)) {
- 
--                    if ((long) it8->inum * 10L > (long) INT_MAX) {
-+                    if ((cmsFloat64Number) it8->inum * 10L > (cmsFloat64Number) +2147483647.0) {
-                         ReadReal(it8, it8->inum);
-                         it8->sy = SDNUM;
-                         it8->dnum *= sign;
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 0256e247b..75f1fae32 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -4199,9 +4199,13 @@ void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io
-     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
- 
- 
-+    // Input and output chans may be ANY (up to 0xffff), 
-+    // but we choose to limit to 16 channels for now
-+    if (InputChans >= cmsMAXCHANNELS) return NULL;
-+    if (OutputChans >= cmsMAXCHANNELS) return NULL;
-+
-     nElems = InputChans * OutputChans;
- 
--    // Input and output chans may be ANY (up to 0xffff)
-     Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number));
-     if (Matrix == NULL) return NULL;
- 
diff --git a/third_party/lcms/0024-verify-size-before-reading.patch b/third_party/lcms/0024-verify-size-before-reading.patch
deleted file mode 100644
index e72e310..0000000
--- a/third_party/lcms/0024-verify-size-before-reading.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 75f1fae32..4d96a1ed6 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -173,6 +173,12 @@ cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
- {
-     cmsUInt32Number i;
-     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
-+    cmsUInt32Number currentPosition;
-+
-+    currentPosition = io->Tell(io);
-+    // Verify there is enough space left to read two cmsUInt32Number items for Count items.
-+    if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count)
-+        return FALSE;
- 
-     // Let's take the offsets to each element
-     ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
diff --git a/third_party/lcms/0025-upstream-direct-leak-Type_MPE_Read.patch b/third_party/lcms/0025-upstream-direct-leak-Type_MPE_Read.patch
deleted file mode 100644
index 3393331..0000000
--- a/third_party/lcms/0025-upstream-direct-leak-Type_MPE_Read.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 75f1fae32..f92a92822 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -4460,18 +4460,19 @@ void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsU
-     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
-     if (NewLUT == NULL) return NULL;
- 
--    if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL;
--
--    if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) {
--        if (NewLUT != NULL) cmsPipelineFree(NewLUT);
--        *nItems = 0;
--        return NULL;
--    }
-+    if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error;
-+    if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error;
- 
-     // Success
-     *nItems = 1;
-     return NewLUT;
- 
-+    // Error
-+Error:
-+    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
-+    *nItems = 0;
-+    return NULL;
-+
-     cmsUNUSED_PARAMETER(SizeOfTag);
- }
- 
diff --git a/third_party/lcms/0026-more-unsupported-characters.patch b/third_party/lcms/0026-more-unsupported-characters.patch
index a66d50c..66e9239 100644
--- a/third_party/lcms/0026-more-unsupported-characters.patch
+++ b/third_party/lcms/0026-more-unsupported-characters.patch
@@ -1,72 +1,40 @@
 diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
-index 23aa54402..abe26b93a 100644
+index f838b6eb7..5ea1b4c85 100644
 --- a/third_party/lcms/src/cmsopt.c
 +++ b/third_party/lcms/src/cmsopt.c
-@@ -1756,8 +1756,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
+@@ -1764,8 +1764,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
          _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1);
          _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);
  
--        // In this particular optimization, cach<E9> does not help as it takes more time to deal with
--        // the cach<E9> that with the pixel handling
+-        // In this particular optimization, caché does not help as it takes more time to deal with
+-        // the caché that with the pixel handling
 +        // In this particular optimization, cache does not help as it takes more time to deal with
 +        // the cache that with the pixel handling
          *dwFlags |= cmsFLAGS_NOCACHE;
  
          // Setup the optimizarion routines
 diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 38091f159..5ea1d2d87 100644
+index e95e6d910..0c24da162 100644
 --- a/third_party/lcms/src/cmstypes.c
 +++ b/third_party/lcms/src/cmstypes.c
-@@ -4194,7 +4194,7 @@ cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER*
+@@ -4207,7 +4207,7 @@ cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER*
  // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
  // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
  // is organized as follows:
--// array = [e11, e12, <85>, e1P, e21, e22, <85>, e2P, <85>, eQ1, eQ2, <85>, eQP, e1, e2, <85>, eQ]
+-// array = [e11, e12, …, e1P, e21, e22, …, e2P, …, eQ1, eQ2, …, eQP, e1, e2, …, eQ]
 +// array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ]
  
  static
  void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
-npm@npm0:~/pdfium/pdfium$ 
-npm@npm0:~/pdfium/pdfium$ 
-npm@npm0:~/pdfium/pdfium$ 
-npm@npm0:~/pdfium/pdfium$ git diff
-diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
-index 23aa54402..abe26b93a 100644
---- a/third_party/lcms/src/cmsopt.c
-+++ b/third_party/lcms/src/cmsopt.c
-@@ -1756,8 +1756,8 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
-         _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1);
-         _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);
- 
--        // In this particular optimization, cach<E9> does not help as it takes more time to deal with
--        // the cach<E9> that with the pixel handling
-+        // In this particular optimization, cache does not help as it takes more time to deal with
-+        // the cache that with the pixel handling
-         *dwFlags |= cmsFLAGS_NOCACHE;
- 
-         // Setup the optimizarion routines
-diff --git a/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
-index 38091f159..8b02f86ca 100644
---- a/third_party/lcms/src/cmstypes.c
-+++ b/third_party/lcms/src/cmstypes.c
-@@ -4194,7 +4194,7 @@ cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER*
- // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
- // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
- // is organized as follows:
--// array = [e11, e12, <85>, e1P, e21, e22, <85>, e2P, <85>, eQ1, eQ2, <85>, eQP, e1, e2, <85>, eQ]
-+// array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ]
- 
- static
- void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
-@@ -4713,10 +4713,10 @@ void *Type_vcgt_Read(struct _cms_typehandler_struct* self,
+@@ -4730,10 +4730,10 @@ void *Type_vcgt_Read(struct _cms_typehandler_struct* self,
              // Y = cX + f             | X < d
  
              // vcgt formula is:
--            // Y = (Max <96> Min) * (X ^ Gamma) + Min
+-            // Y = (Max – Min) * (X ^ Gamma) + Min
 +            // Y = (Max - Min) * (X ^ Gamma) + Min
  
              // So, the translation is
--            // a = (Max <96> Min) ^ ( 1 / Gamma)
+-            // a = (Max – Min) ^ ( 1 / Gamma)
 +            // a = (Max - Min) ^ ( 1 / Gamma)
              // e = Min
              // b=c=d=f=0
diff --git a/third_party/lcms/0030-const-data.patch b/third_party/lcms/0030-const-data.patch
index 6a80679..dc8e37c 100644
--- a/third_party/lcms/0030-const-data.patch
+++ b/third_party/lcms/0030-const-data.patch
@@ -112,92 +112,3 @@
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
  0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-diff --git a/third_party/lcms/src/cmspack.c b/third_party/lcms/src/cmspack.c
-index 6ed41da87..e711ece5e 100644
---- a/third_party/lcms/src/cmspack.c
-+++ b/third_party/lcms/src/cmspack.c
-@@ -2907,7 +2907,7 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,
- // ----------------------------------------------------------------------------------------------------------------
- 
- 
--static cmsFormatters16 InputFormatters16[] = {
-+static const cmsFormatters16 InputFormatters16[] = {
- 
-     //    Type                                          Mask                  Function
-     //  ----------------------------   ------------------------------------  ----------------------------
-@@ -2978,7 +2978,7 @@ static cmsFormatters16 InputFormatters16[] = {
- 
- 
- 
--static cmsFormattersFloat InputFormattersFloat[] = {
-+static const cmsFormattersFloat InputFormattersFloat[] = {
- 
-     //    Type                                          Mask                  Function
-     //  ----------------------------   ------------------------------------  ----------------------------
-@@ -3011,7 +3011,7 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number
- 
-     case CMS_PACK_FLAGS_16BITS: {
-         for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {
--            cmsFormatters16* f = InputFormatters16 + i;
-+            const cmsFormatters16* f = InputFormatters16 + i;
- 
-             if ((dwInput & ~f ->Mask) == f ->Type) {
-                 fr.Fmt16 = f ->Frm;
-@@ -3023,7 +3023,7 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number
- 
-     case CMS_PACK_FLAGS_FLOAT: {
-         for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
--            cmsFormattersFloat* f = InputFormattersFloat + i;
-+            const cmsFormattersFloat* f = InputFormattersFloat + i;
- 
-             if ((dwInput & ~f ->Mask) == f ->Type) {
-                 fr.FmtFloat = f ->Frm;
-@@ -3041,7 +3041,7 @@ cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number
-     return fr;
- }
- 
--static cmsFormatters16 OutputFormatters16[] = {
-+static const cmsFormatters16 OutputFormatters16[] = {
-     //    Type                                          Mask                  Function
-     //  ----------------------------   ------------------------------------  ----------------------------
- 
-@@ -3129,7 +3129,7 @@ static cmsFormatters16 OutputFormatters16[] = {
- };
- 
- 
--static cmsFormattersFloat OutputFormattersFloat[] = {
-+static const cmsFormattersFloat OutputFormattersFloat[] = {
-     //    Type                                          Mask                                 Function
-     //  ----------------------------   ---------------------------------------------------  ----------------------------
-     {     TYPE_Lab_FLT,                                                ANYPLANAR|ANYEXTRA,   PackLabFloatFromFloat},
-@@ -3168,7 +3168,7 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe
-      case CMS_PACK_FLAGS_16BITS: {
- 
-         for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {
--            cmsFormatters16* f = OutputFormatters16 + i;
-+            const cmsFormatters16* f = OutputFormatters16 + i;
- 
-             if ((dwInput & ~f ->Mask) == f ->Type) {
-                 fr.Fmt16 = f ->Frm;
-@@ -3181,7 +3181,7 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe
-     case CMS_PACK_FLAGS_FLOAT: {
- 
-         for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
--            cmsFormattersFloat* f = OutputFormattersFloat + i;
-+            const cmsFormattersFloat* f = OutputFormattersFloat + i;
- 
-             if ((dwInput & ~f ->Mask) == f ->Type) {
-                 fr.FmtFloat = f ->Frm;
-diff --git a/third_party/lcms/src/cmswtpnt.c b/third_party/lcms/src/cmswtpnt.c
-index c6b612584..6df2321de 100644
---- a/third_party/lcms/src/cmswtpnt.c
-+++ b/third_party/lcms/src/cmswtpnt.c
-@@ -102,7 +102,7 @@ typedef struct {
- 
-     } ISOTEMPERATURE;
- 
--static ISOTEMPERATURE isotempdata[] = {
-+static const ISOTEMPERATURE isotempdata[] = {
- //  {Mirek, Ut,       Vt,      Tt      }
-     {0,     0.18006,  0.26352,  -0.24341},
-     {10,    0.18066,  0.26589,  -0.25479},
diff --git a/third_party/lcms/README.pdfium b/third_party/lcms/README.pdfium
index 1a096c8..ca78f0a 100644
--- a/third_party/lcms/README.pdfium
+++ b/third_party/lcms/README.pdfium
@@ -1,6 +1,6 @@
 Name: Little CMS
 URL: http://www.littlecms.com/
-Version: 2.8
+Version: 2.9
 Security Critical: yes
 License: MIT License
 
@@ -17,26 +17,7 @@
 0005-old-fix-e-with-tilde.patch: like https://codereview.chromium.org/2411123003/ but better.
 0006-tag-type-confusion.patch: Fix a type confusion.
 0008-infinite-loop-GrowNamedColorList.patch: Fix infinite loop when calling GrowNamedColorList.
-0009-uninit.patch: Fix use uninitialized value and stack buffer overflow read.
-0010-memory-leak-Type_Curve_Read.patch: Fix memory leak in Type_Curve_Read.
-0011-memory-leak-AllocEmptyTransform.patch: Fix memory leak in AllocEmptyTransform.
-0012-memory-leak-Type_NamedColor_Read.patch: Fix memory leak in Type_NamedColor_Read.
-0013-memory-leak-OptimizeByResampling.patch: Fix memory leak in OptimizeByResampling.
-0014-memory-leak-Type_MPEmatrix_Read.patch: Fix memory leak in MPEmatrix_Read.
-0015-cmsStageAllocMatrix-param-swap.patch: Fix rows/cols swap in cmsStageAllocMatrix.
-0016-reject-nan.patch: Reject NaN when reading float numbers.
-0017-memory-leak-ReadSegmentedCurve.patch: Fix memory leak in ReadSegmentedCurve.
-0018-backport-c0a98d86.patch: Fix several issues. Backport from upstream
-    https://github.com/mm2/Little-CMS/commit/c0a98d86
 0019-utf8.patch: Encode source files as utf-8.
-0020-avoid-fixed-inf.patch: Avoid fixed number LUT optimization on inf values.
-0021-sanitize-float-read.patch: Sanitize floating point read. Partially backport
-    from upstream https://github.com/mm2/Little-CMS/commit/4011a6e3
-0022-check-LUT-and-MPE.patch: check LUT consistency and sanitize MPE profiles.
-0023-upstream-integer-overflow-MPEmatrix_Read.patch: fix some integer overflows.
-0024-verify-size-before-reading.patch: fix OOM issue when there won't be enough
-    data to read anyway.
-0025-upstream-direct-leak-Type_MPE_Read.patch: fix leak in cmstypes.c.
 0026-more-unsupported-characters.patch: remove other unsupported characters.
 0027-changes-from-beginning-of-time.patch: commented changes from initial commit.
 0028-do-not-quickfloor.patch: flooring errors may cause heap-buffer-overflow.
diff --git a/third_party/lcms/include/lcms2.h b/third_party/lcms/include/lcms2.h
index 2bf6f24..7653f8e 100644
--- a/third_party/lcms/include/lcms2.h
+++ b/third_party/lcms/include/lcms2.h
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -23,7 +23,7 @@
 //
 //---------------------------------------------------------------------------------
 //
-// Version 2.8
+// Version 2.9rc3
 //
 
 #ifndef _lcms2_H
@@ -38,7 +38,7 @@
 // #define CMS_DONT_USE_INT64        1
 
 // Uncomment this if your compiler doesn't work with fast floor function
-#define CMS_DONT_USE_FAST_FLOOR 1
+// #define CMS_DONT_USE_FAST_FLOOR 1
 
 // Uncomment this line if you want lcms to use the black point tag in profile,
 // if commented, lcms will compute the black point by its own.
@@ -49,7 +49,7 @@
 // #define CMS_USE_CPP_API
 
 // Uncomment this line if you need strict CGATS syntax. Makes CGATS files to
-// require "KEYWORD" on undefined identifiers, keep it comented out unless needed
+// require "KEYWORD" on undefined identifiers, keep it commented out unless needed
 // #define CMS_STRICT_CGATS  1
 
 // Uncomment to get rid of the tables for "half" float support
@@ -58,6 +58,9 @@
 // Uncomment to get rid of pthreads/windows dependency
 // #define CMS_NO_PTHREADS  1
 
+// Uncomment this for special windows mutex initialization (see lcms2_internal.h)
+// #define CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
+
 // ********** End of configuration toggles ******************************
 
 // Needed for streams
@@ -75,7 +78,7 @@
 #endif
 
 // Version/release
-#define LCMS_VERSION        2080
+#define LCMS_VERSION        2090
 
 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
 #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -225,16 +228,21 @@
 #            define CMSAPI    __declspec(dllexport)
 #        else
 #           define CMSAPI     __declspec(dllimport)
-#       endif
+#        endif
 #     endif
 #  else
-#       define CMSEXPORT
-#       define CMSAPI
+#     define CMSEXPORT
+#     define CMSAPI
 #  endif
-#else
-# define CMSEXPORT
-# define CMSAPI
-#endif
+#else  // not Windows
+#  ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
+#     define CMSEXPORT
+#     define CMSAPI    __attribute__((visibility("default")))
+#  else
+#     define CMSEXPORT
+#     define CMSAPI
+#  endif
+#endif  // CMS_IS_WINDOWS_
 
 #ifdef HasTHREADS
 # if HasTHREADS == 1
@@ -255,9 +263,9 @@
 #endif
 
 // D50 XYZ normalized to Y=1.0
-#define cmsD50X             0.9642
-#define cmsD50Y             1.0
-#define cmsD50Z             0.8249
+#define cmsD50X  0.9642
+#define cmsD50Y  1.0
+#define cmsD50Z  0.8249
 
 // V4 perceptual black
 #define cmsPERCEPTUAL_BLACK_X  0.00336
@@ -265,8 +273,8 @@
 #define cmsPERCEPTUAL_BLACK_Z  0.00287
 
 // Definitions in ICC spec
-#define cmsMagicNumber      0x61637370     // 'acsp'
-#define lcmsSignature       0x6c636d73     // 'lcms'
+#define cmsMagicNumber  0x61637370     // 'acsp'
+#define lcmsSignature   0x6c636d73     // 'lcms'
 
 
 // Base ICC type definitions
@@ -1125,7 +1133,7 @@
     cmsCIEXYZ        whitePoint;
     cmsFloat64Number Yb;
     cmsFloat64Number La;
-    int              surround;
+    cmsUInt32Number  surround;
     cmsFloat64Number D_value;
 
     } cmsViewingConditions;
@@ -1153,16 +1161,16 @@
 // The internal representation is none of your business.
 typedef struct _cms_curve_struct cmsToneCurve;
 
-CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, cmsInt32Number nSegments, const cmsCurveSegment Segments[]);
+CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, cmsUInt32Number nSegments, const cmsCurveSegment Segments[]);
 CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[]);
 CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma);
-CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number values[]);
+CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsUInt32Number nEntries, const cmsUInt16Number values[]);
 CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[]);
 CMSAPI void              CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve);
 CMSAPI void              CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]);
 CMSAPI cmsToneCurve*     CMSEXPORT cmsDupToneCurve(const cmsToneCurve* Src);
 CMSAPI cmsToneCurve*     CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma);
-CMSAPI cmsToneCurve*     CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InGamma);
+CMSAPI cmsToneCurve*     CMSEXPORT cmsReverseToneCurveEx(cmsUInt32Number nResultSamples, const cmsToneCurve* InGamma);
 CMSAPI cmsToneCurve*     CMSEXPORT cmsJoinToneCurve(cmsContext ContextID, const cmsToneCurve* X,  const cmsToneCurve* Y, cmsUInt32Number nPoints);
 CMSAPI cmsBool           CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda);
 CMSAPI cmsFloat32Number  CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsFloat32Number v);
@@ -1207,7 +1215,7 @@
 // Where to place/locate the stages in the pipeline chain
 typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc;
 
-CMSAPI int               CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
+CMSAPI cmsBool           CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
 CMSAPI void              CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe);
 
 // This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements
@@ -1430,7 +1438,7 @@
 CMSAPI cmsTagSignature   CMSEXPORT cmsTagLinkedTo(cmsHPROFILE hProfile, cmsTagSignature sig);
 
 // Read and write raw data
-CMSAPI cmsInt32Number    CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* Buffer, cmsUInt32Number BufferSize);
+CMSAPI cmsUInt32Number   CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* Buffer, cmsUInt32Number BufferSize);
 CMSAPI cmsBool           CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size);
 
 // Access header data
@@ -1521,7 +1529,7 @@
 
 CMSAPI cmsBool           CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile);
 
-// Profile high level funtions ------------------------------------------------------------------------------------------
+// Profile high level functions ------------------------------------------------------------------------------------------
 
 CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess);
 CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *ICCProfile, const char *sAccess);
@@ -1581,21 +1589,21 @@
 CMSAPI cmsHPROFILE      CMSEXPORT cmsCreate_sRGBProfile(void);
 
 CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
-                                                             int nLUTPoints,
+                                                             cmsUInt32Number nLUTPoints,
                                                              cmsFloat64Number Bright,
                                                              cmsFloat64Number Contrast,
                                                              cmsFloat64Number Hue,
                                                              cmsFloat64Number Saturation,
-                                                             int TempSrc,
-                                                             int TempDest);
+                                                             cmsUInt32Number TempSrc,
+                                                             cmsUInt32Number TempDest);
 
-CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
+CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateBCHSWabstractProfile(cmsUInt32Number nLUTPoints,
                                                              cmsFloat64Number Bright,
                                                              cmsFloat64Number Contrast,
                                                              cmsFloat64Number Hue,
                                                              cmsFloat64Number Saturation,
-                                                             int TempSrc,
-                                                             int TempDest);
+                                                             cmsUInt32Number TempSrc,
+                                                             cmsUInt32Number TempDest);
 
 CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID);
 CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateNULLProfile(void);
@@ -1637,7 +1645,7 @@
 #define cmsFLAGS_BLACKPOINTCOMPENSATION   0x2000
 #define cmsFLAGS_NOWHITEONWHITEFIXUP      0x0004    // Don't fix scum dot
 #define cmsFLAGS_HIGHRESPRECALC           0x0400    // Use more memory to give better accurancy
-#define cmsFLAGS_LOWRESPRECALC            0x0800    // Use less memory to minimize resouces
+#define cmsFLAGS_LOWRESPRECALC            0x0800    // Use less memory to minimize resources
 
 // For devicelink creation
 #define cmsFLAGS_8BITS_DEVICELINK         0x0008   // Create 8 bits devicelinks
@@ -1807,7 +1815,7 @@
 
 // Persistence
 CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName);
-CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len);
+CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cmsUInt32Number len);
 // CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromIOhandler(cmsContext ContextID, cmsIOHANDLER* io);
 
 CMSAPI cmsBool          CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName);
diff --git a/third_party/lcms/include/lcms2_plugin.h b/third_party/lcms/include/lcms2_plugin.h
index 7eda009..17bec42 100644
--- a/third_party/lcms/include/lcms2_plugin.h
+++ b/third_party/lcms/include/lcms2_plugin.h
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -318,7 +318,7 @@
 
 // Parametric curves. A negative type means same function but analytically inverted. Max. number of params is 10
 
-// Evaluator callback for user-suplied parametric curves. May implement more than one type
+// Evaluator callback for user-supplied parametric curves. May implement more than one type
 typedef  cmsFloat64Number (* cmsParametricCurveEvaluator)(cmsInt32Number Type, const cmsFloat64Number Params[10], cmsFloat64Number R);
 
 // Plug-in may implement an arbitrary number of parametric curves
@@ -428,7 +428,7 @@
     cmsUInt32Number     nSupportedTypes;    // In how many types this tag can come (MAX_TYPES_IN_LCMS_PLUGIN maximum)
     cmsTagTypeSignature SupportedTypes[MAX_TYPES_IN_LCMS_PLUGIN];
 
-    // For writting
+    // For writing
     cmsTagTypeSignature (* DecideType)(cmsFloat64Number ICCVersion, const void *Data);
 
 } cmsTagDescriptor;
diff --git a/third_party/lcms/src/cmsalpha.c b/third_party/lcms/src/cmsalpha.c
index 566f5fe..3e6b7c3 100644
--- a/third_party/lcms/src/cmsalpha.c
+++ b/third_party/lcms/src/cmsalpha.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -26,7 +26,6 @@
 
 #include "lcms2_internal.h"
 
-
 // Alpha copy ------------------------------------------------------------------------------------------------------------------
 
 // Floor to byte, taking care of saturation
@@ -42,16 +41,16 @@
 
 // Return the size in bytes of a given formatter
 static
-int trueBytesSize(cmsUInt32Number Format)
+cmsUInt32Number trueBytesSize(cmsUInt32Number Format)
 {
-       int fmt_bytes = T_BYTES(Format);
+    cmsUInt32Number 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;
+    // 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;
 }
 
 
@@ -90,8 +89,13 @@
 static
 void from8toHLF(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f;
        *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 // From 16
@@ -122,8 +126,13 @@
 static
 void from16toHLF(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f;
        *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 // From Float
@@ -158,8 +167,13 @@
 static
 void fromFLTtoHLF(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        cmsFloat32Number n = *(cmsFloat32Number*)src;
        *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 
@@ -168,27 +182,48 @@
 static
 void fromHLFto8(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
        *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
+
 }
 
 static
 void fromHLFto16(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
        *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 static
 void fromHLFtoFLT(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 static
 void fromHLFtoDBL(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 // From double
@@ -216,8 +251,13 @@
 static
 void fromDBLtoHLF(void* dst, const void* src)
 {
+#ifndef CMS_NO_HALF_SUPPORT
        cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src;
        *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
+#else
+    cmsUNUSED_PARAMETER(dst);
+    cmsUNUSED_PARAMETER(src);
+#endif
 }
 
 static
@@ -231,21 +271,22 @@
 static
 int FormatterPos(cmsUInt32Number frm)
 {
-       int  b = T_BYTES(frm);
+    cmsUInt32Number  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
+    if (b == 0 && T_FLOAT(frm))
+        return 4; // DBL
+#ifndef CMS_NO_HALF_SUPPORT
+    if (b == 2 && T_FLOAT(frm))
+        return 2; // HLF
+#endif
+    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
-
+    return -1; // not recognized
 }
 
 // Obtains a alpha-to-alpha funmction formatter
@@ -281,12 +322,12 @@
                                 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;
+       cmsUInt32Number extra = T_EXTRA(Format);
+       cmsUInt32Number nchannels = T_CHANNELS(Format);
+       cmsUInt32Number total_chans = nchannels + extra;
+       cmsUInt32Number i;
+       cmsUInt32Number channelSize = trueBytesSize(Format);
+       cmsUInt32Number pixelSize = channelSize * total_chans;
        
 	   // Sanity check
 	   if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
@@ -339,11 +380,11 @@
                                 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);
+       cmsUInt32Number extra = T_EXTRA(Format);
+       cmsUInt32Number nchannels = T_CHANNELS(Format);
+       cmsUInt32Number total_chans = nchannels + extra;
+       cmsUInt32Number i;
+       cmsUInt32Number channelSize = trueBytesSize(Format);
       
        // Sanity check
        if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
diff --git a/third_party/lcms/src/cmscam02.c b/third_party/lcms/src/cmscam02.c
index 5f0ac1f..9cc49fb 100644
--- a/third_party/lcms/src/cmscam02.c
+++ b/third_party/lcms/src/cmscam02.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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/third_party/lcms/src/cmscgats.c b/third_party/lcms/src/cmscgats.c
index 0738a1c..dba77f1 100644
--- a/third_party/lcms/src/cmscgats.c
+++ b/third_party/lcms/src/cmscgats.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -240,65 +240,64 @@
         {"PROD_DATE",        WRITE_STRINGIFY},   // Identifies year and month of production of the target in the form yyyy:mm.
         {"SERIAL",           WRITE_STRINGIFY},   // Uniquely identifies individual physical target.
 
-        {"MATERIAL",         WRITE_STRINGIFY},   // Identifies the material on which the target was produced using a code
-                               // uniquely identifying th e material. This is intend ed to be used for IT8.7
-                               // physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
+        {"MATERIAL",         WRITE_STRINGIFY},    // Identifies the material on which the target was produced using a code
+                                                  // uniquely identifying th e material. This is intend ed to be used for IT8.7
+                                                  // physical targets only (i.e . IT8.7/1 a nd IT8.7/2).
 
-        {"INSTRUMENTATION",  WRITE_STRINGIFY},   // Used to report the specific instrumentation used (manufacturer and
-                               // model number) to generate the data reported. This data will often
-                               // provide more information about the particular data collected than an
-                               // extensive list of specific details. This is particularly important for
-                               // spectral data or data derived from spectrophotometry.
+        {"INSTRUMENTATION",  WRITE_STRINGIFY},    // Used to report the specific instrumentation used (manufacturer and
+                                                  // model number) to generate the data reported. This data will often
+                                                  // provide more information about the particular data collected than an
+                                                  // extensive list of specific details. This is particularly important for
+                                                  // spectral data or data derived from spectrophotometry.
 
-        {"MEASUREMENT_SOURCE", WRITE_STRINGIFY}, // Illumination used for spectral measurements. This data helps provide
-                               // a guide to the potential for issues of paper fluorescence, etc.
+        {"MEASUREMENT_SOURCE", WRITE_STRINGIFY},  // Illumination used for spectral measurements. This data helps provide
+                                                  // a guide to the potential for issues of paper fluorescence, etc.
 
-        {"PRINT_CONDITIONS", WRITE_STRINGIFY},   // Used to define the characteristics of the printed sheet being reported.
-                               // Where standard conditions have been defined (e.g., SWOP at nominal)
-                               // named conditions may suffice. Otherwise, detailed information is
-                               // needed.
+        {"PRINT_CONDITIONS", WRITE_STRINGIFY},     // Used to define the characteristics of the printed sheet being reported.
+                                                   // Where standard conditions have been defined (e.g., SWOP at nominal)
+                                                   // named conditions may suffice. Otherwise, detailed information is
+                                                   // needed.
 
-        {"SAMPLE_BACKING",   WRITE_STRINGIFY},   // Identifies the backing material used behind the sample during
-                               // measurement. Allowed values are "black" "white" or "na".
-
-        {"CHISQ_DOF",        WRITE_STRINGIFY},   // Degrees of freedom associated with the Chi squared statistic
-
-       // below properties are new in recent specs:
+        {"SAMPLE_BACKING",   WRITE_STRINGIFY},     // Identifies the backing material used behind the sample during
+                                                   // measurement. Allowed values are "black", "white", or {"na".
+                                                  
+        {"CHISQ_DOF",        WRITE_STRINGIFY},     // Degrees of freedom associated with the Chi squared statistic
+                                                   // below properties are new in recent specs:
 
         {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated
-                               // along with details of the geometry and the aperture size and shape. For example,
-                               // for transmission measurements it is important to identify 0/diffuse, diffuse/0,
-                               // opal or integrating sphere, etc. For reflection it is important to identify 0/45,
-                               // 45/0, sphere (specular included or excluded), etc.
+                                                   // along with details of the geometry and the aperture size and shape. For example,
+                                                   // for transmission measurements it is important to identify 0/diffuse, diffuse/0,
+                                                   // opal or integrating sphere, etc. For reflection it is important to identify 0/45,
+                                                   // 45/0, sphere (specular included or excluded), etc.
 
-       {"FILTER",            WRITE_STRINGIFY},   // Identifies the use of physical filter(s) during measurement. Typically used to
-                               // denote the use of filters such as none, D65, Red, Green or Blue.
+       {"FILTER",            WRITE_STRINGIFY},     // Identifies the use of physical filter(s) during measurement. Typically used to
+                                                   // denote the use of filters such as none, D65, Red, Green or Blue.
+                                                  
+       {"POLARIZATION",      WRITE_STRINGIFY},     // Identifies the use of a physical polarization filter during measurement. Allowed
+                                                   // values are "yes", "white", "none" or "na".
 
-       {"POLARIZATION",      WRITE_STRINGIFY},   // Identifies the use of a physical polarization filter during measurement. Allowed
-                               // values are "yes" "white" "none" or "na".
+       {"WEIGHTING_FUNCTION", WRITE_PAIR},         // Indicates such functions as: the CIE standard observer functions used in the
+                                                   // calculation of various data parameters (2 degree and 10 degree), CIE standard
+                                                   // illuminant functions used in the calculation of various data parameters (e.g., D50,
+                                                   // D65, etc.), density status response, etc. If used there shall be at least one
+                                                   // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute
+                                                   // in the set shall be {"name" and shall identify the particular parameter used.
+                                                   // The second shall be {"value" and shall provide the value associated with that name.
+                                                   // For ASCII data, a string containing the Name and Value attribute pairs shall follow
+                                                   // the weighting function keyword. A semi-colon separates attribute pairs from each
+                                                   // other and within the attribute the name and value are separated by a comma.
 
-       {"WEIGHTING_FUNCTION", WRITE_PAIR},   // Indicates such functions as: the CIE standard observer functions used in the
-                               // calculation of various data parameters (2 degree and 10 degree), CIE standard
-                               // illuminant functions used in the calculation of various data parameters (e.g., D50,
-                               // D65, etc.), density status response, etc. If used there shall be at least one
-                               // name-value pair following the WEIGHTING_FUNCTION tag/keyword. The first attribute
-                               // in the set shall be {"name" and shall identify the particular parameter used.
-                               // The second shall be {"value" and shall provide the value associated with that name.
-                               // For ASCII data, a string containing the Name and Value attribute pairs shall follow
-                               // the weighting function keyword. A semi-colon separates attribute pairs from each
-                               // other and within the attribute the name and value are separated by a comma.
-
-       {"COMPUTATIONAL_PARAMETER", WRITE_PAIR}, // Parameter that is used in computing a value from measured data. Name is the name
-                               // of the calculation, parameter is the name of the parameter used in the calculation
-                               // and value is the value of the parameter.
-
-       {"TARGET_TYPE",        WRITE_STRINGIFY},  // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
-
-       {"COLORANT",           WRITE_STRINGIFY},  // Identifies the colorant(s) used in creating the target.
-
-       {"TABLE_DESCRIPTOR",   WRITE_STRINGIFY},  // Describes the purpose or contents of a data table.
-
-       {"TABLE_NAME",         WRITE_STRINGIFY}   // Provides a short name for a data table.
+       {"COMPUTATIONAL_PARAMETER", WRITE_PAIR},    // Parameter that is used in computing a value from measured data. Name is the name
+                                                   // of the calculation, parameter is the name of the parameter used in the calculation
+                                                   // and value is the value of the parameter.
+                                                   
+       {"TARGET_TYPE",        WRITE_STRINGIFY},    // The type of target being measured, e.g. IT8.7/1, IT8.7/3, user defined, etc.
+                                                  
+       {"COLORANT",           WRITE_STRINGIFY},    // Identifies the colorant(s) used in creating the target.
+                                                  
+       {"TABLE_DESCRIPTOR",   WRITE_STRINGIFY},    // Describes the purpose or contents of a data table.
+                                                  
+       {"TABLE_NAME",         WRITE_STRINGIFY}     // Provides a short name for a data table.
 };
 
 #define NUMPREDEFINEDPROPS (sizeof(PredefinedProperties)/sizeof(PROPERTY))
@@ -539,13 +538,13 @@
 
 //  Reads a Real number, tries to follow from integer number
 static
-void ReadReal(cmsIT8* it8, int inum)
+void ReadReal(cmsIT8* it8, cmsInt32Number inum)
 {
-    it8->dnum = (cmsFloat64Number) inum;
+    it8->dnum = (cmsFloat64Number)inum;
 
     while (isdigit(it8->ch)) {
 
-        it8->dnum = it8->dnum * 10.0 + (it8->ch - '0');
+        it8->dnum = (cmsFloat64Number)it8->dnum * 10.0 + (cmsFloat64Number)(it8->ch - '0');
         NextCh(it8);
     }
 
@@ -558,7 +557,7 @@
 
         while (isdigit(it8->ch)) {
 
-            frac = frac * 10.0 + (it8->ch - '0');
+            frac = frac * 10.0 + (cmsFloat64Number)(it8->ch - '0');
             prec++;
             NextCh(it8);
         }
@@ -585,17 +584,19 @@
                 NextCh(it8);
             }
 
-            e = 0;
-            while (isdigit(it8->ch)) {
+        e = 0;
+        while (isdigit(it8->ch)) {
 
-                if ((cmsFloat64Number) e * 10L < (cmsFloat64Number) +2147483647.0)
-                    e = e * 10 + (it8->ch - '0');
+            cmsInt32Number digit = (it8->ch - '0');
 
-                NextCh(it8);
-            }
+            if ((cmsFloat64Number)e * 10.0 + (cmsFloat64Number)digit < (cmsFloat64Number)+2147483647.0)
+                e = e * 10 + digit;
 
-            e = sgn*e;
-            it8 -> dnum = it8 -> dnum * xpow10(e);
+            NextCh(it8);
+        }
+
+        e = sgn*e;
+        it8->dnum = it8->dnum * xpow10(e);
     }
 }
 
@@ -613,12 +614,12 @@
 
     if (*Buffer == '-' || *Buffer == '+') {
 
-         sign = (*Buffer == '-') ? -1 : 1;
-         Buffer++;
+        sign = (*Buffer == '-') ? -1 : 1;
+        Buffer++;
     }
 
 
-    while (*Buffer && isdigit((int) *Buffer)) {
+    while (*Buffer && isdigit((int)*Buffer)) {
 
         dnum = dnum * 10.0 + (*Buffer - '0');
         if (*Buffer) Buffer++;
@@ -627,11 +628,11 @@
     if (*Buffer == '.') {
 
         cmsFloat64Number frac = 0.0;      // fraction
-        int prec = 0;                     // precission
+        int prec = 0;                     // precision
 
         if (*Buffer) Buffer++;
 
-        while (*Buffer && isdigit((int) *Buffer)) {
+        while (*Buffer && isdigit((int)*Buffer)) {
 
             frac = frac * 10.0 + (*Buffer - '0');
             prec++;
@@ -662,17 +663,19 @@
                 if (*Buffer) Buffer++;
             }
 
-            e = 0;
-            while (*Buffer && isdigit((int) *Buffer)) {
+        e = 0;
+        while (*Buffer && isdigit((int)*Buffer)) {
 
-                if ((cmsFloat64Number) e * 10L < INT_MAX)
-                    e = e * 10 + (*Buffer - '0');
+            cmsInt32Number digit = (*Buffer - '0');
 
-                if (*Buffer) Buffer++;
-            }
+            if ((cmsFloat64Number)e * 10.0 + digit < (cmsFloat64Number)+2147483647.0)
+                e = e * 10 + digit;
 
-            e = sgn*e;
-            dnum = dnum * xpow10(e);
+            if (*Buffer) Buffer++;
+        }
+
+        e = sgn*e;
+        dnum = dnum * xpow10(e);
     }
 
     return sign * dnum;
@@ -741,7 +744,7 @@
                             if (it8->ch >= 'A' && it8->ch <= 'F')  j = it8->ch -'A'+10;
                             else j = it8->ch - '0';
 
-                            if ((long) it8->inum * 16L > (long) INT_MAX)
+                            if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0)
                             {
                                 SynError(it8, "Invalid hexadecimal number");
                                 return;
@@ -762,7 +765,7 @@
                         {
                             j = it8->ch - '0';
 
-                            if ((long) it8->inum * 2L > (long) INT_MAX)
+                            if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0)
                             {
                                 SynError(it8, "Invalid binary number");
                                 return;
@@ -778,14 +781,16 @@
 
                 while (isdigit(it8->ch)) {
 
-                    if ((cmsFloat64Number) it8->inum * 10L > (cmsFloat64Number) +2147483647.0) {
+                    cmsInt32Number digit = (it8->ch - '0');
+
+                    if ((cmsFloat64Number) it8->inum * 10.0 + (cmsFloat64Number) digit > (cmsFloat64Number) +2147483647.0) {
                         ReadReal(it8, it8->inum);
                         it8->sy = SDNUM;
                         it8->dnum *= sign;
                         return;
                     }
 
-                    it8->inum = it8->inum * 10 + (it8->ch - '0');
+                    it8->inum = it8->inum * 10 + digit;
                     NextCh(it8);
                 }
 
@@ -875,7 +880,7 @@
             k = 0;
             NextCh(it8);
 
-            while (k < MAXSTR && it8->ch != sng) {
+            while (k < (MAXSTR-1) && it8->ch != sng) {
 
                 if (it8->ch == '\n'|| it8->ch == '\r') k = MAXSTR+1;
                 else {
@@ -1490,8 +1495,8 @@
 
 cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE  h, int n, const char *Sample)
 {
-        cmsIT8* it8 = (cmsIT8*) h;
-        return SetDataFormat(it8, n, Sample);
+    cmsIT8* it8 = (cmsIT8*)h;
+    return SetDataFormat(it8, n, Sample);
 }
 
 static
@@ -1522,8 +1527,8 @@
 char* GetData(cmsIT8* it8, int nSet, int nField)
 {
     TABLE* t = GetTable(it8);
-    int  nSamples   = t -> nSamples;
-    int  nPatches   = t -> nPatches;
+    int nSamples    = t -> nSamples;
+    int nPatches    = t -> nPatches;
 
     if (nSet >= nPatches || nField >= nSamples)
         return NULL;
@@ -1954,67 +1959,67 @@
 
 
         case SIDENT:
-                strncpy(VarName, it8->id, MAXID-1);
-                VarName[MAXID-1] = 0;
+            strncpy(VarName, it8->id, MAXID - 1);
+            VarName[MAXID - 1] = 0;
 
-                if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
+            if (!IsAvailableOnList(it8->ValidKeywords, VarName, NULL, &Key)) {
 
 #ifdef CMS_STRICT_CGATS
-                 return SynError(it8, "Undefined keyword '%s'", VarName);
+                return SynError(it8, "Undefined keyword '%s'", VarName);
 #else
-                    Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
-                    if (Key == NULL) return FALSE;
+                Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
+                if (Key == NULL) return FALSE;
 #endif
+            }
+
+            InSymbol(it8);
+            if (!GetVal(it8, Buffer, MAXSTR - 1, "Property data expected")) return FALSE;
+
+            if (Key->WriteAs != WRITE_PAIR) {
+                AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
+                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
+            }
+            else {
+                const char *Subkey;
+                char *Nextkey;
+                if (it8->sy != SSTRING)
+                    return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
+
+                // chop the string as a list of "subkey, value" pairs, using ';' as a separator
+                for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
+                {
+                    char *Value, *temp;
+
+                    //  identify token pair boundary
+                    Nextkey = (char*)strchr(Subkey, ';');
+                    if (Nextkey)
+                        *Nextkey++ = '\0';
+
+                    // for each pair, split the subkey and the value
+                    Value = (char*)strrchr(Subkey, ',');
+                    if (Value == NULL)
+                        return SynError(it8, "Invalid value for property '%s'.", VarName);
+
+                    // gobble the spaces before the coma, and the coma itself
+                    temp = Value++;
+                    do *temp-- = '\0'; while (temp >= Subkey && *temp == ' ');
+
+                    // gobble any space at the right
+                    temp = Value + strlen(Value) - 1;
+                    while (*temp == ' ') *temp-- = '\0';
+
+                    // trim the strings from the left
+                    Subkey += strspn(Subkey, " ");
+                    Value += strspn(Value, " ");
+
+                    if (Subkey[0] == 0 || Value[0] == 0)
+                        return SynError(it8, "Invalid value for property '%s'.", VarName);
+                    AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
                 }
+            }
 
-                InSymbol(it8);
-                if (!GetVal(it8, Buffer, MAXSTR-1, "Property data expected")) return FALSE;
-
-                if(Key->WriteAs != WRITE_PAIR) {
-                    AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
-                                (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
-                }
-                else {
-                    const char *Subkey;
-                    char *Nextkey;
-                    if (it8->sy != SSTRING)
-                        return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
-
-                    // chop the string as a list of "subkey, value" pairs, using ';' as a separator
-                    for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
-                    {
-                        char *Value, *temp;
-
-                        //  identify token pair boundary
-                        Nextkey = (char*) strchr(Subkey, ';');
-                        if(Nextkey)
-                            *Nextkey++ = '\0';
-
-                        // for each pair, split the subkey and the value
-                        Value = (char*) strrchr(Subkey, ',');
-                        if(Value == NULL)
-                            return SynError(it8, "Invalid value for property '%s'.", VarName);
-
-                        // gobble the spaces before the coma, and the coma itself
-                        temp = Value++;
-                        do *temp-- = '\0'; while(temp >= Subkey && *temp == ' ');
-
-                        // gobble any space at the right
-                        temp = Value + strlen(Value) - 1;
-                        while(*temp == ' ') *temp-- = '\0';
-
-                        // trim the strings from the left
-                        Subkey += strspn(Subkey, " ");
-                        Value += strspn(Value, " ");
-
-                        if(Subkey[0] == 0 || Value[0] == 0)
-                            return SynError(it8, "Invalid value for property '%s'.", VarName);
-                        AddToList(it8, &GetTable(it8)->HeaderList, VarName, Subkey, Value, WRITE_PAIR);
-                    }
-                }
-
-                InSymbol(it8);
-                break;
+            InSymbol(it8);
+            break;
 
 
         case SEOLN: break;
@@ -2034,14 +2039,17 @@
 static
 void ReadType(cmsIT8* it8, char* SheetTypePtr)
 {
+    cmsInt32Number cnt = 0;
+
     // First line is a very special case.
 
     while (isseparator(it8->ch))
             NextCh(it8);
 
-    while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != -1) {
+    while (it8->ch != '\r' && it8 ->ch != '\n' && it8->ch != '\t' && it8 -> ch != 0) {
 
-        *SheetTypePtr++= (char) it8 ->ch;
+        if (cnt++ < MAXSTR) 
+            *SheetTypePtr++= (char) it8 ->ch;
         NextCh(it8);
     }
 
@@ -2234,10 +2242,10 @@
 // that should be something like some printable characters plus a \n
 // returns 0 if this is not like a CGATS, or an integer otherwise. This integer is the number of words in first line?
 static
-int IsMyBlock(cmsUInt8Number* Buffer, int n)
+int IsMyBlock(const cmsUInt8Number* Buffer, cmsUInt32Number n)
 {
     int words = 1, space = 0, quot = 0;
-    int i;
+    cmsUInt32Number i;
 
     if (n < 10) return 0;   // Too small
 
@@ -2298,7 +2306,7 @@
 // ---------------------------------------------------------- Exported routines
 
 
-cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len)
+cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, const void *Ptr, cmsUInt32Number len)
 {
     cmsHANDLE hIT8;
     cmsIT8*  it8;
@@ -2307,7 +2315,7 @@
     _cmsAssert(Ptr != NULL);
     _cmsAssert(len != 0);
 
-    type = IsMyBlock((cmsUInt8Number*)Ptr, len);
+    type = IsMyBlock((const cmsUInt8Number*)Ptr, len);
     if (type == 0) return NULL;
 
     hIT8 = cmsIT8Alloc(ContextID);
@@ -2725,7 +2733,7 @@
 {
     const char* cLabelFld;
     char Type[256], Label[256];
-    int nTable;
+    cmsUInt32Number nTable;
 
     _cmsAssert(hIT8 != NULL);
 
@@ -2738,7 +2746,7 @@
     cLabelFld = cmsIT8GetData(hIT8, cSet, cField);
     if (!cLabelFld) return -1;
 
-    if (sscanf(cLabelFld, "%255s %d %255s", Label, &nTable, Type) != 3)
+    if (sscanf(cLabelFld, "%255s %u %255s", Label, &nTable, Type) != 3)
             return -1;
 
     if (ExpectedType != NULL && *ExpectedType == 0)
diff --git a/third_party/lcms/src/cmscnvrt.c b/third_party/lcms/src/cmscnvrt.c
index 6c92148..082f1f8 100644
--- a/third_party/lcms/src/cmscnvrt.c
+++ b/third_party/lcms/src/cmscnvrt.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -363,11 +363,12 @@
 
 // Compute the conversion layer
 static
-cmsBool ComputeConversion(int i, cmsHPROFILE hProfiles[],
-                                 cmsUInt32Number Intent,
-                                 cmsBool BPC,
-                                 cmsFloat64Number AdaptationState,
-                                 cmsMAT3* m, cmsVEC3* off)
+cmsBool ComputeConversion(cmsUInt32Number i, 
+                          cmsHPROFILE hProfiles[],
+                          cmsUInt32Number Intent,
+                          cmsBool BPC,
+                          cmsFloat64Number AdaptationState,
+                          cmsMAT3* m, cmsVEC3* off)
 {
 
     int k;
@@ -679,7 +680,7 @@
 
 // Translate black-preserving intents to ICC ones
 static
-int TranslateNonICCIntents(int Intent)
+cmsUInt32Number TranslateNonICCIntents(cmsUInt32Number Intent)
 {
     switch (Intent) {
         case INTENT_PRESERVE_K_ONLY_PERCEPTUAL:
diff --git a/third_party/lcms/src/cmserr.c b/third_party/lcms/src/cmserr.c
index 69b0550..d549f27 100644
--- a/third_party/lcms/src/cmserr.c
+++ b/third_party/lcms/src/cmserr.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -56,9 +56,11 @@
     long int p , n;
 
     p = ftell(f); // register current file position
+    if (p == -1L) 
+        return -1L;
 
     if (fseek(f, 0, SEEK_END) != 0) {
-        return -1;
+        return -1L;
     }
 
     n = ftell(f);
@@ -131,7 +133,7 @@
     }
     else {
 
-        // To reset it, we use the default allocators, which cannot be overriden
+        // To reset it, we use the default allocators, which cannot be overridden
         ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager;
     }
 }
diff --git a/third_party/lcms/src/cmsgamma.c b/third_party/lcms/src/cmsgamma.c
index eadbed8..b2d3e11 100644
--- a/third_party/lcms/src/cmsgamma.c
+++ b/third_party/lcms/src/cmsgamma.c
@@ -44,10 +44,11 @@
 // The list of supported parametric curves
 typedef struct _cmsParametricCurvesCollection_st {
 
-    int nFunctions;                                     // Number of supported functions in this chunk
-    int FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN];        // The identification types
-    int ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN];       // Number of parameters for each function
-    cmsParametricCurveEvaluator    Evaluator;           // The evaluator
+    cmsUInt32Number nFunctions;                                     // Number of supported functions in this chunk
+    cmsInt32Number  FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN];        // The identification types
+    cmsUInt32Number ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN];       // Number of parameters for each function
+
+    cmsParametricCurveEvaluator Evaluator;                          // The evaluator
 
     struct _cmsParametricCurvesCollection_st* Next; // Next in list
 
@@ -165,7 +166,7 @@
 {
     int i;
 
-    for (i=0; i < c ->nFunctions; i++)
+    for (i=0; i < (int) c ->nFunctions; i++)
         if (abs(Type) == c ->FunctionTypes[i]) return i;
 
     return -1;
@@ -209,20 +210,20 @@
 // no optimation curve is computed. nSegments may also be zero in the inverse case, where only the
 // optimization curve is given. Both features simultaneously is an error
 static
-cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntries,
-                                      cmsInt32Number nSegments, const cmsCurveSegment* Segments,
+cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsUInt32Number nEntries,
+                                      cmsUInt32Number nSegments, const cmsCurveSegment* Segments,
                                       const cmsUInt16Number* Values)
 {
     cmsToneCurve* p;
-    int i;
+    cmsUInt32Number i;
 
     // We allow huge tables, which are then restricted for smoothing operations
-    if (nEntries > 65530 || nEntries < 0) {
+    if (nEntries > 65530) {
         cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve of more than 65530 entries");
         return NULL;
     }
 
-    if (nEntries <= 0 && nSegments <= 0) {
+    if (nEntries == 0 && nSegments == 0) {
         cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve with zero segments and no table");
         return NULL;
     }
@@ -232,7 +233,7 @@
     if (!p) return NULL;
 
     // In this case, there are no segments
-    if (nSegments <= 0) {
+    if (nSegments == 0) {
         p ->Segments = NULL;
         p ->Evals = NULL;
     }
@@ -248,7 +249,7 @@
 
     // This 16-bit table contains a limited precision representation of the whole curve and is kept for
     // increasing xput on certain operations.
-    if (nEntries <= 0) {
+    if (nEntries == 0) {
         p ->Table16 = NULL;
     }
     else {
@@ -274,7 +275,7 @@
         p ->SegInterp = (cmsInterpParams**) _cmsCalloc(ContextID, nSegments, sizeof(cmsInterpParams*));
         if (p ->SegInterp == NULL) goto Error;
 
-        for (i=0; i< nSegments; i++) {
+        for (i=0; i < nSegments; i++) {
 
             // Type 0 is a special marker for table-based curves
             if (Segments[i].Type == 0)
@@ -330,7 +331,7 @@
 
     // Type 1 Reversed: X = Y ^1/gamma
     case -1:
-         if (R < 0) {
+        if (R < 0) {
 
             if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE)
                 Val = R;
@@ -338,80 +339,123 @@
                 Val = 0;
         }
         else
-            Val = pow(R, 1/Params[0]);
+        {
+            if (fabs(Params[0]) < MATRIX_DET_TOLERANCE)
+                Val = PLUS_INF;
+            else
+                Val = pow(R, 1 / Params[0]);
+        }
         break;
 
     // CIE 122-1966
     // Y = (aX + b)^Gamma  | X >= -b/a
     // Y = 0               | else
     case 2:
-        disc = -Params[2] / Params[1];
+    {
 
-        if (R >= disc ) {
+        if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
+        {
+            Val = 0;
+        }
+        else
+        {
+            disc = -Params[2] / Params[1];
 
-            e = Params[1]*R + Params[2];
+            if (R >= disc) {
 
-            if (e > 0)
-                Val = pow(e, Params[0]);
+                e = Params[1] * R + Params[2];
+
+                if (e > 0)
+                    Val = pow(e, Params[0]);
+                else
+                    Val = 0;
+            }
             else
                 Val = 0;
         }
-        else
-            Val = 0;
-        break;
+    }
+    break;
 
      // Type 2 Reversed
      // X = (Y ^1/g  - b) / a
      case -2:
-         if (R < 0)
+     {
+         if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
+             fabs(Params[1]) < MATRIX_DET_TOLERANCE)
+         {
              Val = 0;
+         }
          else
-             Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
+         {
+             if (R < 0)
+                 Val = 0;
+             else
+                 Val = (pow(R, 1.0 / Params[0]) - Params[2]) / Params[1];
 
-         if (Val < 0)
-              Val = 0;
-         break;
+             if (Val < 0)
+                 Val = 0;
+         }
+     }         
+     break;
 
 
     // IEC 61966-3
     // Y = (aX + b)^Gamma | X <= -b/a
     // Y = c              | else
     case 3:
-        disc = -Params[2] / Params[1];
-        if (disc < 0)
-            disc = 0;
-
-        if (R >= disc) {
-
-            e = Params[1]*R + Params[2];
-
-            if (e > 0)
-                Val = pow(e, Params[0]) + Params[3];
-            else
-                Val = 0;
+    {
+        if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
+        {
+            Val = 0;
         }
         else
-            Val = Params[3];
-        break;
+        {
+            disc = -Params[2] / Params[1];
+            if (disc < 0)
+                disc = 0;
+
+            if (R >= disc) {
+
+                e = Params[1] * R + Params[2];
+
+                if (e > 0)
+                    Val = pow(e, Params[0]) + Params[3];
+                else
+                    Val = 0;
+            }
+            else
+                Val = Params[3];
+        }
+    }
+    break;
 
 
     // Type 3 reversed
     // X=((Y-c)^1/g - b)/a      | (Y>=c)
     // X=-b/a                   | (Y<c)
     case -3:
-        if (R >= Params[3])  {
-
-            e = R - Params[3];
-
-            if (e > 0)
-                Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1];
-            else
-                Val = 0;
+    {
+        if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
+        {
+            Val = 0;
         }
-        else {
-            Val = -Params[2] / Params[1];
+        else
+        {
+            if (R >= Params[3]) {
+
+                e = R - Params[3];
+
+                if (e > 0)
+                    Val = (pow(e, 1 / Params[0]) - Params[2]) / Params[1];
+                else
+                    Val = 0;
+            }
+            else {
+                Val = -Params[2] / Params[1];
+            }
         }
-        break;
+    }
+    break;
 
 
     // IEC 61966-2.1 (sRGB)
@@ -435,20 +479,31 @@
     // X=((Y^1/g-b)/a)    | Y >= (ad+b)^g
     // X=Y/c              | Y< (ad+b)^g
     case -4:
-        e = Params[1] * Params[4] + Params[2];
-        if (e < 0)
-            disc = 0;
+    {
+        if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
+            fabs(Params[1]) < MATRIX_DET_TOLERANCE ||
+            fabs(Params[3]) < MATRIX_DET_TOLERANCE)
+        {
+            Val = 0;
+        }
         else
-            disc = pow(e, Params[0]);
+        {
+            e = Params[1] * Params[4] + Params[2];
+            if (e < 0)
+                disc = 0;
+            else
+                disc = pow(e, Params[0]);
 
-        if (R >= disc) {
+            if (R >= disc) {
 
-            Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
+                Val = (pow(R, 1.0 / Params[0]) - Params[2]) / Params[1];
+            }
+            else {
+                Val = R / Params[3];
+            }
         }
-        else {
-            Val = R / Params[3];
-        }
-        break;
+    }
+    break;
 
 
     // Y = (aX + b)^Gamma + e | X >= d
@@ -472,20 +527,29 @@
     // X=((Y-e)1/g-b)/a   | Y >=(ad+b)^g+e), cd+f
     // X=(Y-f)/c          | else
     case -5:
-
-        disc = Params[3] * Params[4] + Params[6];
-        if (R >= disc) {
-
-            e = R - Params[5];
-            if (e < 0)
-                Val = 0;
-            else
-                Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1];
+    {
+        if (fabs(Params[1]) < MATRIX_DET_TOLERANCE ||
+            fabs(Params[3]) < MATRIX_DET_TOLERANCE)
+        {
+            Val = 0;
         }
-        else {
-            Val = (R - Params[6]) / Params[3];
+        else
+        {
+            disc = Params[3] * Params[4] + Params[6];
+            if (R >= disc) {
+
+                e = R - Params[5];
+                if (e < 0)
+                    Val = 0;
+                else
+                    Val = (pow(e, 1.0 / Params[0]) - Params[2]) / Params[1];
+            }
+            else {
+                Val = (R - Params[6]) / Params[3];
+            }
         }
-        break;
+    }
+    break;
 
 
     // Types 6,7,8 comes from segmented curves as described in ICCSpecRevision_02_11_06_Float.pdf
@@ -503,12 +567,21 @@
 
     // ((Y - c) ^1/Gamma - b) / a
     case -6:
-        e = R - Params[3];
-        if (e < 0)
+    {
+        if (fabs(Params[1]) < MATRIX_DET_TOLERANCE)
+        {
             Val = 0;
+        }
         else
-        Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1];
-        break;
+        {
+            e = R - Params[3];
+            if (e < 0)
+                Val = 0;
+            else
+                Val = (pow(e, 1.0 / Params[0]) - Params[2]) / Params[1];
+        }
+    }
+    break;
 
 
     // Y = a * log (b * X^Gamma + c) + d
@@ -525,8 +598,19 @@
     // pow(10, (Y-d) / a) = b * X ^Gamma + c
     // pow((pow(10, (Y-d) / a) - c) / b, 1/g) = X
     case -7:
-       Val = pow((pow(10.0, (R-Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]);
-       break;
+    {
+        if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
+            fabs(Params[1]) < MATRIX_DET_TOLERANCE ||
+            fabs(Params[2]) < MATRIX_DET_TOLERANCE)
+        {
+            Val = 0;
+        }
+        else
+        {
+            Val = pow((pow(10.0, (R - Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]);
+        }
+    }
+    break;
 
 
    //Y = a * b^(c*X+d) + e
@@ -542,12 +626,25 @@
        disc = R - Params[4];
        if (disc < 0) Val = 0;
        else
-           Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2];
+       {
+           if (fabs(Params[0]) < MATRIX_DET_TOLERANCE ||
+               fabs(Params[2]) < MATRIX_DET_TOLERANCE)
+           {
+               Val = 0;
+           }
+           else
+           {
+               Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2];
+           }
+       }
        break;
 
    // S-Shaped: (1 - (1-x)^1/g)^1/g
    case 108:
-      Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]);
+       if (fabs(Params[0]) < MATRIX_DET_TOLERANCE)
+           Val = 0;
+       else
+           Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]);
       break;
 
     // y = (1 - (1-x)^1/g)^1/g
@@ -567,33 +664,45 @@
     return Val;
 }
 
-// Evaluate a segmented function for a single value. Return -1 if no valid segment found .
+// Evaluate a segmented function for a single value. Return -Inf if no valid segment found .
 // If fn type is 0, perform an interpolation on the table
 static
 cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R)
 {
     int i;
+    cmsFloat32Number Out32;
+    cmsFloat64Number Out;
 
-    for (i = g ->nSegments-1; i >= 0 ; --i) {
+    for (i = (int) g->nSegments - 1; i >= 0; --i) {
 
         // Check for domain
-        if ((R > g ->Segments[i].x0) && (R <= g ->Segments[i].x1)) {
+        if ((R > g->Segments[i].x0) && (R <= g->Segments[i].x1)) {
 
             // Type == 0 means segment is sampled
-            if (g ->Segments[i].Type == 0) {
+            if (g->Segments[i].Type == 0) {
 
-                cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0) / (g ->Segments[i].x1 - g ->Segments[i].x0);
-                cmsFloat32Number Out;
+                cmsFloat32Number R1 = (cmsFloat32Number)(R - g->Segments[i].x0) / (g->Segments[i].x1 - g->Segments[i].x0);
 
                 // Setup the table (TODO: clean that)
-                g ->SegInterp[i]-> Table = g ->Segments[i].SampledPoints;
+                g->SegInterp[i]->Table = g->Segments[i].SampledPoints;
 
-                g ->SegInterp[i] -> Interpolation.LerpFloat(&R1, &Out, g ->SegInterp[i]);
+                g->SegInterp[i]->Interpolation.LerpFloat(&R1, &Out32, g->SegInterp[i]);
+                Out = (cmsFloat64Number) Out32;
 
-                return Out;
             }
+            else {
+                Out = g->Evals[i](g->Segments[i].Type, g->Segments[i].Params, R);
+            }
+
+            if (isinf(Out))
+                return PLUS_INF;
             else
-                return g ->Evals[i](g->Segments[i].Type, g ->Segments[i].Params, R);
+            {
+                if (isinf(-Out))
+                    return MINUS_INF;
+            }
+
+            return Out;
         }
     }
 
@@ -616,13 +725,13 @@
 
 // Create an empty gamma curve, by using tables. This specifies only the limited-precision part, and leaves the
 // floating point description empty.
-cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number Values[])
+cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsUInt32Number nEntries, const cmsUInt16Number Values[])
 {
     return AllocateToneCurveStruct(ContextID, nEntries, 0, NULL, Values);
 }
 
 static
-int EntriesByGamma(cmsFloat64Number Gamma)
+cmsUInt32Number EntriesByGamma(cmsFloat64Number Gamma)
 {
     if (fabs(Gamma - 1.0) < 0.001) return 2;
     return 4096;
@@ -631,12 +740,12 @@
 
 // Create a segmented gamma, fill the table
 cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID,
-                                                   cmsInt32Number nSegments, const cmsCurveSegment Segments[])
+                                                   cmsUInt32Number nSegments, const cmsCurveSegment Segments[])
 {
-    int i;
+    cmsUInt32Number i;
     cmsFloat64Number R, Val;
     cmsToneCurve* g;
-    int nGridPoints = 4096;
+    cmsUInt32Number nGridPoints = 4096;
 
     _cmsAssert(Segments != NULL);
 
@@ -651,7 +760,7 @@
 
     // Once we have the floating point version, we can approximate a 16 bit table of 4096 entries
     // for performance reasons. This table would normally not be used except on 8/16 bits transforms.
-    for (i=0; i < nGridPoints; i++) {
+    for (i = 0; i < nGridPoints; i++) {
 
         R   = (cmsFloat64Number) i / (nGridPoints-1);
 
@@ -882,7 +991,7 @@
     if (LutTable[0] < LutTable[p ->Domain[0]]) {
 
         // Table is overall ascending
-        for (i=p->Domain[0]-1; i >=0; --i) {
+        for (i = (int) p->Domain[0] - 1; i >= 0; --i) {
 
             y0 = LutTable[i];
             y1 = LutTable[i+1];
@@ -917,7 +1026,7 @@
 }
 
 // Reverse a gamma table
-cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InCurve)
+cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsUInt32Number nResultSamples, const cmsToneCurve* InCurve)
 {
     cmsToneCurve *out;
     cmsFloat64Number a = 0, b = 0, y, x1, y1, x2, y2;
@@ -946,7 +1055,7 @@
     Ascending = !cmsIsToneCurveDescending(InCurve);
 
     // Iterate across Y axis
-    for (i=0; i <  nResultSamples; i++) {
+    for (i=0; i < (int) nResultSamples; i++) {
 
         y = (cmsFloat64Number) i * 65535.0 / (nResultSamples - 1);
 
@@ -1001,7 +1110,8 @@
 //   Output: smoothed vector (z): vector from 1 to m.
 
 static
-cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[], cmsFloat32Number z[], cmsFloat32Number lambda, int m)
+cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[], 
+                cmsFloat32Number z[], cmsFloat32Number lambda, int m)
 {
     int i, i1, i2;
     cmsFloat32Number *c, *d, *e;
@@ -1060,73 +1170,121 @@
 // Smooths a curve sampled at regular intervals.
 cmsBool  CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda)
 {
-    cmsFloat32Number w[MAX_NODES_IN_CURVE], y[MAX_NODES_IN_CURVE], z[MAX_NODES_IN_CURVE];
-    int i, nItems, Zeros, Poles;
+    cmsBool SuccessStatus = TRUE;
+    cmsFloat32Number *w, *y, *z;
+    cmsUInt32Number i, nItems, Zeros, Poles;
 
-    if (Tab == NULL) return FALSE;
-
-    if (cmsIsToneCurveLinear(Tab)) return TRUE; // Nothing to do
-
-    nItems = Tab -> nEntries;
-
-    if (nItems >= MAX_NODES_IN_CURVE) {
-        cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: too many points.");
-        return FALSE;
-    }
-
-    memset(w, 0, nItems * sizeof(cmsFloat32Number));
-    memset(y, 0, nItems * sizeof(cmsFloat32Number));
-    memset(z, 0, nItems * sizeof(cmsFloat32Number));
-
-    for (i=0; i < nItems; i++)
+    if (Tab != NULL && Tab->InterpParams != NULL)
     {
-        y[i+1] = (cmsFloat32Number) Tab -> Table16[i];
-        w[i+1] = 1.0;
-    }
+        cmsContext ContextID = Tab->InterpParams->ContextID;
 
-    if (!smooth2(Tab ->InterpParams->ContextID, w, y, z, (cmsFloat32Number) lambda, nItems)) return FALSE;
+        if (!cmsIsToneCurveLinear(Tab)) // Only non-linear curves need smoothing
+        {
+            nItems = Tab->nEntries;
+            if (nItems < MAX_NODES_IN_CURVE)
+            {
+                // Allocate one more item than needed
+                w = (cmsFloat32Number *)_cmsCalloc(ContextID, nItems + 1, sizeof(cmsFloat32Number));
+                y = (cmsFloat32Number *)_cmsCalloc(ContextID, nItems + 1, sizeof(cmsFloat32Number));
+                z = (cmsFloat32Number *)_cmsCalloc(ContextID, nItems + 1, sizeof(cmsFloat32Number));
 
-    // Do some reality - checking...
-    Zeros = Poles = 0;
-    for (i=nItems; i > 1; --i) {
+                if (w != NULL && y != NULL && z != NULL) // Ensure no memory allocation failure
+                {
+                    memset(w, 0, (nItems + 1) * sizeof(cmsFloat32Number));
+                    memset(y, 0, (nItems + 1) * sizeof(cmsFloat32Number));
+                    memset(z, 0, (nItems + 1) * sizeof(cmsFloat32Number));
 
-        if (z[i] == 0.) Zeros++;
-        if (z[i] >= 65535.) Poles++;
-        if (z[i] < z[i-1]) {
-            cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
-            return FALSE;
+                    for (i = 0; i < nItems; i++)
+                    {
+                        y[i + 1] = (cmsFloat32Number)Tab->Table16[i];
+                        w[i + 1] = 1.0;
+                    }
+
+                    if (smooth2(ContextID, w, y, z, (cmsFloat32Number)lambda, (int)nItems))
+                    {
+                        // Do some reality - checking...
+
+                        Zeros = Poles = 0;
+                        for (i = nItems; i > 1; --i)
+                        {
+                            if (z[i] == 0.) Zeros++;
+                            if (z[i] >= 65535.) Poles++;
+                            if (z[i] < z[i - 1])
+                            {
+                                cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
+                                SuccessStatus = FALSE;
+                                break;
+                            }
+                        }
+
+                        if (SuccessStatus && Zeros > (nItems / 3))
+                        {
+                            cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
+                            SuccessStatus = FALSE;
+                        }
+
+                        if (SuccessStatus && Poles > (nItems / 3))
+                        {
+                            cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
+                            SuccessStatus = FALSE;
+                        }
+
+                        if (SuccessStatus) // Seems ok
+                        {
+                            for (i = 0; i < nItems; i++)
+                            {
+                                // Clamp to cmsUInt16Number
+                                Tab->Table16[i] = _cmsQuickSaturateWord(z[i + 1]);
+                            }
+                        }
+                    }
+                    else // Could not smooth
+                    {
+                        cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Function smooth2 failed.");
+                        SuccessStatus = FALSE;
+                    }
+                }
+                else // One or more buffers could not be allocated
+                {
+                    cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Could not allocate memory.");
+                    SuccessStatus = FALSE;
+                }
+
+                if (z != NULL)
+                    _cmsFree(ContextID, z);
+
+                if (y != NULL)
+                    _cmsFree(ContextID, y);
+
+                if (w != NULL)
+                    _cmsFree(ContextID, w);
+            }
+            else // too many items in the table
+            {
+                cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Too many points.");
+                SuccessStatus = FALSE;
+            }
         }
     }
-
-    if (Zeros > (nItems / 3)) {
-        cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
-        return FALSE;
-    }
-    if (Poles > (nItems / 3)) {
-        cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
-        return FALSE;
+    else // Tab parameter or Tab->InterpParams is NULL
+    {
+        // Can't signal an error here since the ContextID is not known at this point
+        SuccessStatus = FALSE;
     }
 
-    // Seems ok
-    for (i=0; i < nItems; i++) {
-
-        // Clamp to cmsUInt16Number
-        Tab -> Table16[i] = _cmsQuickSaturateWord(z[i+1]);
-    }
-
-    return TRUE;
+    return SuccessStatus;
 }
 
 // Is a table linear? Do not use parametric since we cannot guarantee some weird parameters resulting
 // in a linear table. This way assures it is linear in 12 bits, which should be enought in most cases.
 cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve)
 {
-    cmsUInt32Number i;
+    int i;
     int diff;
 
     _cmsAssert(Curve != NULL);
 
-    for (i=0; i < Curve ->nEntries; i++) {
+    for (i=0; i < (int) Curve ->nEntries; i++) {
 
         diff = abs((int) Curve->Table16[i] - (int) _cmsQuantizeVal(i, Curve ->nEntries));
         if (diff > 0x0f)
@@ -1139,7 +1297,7 @@
 // Same, but for monotonicity
 cmsBool  CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t)
 {
-    int n;
+    cmsUInt32Number n;
     int i, last;
     cmsBool lDescending;
 
@@ -1156,7 +1314,7 @@
 
         last = t ->Table16[0];
 
-        for (i = 1; i < n; i++) {
+        for (i = 1; i < (int) n; i++) {
 
             if (t ->Table16[i] - last > 2) // We allow some ripple
                 return FALSE;
@@ -1169,7 +1327,7 @@
 
         last = t ->Table16[n-1];
 
-        for (i = n-2; i >= 0; --i) {
+        for (i = (int) n - 2; i >= 0; --i) {
 
             if (t ->Table16[i] - last > 2)
                 return FALSE;
diff --git a/third_party/lcms/src/cmsgmt.c b/third_party/lcms/src/cmsgmt.c
index b82f3be..5d7a320 100644
--- a/third_party/lcms/src/cmsgmt.c
+++ b/third_party/lcms/src/cmsgmt.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------

 //

 //  Little Color Management System

-//  Copyright (c) 1998-2016 Marti Maria Saguer

+//  Copyright (c) 1998-2017 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"),

@@ -297,7 +297,7 @@
     cmsStage* CLUT;

     cmsUInt32Number dwFormat;

     GAMUTCHAIN Chain;

-    int nChannels, nGridpoints;

+    cmsUInt32Number nChannels, nGridpoints;

     cmsColorSpaceSignature ColorSpace;

     cmsUInt32Number i;

     cmsHPROFILE ProfileList[256];

diff --git a/third_party/lcms/src/cmshalf.c b/third_party/lcms/src/cmshalf.c
index cceb6f9..935273d 100644
--- a/third_party/lcms/src/cmshalf.c
+++ b/third_party/lcms/src/cmshalf.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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/third_party/lcms/src/cmsintrp.c b/third_party/lcms/src/cmsintrp.c
index 60d6a0e..e44ab3e 100644
--- a/third_party/lcms/src/cmsintrp.c
+++ b/third_party/lcms/src/cmsintrp.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -29,6 +29,13 @@
 // This module incorporates several interpolation routines, for 1 to 8 channels on input and
 // up to 65535 channels on output. The user may change those by using the interpolation plug-in
 
+// Some people may want to compile as C++ with all warnings on, in this case make compiler silent
+#ifdef _MSC_VER
+#    if (_MSC_VER >= 1400)
+#       pragma warning( disable : 4365 )
+#    endif
+#endif
+
 // Interpolation routines by default
 static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
 
@@ -102,12 +109,12 @@
 // This function precalculates as many parameters as possible to speed up the interpolation.
 cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
                                            const cmsUInt32Number nSamples[],
-                                           int InputChan, int OutputChan,
+                                           cmsUInt32Number InputChan, cmsUInt32Number OutputChan,
                                            const void *Table,
                                            cmsUInt32Number dwFlags)
 {
     cmsInterpParams* p;
-    int i;
+    cmsUInt32Number i;
 
     // Check for maximum inputs
     if (InputChan > MAX_INPUT_DIMENSIONS) {
@@ -151,7 +158,8 @@
 
 
 // This one is a wrapper on the anterior, but assuming all directions have same number of nodes
-cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
+cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, cmsUInt32Number nSamples, 
+                                         cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags)
 {
     int i;
     cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
@@ -215,7 +223,7 @@
 // To prevent out of bounds indexing
 cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) 
 {
-    return ((v < 0.0f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v);
+    return ((v < 1.0e-9f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v);
 }
 
 // Floating-point version of 1D interpolation
@@ -352,10 +360,10 @@
     y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
 
     X0 = p -> opta[1] * x0;
-    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]);
+    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[1]);
 
     Y0 = p -> opta[0] * y0;
-    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]);
+    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[0]);
 
     for (OutChan = 0; OutChan < TotalOut; OutChan++) {
 
@@ -464,18 +472,18 @@
     py = fclamp(Input[1]) * p->Domain[1];
     pz = fclamp(Input[2]) * p->Domain[2];
 
-    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
-    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
-    z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
+    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor funcionality here
+    y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
+    z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
 
     X0 = p -> opta[2] * x0;
-    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
+    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
 
     Y0 = p -> opta[1] * y0;
-    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
+    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
 
     Z0 = p -> opta[0] * z0;
-    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
+    Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
 
     for (OutChan = 0; OutChan < TotalOut; OutChan++) {
 
@@ -608,19 +616,19 @@
     py = fclamp(Input[1]) * p->Domain[1];
     pz = fclamp(Input[2]) * p->Domain[2];
 
-    x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
-    y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
-    z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
+    x0 = (int) floor(px); rx = (px - (cmsFloat32Number) x0);  // We need full floor functionality here
+    y0 = (int) floor(py); ry = (py - (cmsFloat32Number) y0);
+    z0 = (int) floor(pz); rz = (pz - (cmsFloat32Number) z0);
 
 
     X0 = p -> opta[2] * x0;
-    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
+    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
 
     Y0 = p -> opta[1] * y0;
-    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
+    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
 
     Z0 = p -> opta[0] * z0;
-    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
+    Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
 
     for (OutChan=0; OutChan < TotalOut; OutChan++) {
 
@@ -923,13 +931,13 @@
                                 c3 = DENS(X0, Y0, Z1) - c0;
 
                             }
-                            else  {
+                            else {
                                 c1 = c2 = c3 = 0;
                             }
 
                             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)));
     }
 
 
@@ -1028,7 +1036,7 @@
        rest = pk - (cmsFloat32Number) k0;
 
        K0 = p -> opta[3] * k0;
-       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
+       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[3]);
 
        p1 = *p;
        memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
@@ -1115,7 +1123,7 @@
        rest = pk - (cmsFloat32Number) k0;
 
        K0 = p -> opta[4] * k0;
-       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
+       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]);
 
        p1 = *p;
        memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
@@ -1202,7 +1210,7 @@
        rest = pk - (cmsFloat32Number) k0;
 
        K0 = p -> opta[5] * k0;
-       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
+       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]);
 
        p1 = *p;
        memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
@@ -1287,7 +1295,7 @@
        rest = pk - (cmsFloat32Number) k0;
 
        K0 = p -> opta[6] * k0;
-       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
+       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]);
 
        p1 = *p;
        memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
@@ -1372,7 +1380,7 @@
        rest = pk - (cmsFloat32Number) k0;
 
        K0 = p -> opta[7] * k0;
-       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
+       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]);
 
        p1 = *p;
        memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
diff --git a/third_party/lcms/src/cmsio0.c b/third_party/lcms/src/cmsio0.c
index 63bbe36..1b4942c 100644
--- a/third_party/lcms/src/cmsio0.c
+++ b/third_party/lcms/src/cmsio0.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -337,21 +337,27 @@
     return TRUE;
 }
 
-// Returns file pointer position
+// Returns file pointer position or 0 on error, which is also a valid position.
 static
 cmsUInt32Number FileTell(cmsIOHANDLER* iohandler)
 {
-    return (cmsUInt32Number) ftell((FILE*)iohandler ->stream);
+    long t = ftell((FILE*)iohandler ->stream);
+    if (t == -1L) {
+        cmsSignalError(iohandler->ContextID, cmsERROR_FILE, "Tell error; probably corrupted file");
+        return 0;
+    }
+
+    return (cmsUInt32Number)t;
 }
 
 // Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error
 static
 cmsBool  FileWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void* Buffer)
 {
-       if (size == 0) return TRUE;  // We allow to write 0 bytes, but nothing is written
+    if (size == 0) return TRUE;  // We allow to write 0 bytes, but nothing is written
 
-       iohandler->UsedSpace += size;
-       return (fwrite(Buffer, size, 1, (FILE*) iohandler->stream) == 1);
+    iohandler->UsedSpace += size;
+    return (fwrite(Buffer, size, 1, (FILE*)iohandler->stream) == 1);
 }
 
 // Closes the file
@@ -527,7 +533,7 @@
     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
     if (Icc == NULL) return -1;
 
-    return  Icc->TagCount;
+    return  (cmsInt32Number) Icc->TagCount;
 }
 
 // Return the tag signature of a given tag number
@@ -545,9 +551,9 @@
 static
 int SearchOneTag(_cmsICCPROFILE* Profile, cmsTagSignature sig)
 {
-    cmsUInt32Number i;
+    int i;
 
-    for (i=0; i < Profile -> TagCount; i++) {
+    for (i=0; i < (int) Profile -> TagCount; i++) {
 
         if (sig == Profile -> TagNames[i])
             return i;
@@ -649,7 +655,7 @@
             return FALSE;
         }
 
-        *NewPos = Icc ->TagCount;
+        *NewPos = (int) Icc ->TagCount;
         Icc -> TagCount++;
     }
 
@@ -680,10 +686,10 @@
     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;
+    temp1 = (cmsUInt8Number) (*(pByte+1) & 0xf0);
+    temp2 = (cmsUInt8Number) (*(pByte+1) & 0x0f);
+    if (temp1 > 0x90U) temp1 = 0x90U;
+    if (temp2 > 0x09U) temp2 = 0x09U;
     *(pByte+1) = (cmsUInt8Number)(temp1 | temp2);
     *(pByte+2) = (cmsUInt8Number)0;
     *(pByte+3) = (cmsUInt8Number)0;
@@ -792,7 +798,7 @@
     cmsICCHeader Header;
     cmsUInt32Number i;
     cmsTagEntry Tag;
-    cmsInt32Number Count = 0;
+    cmsUInt32Number Count;
 
     Header.size        = _cmsAdjustEndianess32(UsedSpace);
     Header.cmmId       = _cmsAdjustEndianess32(lcmsSignature);
@@ -823,9 +829,9 @@
     Header.renderingIntent = _cmsAdjustEndianess32(Icc -> RenderingIntent);
 
     // Illuminant is always D50
-    Header.illuminant.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->X));
-    Header.illuminant.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y));
-    Header.illuminant.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z));
+    Header.illuminant.X = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->X));
+    Header.illuminant.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y));
+    Header.illuminant.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z));
 
     // Created by LittleCMS (that's me!)
     Header.creator      = _cmsAdjustEndianess32(lcmsSignature);
@@ -841,6 +847,7 @@
     // Saves Tag directory
 
     // Get true count
+    Count = 0;
     for (i=0;  i < Icc -> TagCount; i++) {
         if (Icc ->TagNames[i] != (cmsTagSignature) 0)
             Count++;
@@ -853,9 +860,9 @@
 
         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]);
-        Tag.size   = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagSizes[i]);
+        Tag.sig    = (cmsTagSignature) _cmsAdjustEndianess32((cmsUInt32Number) Icc -> TagNames[i]);
+        Tag.offset = _cmsAdjustEndianess32((cmsUInt32Number) Icc -> TagOffsets[i]);
+        Tag.size   = _cmsAdjustEndianess32((cmsUInt32Number) Icc -> TagSizes[i]);
 
         if (!Icc ->IOhandler -> Write(Icc-> IOhandler, sizeof(cmsTagEntry), &Tag)) return FALSE;
     }
@@ -1164,7 +1171,7 @@
     NewIcc = (_cmsICCPROFILE*) hEmpty;
 
     // Ok, in this case const void* is casted to void* just because open IO handler
-    // shares read and writting modes. Don't abuse this feature!
+    // shares read and writing modes. Don't abuse this feature!
     NewIcc ->IOhandler = cmsOpenIOhandlerFromMem(ContextID, (void*) MemPtr, dwSize, "r");
     if (NewIcc ->IOhandler == NULL) goto Error;
 
@@ -1460,7 +1467,7 @@
     // Was open in write mode?
     if (Icc ->IsWrite) {
 
-        Icc ->IsWrite = FALSE;      // Assure no further writting
+        Icc ->IsWrite = FALSE;      // Assure no further writing
         rc &= cmsSaveProfileToFile(hProfile, Icc ->IOhandler->PhysicalFile);
     }
 
@@ -1558,6 +1565,8 @@
     Offset    = Icc -> TagOffsets[n];
     TagSize   = Icc -> TagSizes[n];
 
+    if (TagSize < 8) goto Error;
+
     // Seek to its location
     if (!io -> Seek(io, Offset))
         goto Error;
@@ -1580,8 +1589,8 @@
     if (BaseType == 0) goto Error;
 
     if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error;
-
-    TagSize  -= 8;                      // Alredy read by the type base logic
+   
+    TagSize  -= 8;       // Alredy read by the type base logic
 
     // Get type handler
     TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType);
@@ -1771,7 +1780,7 @@
 // raw data written does not exactly correspond with the raw data proposed to cmsWriteRaw data, but this approach allows
 // to write a tag as raw data and the read it as handled.
 
-cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize)
+cmsUInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize)
 {
     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
     void *Object;
@@ -1889,7 +1898,7 @@
 }
 
 // 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
+// checking anything. As a rule, mixing Raw with cooked doesn't work, so writing a tag as raw and then reading
 // 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)
diff --git a/third_party/lcms/src/cmsio1.c b/third_party/lcms/src/cmsio1.c
index 4b12ae1..1343f2b 100644
--- a/third_party/lcms/src/cmsio1.c
+++ b/third_party/lcms/src/cmsio1.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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 @@
 
 // Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc
 // is adjusted here in order to create a LUT that takes care of all those details.
-// We add intent = -1 as a way to read matrix shaper always, no matter of other LUT
-cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
+// We add intent = 0xffffffff as a way to read matrix shaper always, no matter of other LUT
+cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent)
 {
     cmsTagTypeSignature OriginalType;
     cmsTagSignature tag16;
@@ -341,8 +341,8 @@
     }
 
     // This is an attempt to reuse this function to retrieve the matrix-shaper as pipeline no
-    // matter other LUT are present and have precedence. Intent = -1 means just this.
-    if (Intent >= INTENT_PERCEPTUAL && Intent <= INTENT_ABSOLUTE_COLORIMETRIC) {
+    // matter other LUT are present and have precedence. Intent = 0xffffffff can be used for that.
+    if (Intent <= INTENT_ABSOLUTE_COLORIMETRIC) {
 
         tag16 = Device2PCS16[Intent];
         tagFloat = Device2PCSFloat[Intent];
@@ -586,7 +586,7 @@
 }
 
 // Create an output MPE LUT from agiven profile. Version mismatches are handled here
-cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
+cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent)
 {
     cmsTagTypeSignature OriginalType;
     cmsTagSignature tag16;
@@ -594,7 +594,7 @@
     cmsContext ContextID  = cmsGetProfileContextID(hProfile);
 
 
-    if (Intent >= INTENT_PERCEPTUAL && Intent <= INTENT_ABSOLUTE_COLORIMETRIC) {
+    if (Intent <= INTENT_ABSOLUTE_COLORIMETRIC) {
 
         tag16 = PCS2Device16[Intent];
         tagFloat = PCS2DeviceFloat[Intent];
@@ -670,8 +670,8 @@
 static
 cmsPipeline* _cmsReadFloatDevicelinkTag(cmsHPROFILE hProfile, cmsTagSignature tagFloat)
 {
-    cmsContext ContextID       = cmsGetProfileContextID(hProfile);
-    cmsPipeline* Lut           = cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
+    cmsContext ContextID = cmsGetProfileContextID(hProfile);
+    cmsPipeline* Lut = cmsPipelineDup((cmsPipeline*)cmsReadTag(hProfile, tagFloat));
     cmsColorSpaceSignature PCS = cmsGetPCS(hProfile);
     cmsColorSpaceSignature spc = cmsGetColorSpace(hProfile);
 
@@ -689,17 +689,17 @@
                 goto Error;
         }
 
-        if (PCS == cmsSigLabData)
+    if (PCS == cmsSigLabData)
+    {
+        if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+            goto Error;
+    }
+    else
+        if (PCS == cmsSigXYZData)
         {
-            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromLabFloat(ContextID)))
+            if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
                 goto Error;
         }
-        else
-            if (PCS == cmsSigXYZData)
-            {
-                if (!cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageNormalizeFromXyzFloat(ContextID)))
-                    goto Error;
-            }
 
     return Lut;
 Error:
@@ -709,7 +709,7 @@
 
 // This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
 // tag name here may default to AToB0
-cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
+cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent)
 {
     cmsPipeline* Lut;
     cmsTagTypeSignature OriginalType;
@@ -718,7 +718,7 @@
     cmsContext ContextID = cmsGetProfileContextID(hProfile);
 
 
-    if (Intent < INTENT_PERCEPTUAL || Intent > INTENT_ABSOLUTE_COLORIMETRIC)
+    if (Intent > INTENT_ABSOLUTE_COLORIMETRIC)
         return NULL;
 
     tag16 = Device2PCS16[Intent];
diff --git a/third_party/lcms/src/cmslut.c b/third_party/lcms/src/cmslut.c
index 8d58159..1c1e18f 100644
--- a/third_party/lcms/src/cmslut.c
+++ b/third_party/lcms/src/cmslut.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -124,8 +124,8 @@
     mpe = Lut ->Elements;
     for (i=0; i < n; i++) {
 
-        // Get asked type
-        Type  = (cmsStageSignature)va_arg(args, cmsStageSignature);
+        // Get asked type. cmsStageSignature is promoted to int by compiler
+        Type  = (cmsStageSignature)va_arg(args, int);
         if (mpe ->Type != Type) {
 
             va_end(args);       // Mismatch. We are done.
@@ -292,7 +292,7 @@
 
 
 // Create a bunch of identity curves
-cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels)
+cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, cmsUInt32Number nChannels)
 {
     cmsStage* mpe = cmsStageAllocToneCurves(ContextID, nChannels, NULL);
 
@@ -712,7 +712,7 @@
 }
 
 // Creates an MPE that just copies input to output
-cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan)
+cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, cmsUInt32Number nChan)
 {
     cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
     cmsStage* mpe ;
@@ -736,7 +736,7 @@
 
 
 // Quantize a value 0 <= i < MaxSamples to 0..0xffff
-cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples)
+cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, cmsUInt32Number MaxSamples)
 {
     cmsFloat64Number x;
 
@@ -749,8 +749,9 @@
 // function on knots. returns TRUE if all ok, FALSE otherwise.
 cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void * Cargo, cmsUInt32Number dwFlags)
 {
-    int i, t, nTotalPoints, index, rest;
-    int nInputs, nOutputs;
+    int i, t, index, rest;
+    cmsUInt32Number nTotalPoints;
+    cmsUInt32Number nInputs, nOutputs;
     cmsUInt32Number* nSamples;
     cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
     _cmsStageCLutData* clut;
@@ -770,14 +771,17 @@
     if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
     if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
 
+    memset(In, 0, sizeof(In));
+    memset(Out, 0, sizeof(Out));
+
     nTotalPoints = CubeSize(nSamples, nInputs);
     if (nTotalPoints == 0) return FALSE;
 
     index = 0;
-    for (i = 0; i < nTotalPoints; i++) {
+    for (i = 0; i < (int) nTotalPoints; i++) {
 
         rest = i;
-        for (t = nInputs-1; t >=0; --t) {
+        for (t = (int)nInputs - 1; t >= 0; --t) {
 
             cmsUInt32Number  Colorant = rest % nSamples[t];
 
@@ -787,7 +791,7 @@
         }
 
         if (clut ->Tab.T != NULL) {
-            for (t=0; t < nOutputs; t++)
+            for (t = 0; t < (int)nOutputs; t++)
                 Out[t] = clut->Tab.T[index + t];
         }
 
@@ -797,7 +801,7 @@
         if (!(dwFlags & SAMPLER_INSPECT)) {
 
             if (clut ->Tab.T != NULL) {
-                for (t=0; t < nOutputs; t++)
+                for (t=0; t < (int) nOutputs; t++)
                     clut->Tab.T[index + t] = Out[t];
             }
         }
@@ -808,11 +812,12 @@
     return TRUE;
 }
 
-// Same as anterior, but for floting point
+// Same as anterior, but for floating point
 cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void * Cargo, cmsUInt32Number dwFlags)
 {
-    int i, t, nTotalPoints, index, rest;
-    int nInputs, nOutputs;
+    int i, t, index, rest;
+    cmsUInt32Number nTotalPoints;
+    cmsUInt32Number nInputs, nOutputs;
     cmsUInt32Number* nSamples;
     cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
@@ -830,10 +835,10 @@
     if (nTotalPoints == 0) return FALSE;
 
     index = 0;
-    for (i = 0; i < nTotalPoints; i++) {
+    for (i = 0; i < (int)nTotalPoints; i++) {
 
         rest = i;
-        for (t = nInputs-1; t >=0; --t) {
+        for (t = (int) nInputs-1; t >=0; --t) {
 
             cmsUInt32Number  Colorant = rest % nSamples[t];
 
@@ -843,7 +848,7 @@
         }
 
         if (clut ->Tab.TFloat != NULL) {
-            for (t=0; t < nOutputs; t++)
+            for (t=0; t < (int) nOutputs; t++)
                 Out[t] = clut->Tab.TFloat[index + t];
         }
 
@@ -853,7 +858,7 @@
         if (!(dwFlags & SAMPLER_INSPECT)) {
 
             if (clut ->Tab.TFloat != NULL) {
-                for (t=0; t < nOutputs; t++)
+                for (t=0; t < (int) nOutputs; t++)
                     clut->Tab.TFloat[index + t] = Out[t];
             }
         }
@@ -871,7 +876,8 @@
 cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
                                          cmsSAMPLER16 Sampler, void * Cargo)
 {
-    int i, t, nTotalPoints, rest;
+    int i, t, rest;
+    cmsUInt32Number nTotalPoints;
     cmsUInt16Number In[cmsMAXCHANNELS];
 
     if (nInputs >= cmsMAXCHANNELS) return FALSE;
@@ -879,10 +885,10 @@
     nTotalPoints = CubeSize(clutPoints, nInputs);
     if (nTotalPoints == 0) return FALSE;
 
-    for (i = 0; i < nTotalPoints; i++) {
+    for (i = 0; i < (int) nTotalPoints; i++) {
 
         rest = i;
-        for (t = nInputs-1; t >=0; --t) {
+        for (t = (int) nInputs-1; t >=0; --t) {
 
             cmsUInt32Number  Colorant = rest % clutPoints[t];
 
@@ -901,7 +907,8 @@
 cmsInt32Number CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
                                             cmsSAMPLERFLOAT Sampler, void * Cargo)
 {
-    int i, t, nTotalPoints, rest;
+    int i, t, rest;
+    cmsUInt32Number nTotalPoints;
     cmsFloat32Number In[cmsMAXCHANNELS];
 
     if (nInputs >= cmsMAXCHANNELS) return FALSE;
@@ -909,10 +916,10 @@
     nTotalPoints = CubeSize(clutPoints, nInputs);
     if (nTotalPoints == 0) return FALSE;
 
-    for (i = 0; i < nTotalPoints; i++) {
+    for (i = 0; i < (int) nTotalPoints; i++) {
 
         rest = i;
-        for (t = nInputs-1; t >=0; --t) {
+        for (t = (int) nInputs-1; t >=0; --t) {
 
             cmsUInt32Number  Colorant = rest % clutPoints[t];
 
@@ -992,7 +999,7 @@
             return NULL;
         }
 
-        // We need to map * (0xffff / 0xff00), thats same as (257 / 256)
+        // We need to map * (0xffff / 0xff00), that's same as (257 / 256)
         // So we can use 258-entry tables to do the trick (i / 257) * (255 * 257) * (257 / 256);
         for (i=0; i < 257; i++)  {
 
@@ -1137,7 +1144,7 @@
        }
 }
 
-cmsStage*  _cmsStageClipNegatives(cmsContext ContextID, int nChannels)
+cmsStage*  _cmsStageClipNegatives(cmsContext ContextID, cmsUInt32Number nChannels)
 {
        return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType,
               nChannels, nChannels, Clipper, NULL, NULL, NULL);
@@ -1274,7 +1281,7 @@
 static
 cmsBool BlessLUT(cmsPipeline* lut)
 {
-    // We can set the input/ouput channels only if we have elements.
+    // We can set the input/output channels only if we have elements.
     if (lut ->Elements != NULL) {
 
         cmsStage* prev;
@@ -1301,9 +1308,10 @@
 
             next = next->Next;
             prev = prev->Next;
-        }
     }
-    return TRUE;
+}
+
+    return TRUE;    
 }
 
 
@@ -1357,10 +1365,7 @@
 }
 
 
-
-
 // LUT Creation & Destruction
-
 cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels)
 {
        cmsPipeline* NewLUT;
@@ -1372,7 +1377,6 @@
        NewLUT = (cmsPipeline*) _cmsMallocZero(ContextID, sizeof(cmsPipeline));
        if (NewLUT == NULL) return NULL;
 
-
        NewLUT -> InputChannels  = InputChannels;
        NewLUT -> OutputChannels = OutputChannels;
 
@@ -1536,7 +1540,7 @@
             return FALSE;
     }
 
-    return BlessLUT(lut);
+    return BlessLUT(lut);    
 }
 
 // Unlink an element and return the pointer to it
@@ -1618,7 +1622,7 @@
                 return FALSE;
     }
 
-    return BlessLUT(l1);
+    return BlessLUT(l1);    
 }
 
 
diff --git a/third_party/lcms/src/cmsmd5.c b/third_party/lcms/src/cmsmd5.c
index c7380ca..4b16ad4 100644
--- a/third_party/lcms/src/cmsmd5.c
+++ b/third_party/lcms/src/cmsmd5.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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/third_party/lcms/src/cmsmtrx.c b/third_party/lcms/src/cmsmtrx.c
index d0e5461..a83d39d 100644
--- a/third_party/lcms/src/cmsmtrx.c
+++ b/third_party/lcms/src/cmsmtrx.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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/third_party/lcms/src/cmsnamed.c b/third_party/lcms/src/cmsnamed.c
index 9ed4cad..9cfd228 100644
--- a/third_party/lcms/src/cmsnamed.c
+++ b/third_party/lcms/src/cmsnamed.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -127,7 +127,7 @@
     for (i=0; i < mlu ->UsedEntries; i++) {
 
         if (mlu ->Entries[i].Country  == CountryCode &&
-            mlu ->Entries[i].Language == LanguageCode) return i;
+            mlu ->Entries[i].Language == LanguageCode) return (int) i;
     }
 
     // Not found
@@ -178,31 +178,32 @@
     return TRUE;
 }
 
-// Convert from a 3-char code to a cmsUInt16Number. It is done inthis way because some
+// Convert from a 3-char code to a cmsUInt16Number. It is done in this 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];
+    const cmsUInt8Number* ptr8 = (const cmsUInt8Number*)str;
+    cmsUInt16Number n = (cmsUInt16Number) (((cmsUInt16Number) ptr8[1] << 8) | ptr8[0]);
 
-    return n;  // Always big endian in this case
+    return _cmsAdjustEndianess16(n);
 }
 
 static
 void strFrom16(char str[3], cmsUInt16Number n)
 {
-    // Assiming this would be aligned
+    // Assuming this would be aligned
     union {
 
        cmsUInt16Number n;
-       char str[2];
+       cmsUInt8Number str[2];
        
     } c;
 
-    c.n = n;  // Always big endian in this case
+    c.n = _cmsAdjustEndianess16(n);  
 
-    str[0] = c.str[0]; str[1] = c.str[1]; str[2] = 0;
+    str[0] = (char) c.str[0]; str[1] = (char) c.str[1]; str[2] = (char) 0;
 
 }
 
@@ -325,7 +326,7 @@
                               cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
 {
     cmsUInt32Number i;
-    cmsInt32Number Best = -1;
+    int Best = -1;
     _cmsMLUentry* v;
 
     if (mlu == NULL) return NULL;
@@ -338,7 +339,7 @@
 
         if (v -> Language == LanguageCode) {
 
-            if (Best == -1) Best = i;
+            if (Best == -1) Best = (int) i;
 
             if (v -> Country == CountryCode) {
 
@@ -517,7 +518,11 @@
         size = v ->Allocated * 2;
 
     // Keep a maximum color lists can grow, 100K entries seems reasonable
-    if (size > 1024*100) return FALSE;
+    if (size > 1024 * 100) {
+        _cmsFree(v->ContextID, (void*) v->List);
+        v->List = NULL;
+        return FALSE;
+    }
 
     NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR));
     if (NewPtr == NULL)
@@ -539,7 +544,7 @@
     v ->nColors   = 0;
     v ->ContextID  = ContextID;
 
-    while (v -> Allocated < n){
+    while (v -> Allocated < n) {
         if (!GrowNamedColorList(v)) {
             cmsFreeNamedColorList(v);
             return NULL;
@@ -603,10 +608,10 @@
     }
 
     for (i=0; i < NamedColorList ->ColorantCount; i++)
-        NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL? 0 : Colorant[i];
+        NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL ? (cmsUInt16Number)0 : Colorant[i];
 
     for (i=0; i < 3; i++)
-        NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? 0 : PCS[i];
+        NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? (cmsUInt16Number) 0 : PCS[i];
 
     if (Name != NULL) {
 
@@ -641,6 +646,7 @@
 
     if (nColor >= cmsNamedColorCount(NamedColorList)) return FALSE;
 
+    // strcpy instead of strncpy because many apps are using small buffers
     if (Name) strcpy(Name, NamedColorList->List[nColor].Name);
     if (Prefix) strcpy(Prefix, NamedColorList->Prefix);
     if (Suffix) strcpy(Suffix, NamedColorList->Suffix);
@@ -658,13 +664,14 @@
 // Search for a given color name (no prefix or suffix)
 cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* NamedColorList, const char* Name)
 {
-    int i, n;
+    cmsUInt32Number i;
+    cmsUInt32Number n;
 
     if (NamedColorList == NULL) return -1;
     n = cmsNamedColorCount(NamedColorList);
     for (i=0; i < n; i++) {
         if (cmsstrcasecmp(Name,  NamedColorList->List[i].Name) == 0)
-            return i;
+            return (cmsInt32Number) i;
     }
 
     return -1;
@@ -693,7 +700,8 @@
     cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0);
 
     if (index >= NamedColorList-> nColors) {
-        cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index);
+        cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range", index);
+        Out[0] = Out[1] = Out[2] = 0.0f;
     }
     else {
 
@@ -712,7 +720,10 @@
     cmsUInt32Number j;
 
     if (index >= NamedColorList-> nColors) {
-        cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index);
+        cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range", index);
+        for (j = 0; j < NamedColorList->ColorantCount; j++)
+            Out[j] = 0.0f;
+
     }
     else {
         for (j=0; j < NamedColorList ->ColorantCount; j++)
diff --git a/third_party/lcms/src/cmsopt.c b/third_party/lcms/src/cmsopt.c
index abe26b9..5ea1b4c 100644
--- a/third_party/lcms/src/cmsopt.c
+++ b/third_party/lcms/src/cmsopt.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -49,8 +49,8 @@
     cmsContext ContextID;
 
     // Number of channels
-    int nInputs;
-    int nOutputs;
+    cmsUInt32Number nInputs;
+    cmsUInt32Number nOutputs;
 
     _cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS];       // The maximum number of input channels is known in advance
     cmsInterpParams*  ParamsCurveIn16[MAX_INPUT_DIMENSIONS];
@@ -94,8 +94,8 @@
 
     cmsContext ContextID;
 
-    int nCurves;                  // Number of curves
-    int nElements;                // Elements in curves
+    cmsUInt32Number nCurves;      // Number of curves
+    cmsUInt32Number nElements;    // Elements in curves
     cmsUInt16Number** Curves;     // Points to a dynamically  allocated array
 
 } Curves16Data;
@@ -216,7 +216,7 @@
                      // Multiply both matrices to get the result
                      _cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double);
 
-                     // Get the next in chain afer the matrices
+                     // Get the next in chain after the matrices
                      chain = (*pt2)->Next;
 
                      // Remove both matrices
@@ -305,7 +305,7 @@
     Prelin16Data* p16 = (Prelin16Data*) D;
     cmsUInt16Number  StageABC[MAX_INPUT_DIMENSIONS];
     cmsUInt16Number  StageDEF[cmsMAXCHANNELS];
-    int i;
+    cmsUInt32Number i;
 
     for (i=0; i < p16 ->nInputs; i++) {
 
@@ -350,15 +350,15 @@
 static
 Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
                                const cmsInterpParams* ColorMap,
-                               int nInputs, cmsToneCurve** In,
-                               int nOutputs, cmsToneCurve** Out )
+                               cmsUInt32Number nInputs, cmsToneCurve** In,
+                               cmsUInt32Number nOutputs, cmsToneCurve** Out )
 {
-    int i;
+    cmsUInt32Number i;
     Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data));
     if (p16 == NULL) return NULL;
 
     p16 ->nInputs = nInputs;
-    p16 -> nOutputs = nOutputs;
+    p16 ->nOutputs = nOutputs;
 
 
     for (i=0; i < nInputs; i++) {
@@ -406,7 +406,7 @@
 // Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for
 // almost any transform. We use floating point precision and then convert from floating point to 16 bits.
 static
-int XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
+cmsInt32Number XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 {
     cmsPipeline* Lut = (cmsPipeline*) Cargo;
     cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
@@ -453,7 +453,7 @@
 // is to fix scum dot on broken profiles/transforms. Works on 1, 3 and 4 channels
 static
 cmsBool  PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[],
-                  int nChannelsOut, int nChannelsIn)
+                  cmsUInt32Number nChannelsOut, cmsUInt32Number nChannelsIn)
 {
     _cmsStageCLutData* Grid = (_cmsStageCLutData*) CLUT ->Data;
     cmsInterpParams* p16  = Grid ->Params;
@@ -483,10 +483,10 @@
             ((pz - z0) != 0) ||
             ((pw - w0) != 0)) return FALSE; // Not on exact node
 
-        index = p16 -> opta[3] * x0 +
-                p16 -> opta[2] * y0 +
-                p16 -> opta[1] * z0 +
-                p16 -> opta[0] * w0;
+        index = (int) p16 -> opta[3] * x0 +
+                (int) p16 -> opta[2] * y0 +
+                (int) p16 -> opta[1] * z0 +
+                (int) p16 -> opta[0] * w0;
     }
     else
         if (nChannelsIn == 3) {
@@ -503,9 +503,9 @@
                 ((py - y0) != 0) ||
                 ((pz - z0) != 0)) return FALSE;  // Not on exact node
 
-            index = p16 -> opta[2] * x0 +
-                    p16 -> opta[1] * y0 +
-                    p16 -> opta[0] * z0;
+            index = (int) p16 -> opta[2] * x0 +
+                    (int) p16 -> opta[1] * y0 +
+                    (int) p16 -> opta[0] * z0;
         }
         else
             if (nChannelsIn == 1) {
@@ -516,24 +516,24 @@
                 
                 if (((px - x0) != 0)) return FALSE; // Not on exact node
 
-                index = p16 -> opta[0] * x0;
+                index = (int) p16 -> opta[0] * x0;
             }
             else {
                 cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn);
                 return FALSE;
             }
 
-            for (i=0; i < nChannelsOut; i++)
-                Grid -> Tab.T[index + i] = Value[i];
+            for (i = 0; i < (int) nChannelsOut; i++)
+                Grid->Tab.T[index + i] = Value[i];
 
             return TRUE;
 }
 
 // Auxiliary, to see if two values are equal or very different
 static
-cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] )
+cmsBool WhitesAreEqual(cmsUInt32Number n, cmsUInt16Number White1[], cmsUInt16Number White2[] )
 {
-    int i;
+    cmsUInt32Number i;
 
     for (i=0; i < n; i++) {
 
@@ -635,7 +635,7 @@
     cmsStage* mpe;
     cmsStage* CLUT;
     cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
-    int nGridPoints;
+    cmsUInt32Number nGridPoints;
     cmsColorSpaceSignature ColorSpace, OutputColorSpace;
     cmsStage *NewPreLin = NULL;
     cmsStage *NewPostLin = NULL;
@@ -647,8 +647,13 @@
     // This is a loosy optimization! does not apply in floating-point cases
     if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
 
-    ColorSpace       = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat));
-    OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat));
+    ColorSpace       = _cmsICCcolorSpace((int) T_COLORSPACE(*InputFormat));
+    OutputColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*OutputFormat));
+
+    // Color space must be specified
+    if (ColorSpace == (cmsColorSpaceSignature)0 ||
+        OutputColorSpace == (cmsColorSpaceSignature)0) return FALSE;
+
     nGridPoints      = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);
 
     // For empty LUTs, 2 points are enough
@@ -686,7 +691,7 @@
                     goto Error;
 
                 // Remove prelinearization. Since we have duplicated the curve
-                // in destination LUT, the sampling shoud be applied after this stage.
+                // in destination LUT, the sampling should be applied after this stage.
                 cmsPipelineUnlinkStage(Src, cmsAT_BEGIN, &KeepPreLin);
             }
         }
@@ -718,14 +723,14 @@
                 if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin))
                     goto Error;
 
-                // In destination LUT, the sampling shoud be applied after this stage.
+                // In destination LUT, the sampling should be applied after this stage.
                 cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin);
             }
         }
     }
 
     // Now its time to do the sampling. We have to ignore pre/post linearization
-    // The source LUT whithout pre/post curves is passed as parameter.
+    // The source LUT without pre/post curves is passed as parameter.
     if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) {
 Error:
         // Ops, something went wrong, Restore stages
@@ -805,7 +810,7 @@
 {
     int BeginVal, EndVal;
     int AtBegin = (int) floor((cmsFloat64Number) g ->nEntries * 0.02 + 0.5);   // Cutoff at 2%
-    int AtEnd   = g ->nEntries - AtBegin - 1;                                  // And 98%
+    int AtEnd   = (int) g ->nEntries - AtBegin - 1;                                  // And 98%
     cmsFloat64Number Val, Slope, beta;
     int i;
 
@@ -866,9 +871,9 @@
 
 
         // Move to 0..1.0 in fixed domain
-        v1 = _cmsToFixedDomain(Input[0] * p -> Domain[0]);
-        v2 = _cmsToFixedDomain(Input[1] * p -> Domain[1]);
-        v3 = _cmsToFixedDomain(Input[2] * p -> Domain[2]);
+        v1 = _cmsToFixedDomain((int) (Input[0] * p -> Domain[0]));
+        v2 = _cmsToFixedDomain((int) (Input[1] * p -> Domain[1]));
+        v3 = _cmsToFixedDomain((int) (Input[2] * p -> Domain[2]));
 
         // Store the precalculated table of nodes
         p8 ->X0[i] = (p->opta[2] * FIXED_TO_INT(v1));
@@ -913,27 +918,27 @@
     cmsS15Fixed16Number    rx, ry, rz;
     cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
     int                    OutChan;
-    register cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
+    register cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
     Prelin8Data* p8 = (Prelin8Data*) D;
     register const cmsInterpParams* p = p8 ->p;
-    int                    TotalOut = p -> nOutputs;
+    int                    TotalOut = (int) p -> nOutputs;
     const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table;
 
-    r = Input[0] >> 8;
-    g = Input[1] >> 8;
-    b = Input[2] >> 8;
+    r = (cmsUInt8Number) (Input[0] >> 8);
+    g = (cmsUInt8Number) (Input[1] >> 8);
+    b = (cmsUInt8Number) (Input[2] >> 8);
 
-    X0 = X1 = p8->X0[r];
-    Y0 = Y1 = p8->Y0[g];
-    Z0 = Z1 = p8->Z0[b];
+    X0 = X1 = (cmsS15Fixed16Number) p8->X0[r];
+    Y0 = Y1 = (cmsS15Fixed16Number) p8->Y0[g];
+    Z0 = Z1 = (cmsS15Fixed16Number) p8->Z0[b];
 
     rx = p8 ->rx[r];
     ry = p8 ->ry[g];
     rz = p8 ->rz[b];
 
-    X1 = X0 + ((rx == 0) ? 0 : p ->opta[2]);
-    Y1 = Y0 + ((ry == 0) ? 0 : p ->opta[1]);
-    Z1 = Z0 + ((rz == 0) ? 0 : p ->opta[0]);
+    X1 = X0 + (cmsS15Fixed16Number)((rx == 0) ? 0 :  p ->opta[2]);
+    Y1 = Y0 + (cmsS15Fixed16Number)((ry == 0) ? 0 :  p ->opta[1]);
+    Z1 = Z0 + (cmsS15Fixed16Number)((rz == 0) ? 0 :  p ->opta[0]);
 
 
     // These are the 6 Tetrahedral
@@ -986,9 +991,8 @@
                                 c1 = c2 = c3 = 0;
                             }
 
-
                             Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
-                            Output[OutChan] = (cmsUInt16Number)c0 + ((Rest + (Rest>>16))>>16);
+                            Output[OutChan] = (cmsUInt16Number) (c0 + ((Rest + (Rest >> 16)) >> 16));
 
     }
 }
@@ -1000,8 +1004,8 @@
 static
 cmsBool IsDegenerated(const cmsToneCurve* g)
 {
-    int i, Zeros = 0, Poles = 0;
-    int nEntries = g ->nEntries;
+    cmsUInt32Number i, Zeros = 0, Poles = 0;
+    cmsUInt32Number nEntries = g ->nEntries;
 
     for (i=0; i < nEntries; i++) {
 
@@ -1023,7 +1027,7 @@
 cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
 {
     cmsPipeline* OriginalLut;
-    int nGridPoints;
+    cmsUInt32Number nGridPoints;
     cmsToneCurve *Trans[cmsMAXCHANNELS], *TransReverse[cmsMAXCHANNELS];
     cmsUInt32Number t, i;
     cmsFloat32Number v, In[cmsMAXCHANNELS], Out[cmsMAXCHANNELS];
@@ -1061,8 +1065,13 @@
             if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
     }
 
-    ColorSpace       = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat));
-    OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat));
+    ColorSpace       = _cmsICCcolorSpace((int) T_COLORSPACE(*InputFormat));
+    OutputColorSpace = _cmsICCcolorSpace((int) T_COLORSPACE(*OutputFormat));
+
+    // Color space must be specified
+    if (ColorSpace == (cmsColorSpaceSignature)0 ||
+        OutputColorSpace == (cmsColorSpaceSignature)0) return FALSE;
+
     nGridPoints      = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);
 
     // Empty gamma containers
@@ -1231,6 +1240,7 @@
     return FALSE;
 
     cmsUNUSED_PARAMETER(Intent);
+    cmsUNUSED_PARAMETER(lIsLinear);
 }
 
 
@@ -1240,7 +1250,7 @@
 void CurvesFree(cmsContext ContextID, void* ptr)
 {
      Curves16Data* Data = (Curves16Data*) ptr;
-     int i;
+     cmsUInt32Number i;
 
      for (i=0; i < Data -> nCurves; i++) {
 
@@ -1255,7 +1265,7 @@
 void* CurvesDup(cmsContext ContextID, const void* ptr)
 {
     Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
-    int i;
+    cmsUInt32Number i;
 
     if (Data == NULL) return NULL;
 
@@ -1270,9 +1280,9 @@
 
 // Precomputes tables for 8-bit on input devicelink.
 static
-Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsToneCurve** G)
+Curves16Data* CurvesAlloc(cmsContext ContextID, cmsUInt32Number nCurves, cmsUInt32Number nElements, cmsToneCurve** G)
 {
-    int i, j;
+    cmsUInt32Number i, j;
     Curves16Data* c16;
 
     c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data));
@@ -1282,7 +1292,10 @@
     c16 ->nElements = nElements;
 
     c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
-    if (c16 ->Curves == NULL) return NULL;
+    if (c16->Curves == NULL) {
+        _cmsFree(ContextID, c16);
+        return NULL;
+    }
 
     for (i=0; i < nCurves; i++) {
 
@@ -1298,7 +1311,7 @@
             return NULL;
         }
 
-        if (nElements == 256) {
+        if (nElements == 256U) {
 
             for (j=0; j < nElements; j++) {
 
@@ -1322,8 +1335,8 @@
                           register const void* D)
 {
     Curves16Data* Data = (Curves16Data*) D;
-    cmsUInt8Number x;
-    int i;
+    int x;
+    cmsUInt32Number i;
 
     for (i=0; i < Data ->nCurves; i++) {
 
@@ -1339,7 +1352,7 @@
                           register const void* D)
 {
     Curves16Data* Data = (Curves16Data*) D;
-    int i;
+    cmsUInt32Number i;
 
     for (i=0; i < Data ->nCurves; i++) {
          Out[i] = Data -> Curves[i][In[i]];
@@ -1454,6 +1467,7 @@
 
         // LUT optimizes to nothing. Set the identity LUT
         cmsStageFree(ObtainedCurves);
+        ObtainedCurves = NULL;
 
         if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)))
             goto Error;
@@ -1518,9 +1532,9 @@
 
     // In this case (and only in this case!) we can use this simplification since
     // In[] is assured to come from a 8 bit number. (a << 8 | a)
-    ri = In[0] & 0xFF;
-    gi = In[1] & 0xFF;
-    bi = In[2] & 0xFF;
+    ri = In[0] & 0xFFU;
+    gi = In[1] & 0xFFU;
+    bi = In[2] & 0xFFU;
 
     // Across first shaper, which also converts to 1.14 fixed point
     r = p->Shaper1R[ri];
@@ -1533,9 +1547,9 @@
     l3 =  (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14;
 
     // Now we have to clip to 0..1.0 range
-    ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384 : l1);
-    gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384 : l2);
-    bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384 : l3);
+    ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384U : (cmsUInt32Number) l1);
+    gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384U : (cmsUInt32Number) l2);
+    bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384U : (cmsUInt32Number) l3);
 
     // And across second shaper,
     Out[0] = p->Shaper2R[ri];
@@ -1546,7 +1560,7 @@
 
 // This table converts from 8 bits to 1.14 after applying the curve
 static
-cmsBool FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
+void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
 {
     int i;
     cmsFloat32Number R, y;
@@ -1555,17 +1569,17 @@
 
         R   = (cmsFloat32Number) (i / 255.0);
         y   = cmsEvalToneCurveFloat(Curve, R);
-        if (isinf(y))
-            return FALSE;
 
-        Table[i] = DOUBLE_TO_1FIXED14(y);
+        if (y < 131072.0)
+            Table[i] = DOUBLE_TO_1FIXED14(y);
+        else
+            Table[i] = 0x7fffffff;
     }
-    return TRUE;
 }
 
 // This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve
 static
-cmsBool FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput)
+void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput)
 {
     int i;
     cmsFloat32Number R, Val;
@@ -1574,8 +1588,12 @@
 
         R   = (cmsFloat32Number) (i / 16384.0);
         Val = cmsEvalToneCurveFloat(Curve, R);    // Val comes 0..1.0
-        if (isinf(Val))
-            return FALSE;
+
+        if (Val < 0)
+            Val = 0;
+
+        if (Val > 1.0)
+            Val = 1.0;
 
         if (Is8BitsOutput) {
 
@@ -1590,7 +1608,6 @@
         }
         else Table[i]  = _cmsQuickSaturateWord(Val * 65535.0);
     }
-    return TRUE;
 }
 
 // Compute the matrix-shaper structure
@@ -1608,21 +1625,15 @@
     p -> ContextID = Dest -> ContextID;
 
     // Precompute tables
-    if (!FillFirstShaper(p ->Shaper1R, Curve1[0]))
-        goto Error;
-    if (!FillFirstShaper(p ->Shaper1G, Curve1[1]))
-        goto Error;
-    if (!FillFirstShaper(p ->Shaper1B, Curve1[2]))
-        goto Error;
+    FillFirstShaper(p ->Shaper1R, Curve1[0]);
+    FillFirstShaper(p ->Shaper1G, Curve1[1]);
+    FillFirstShaper(p ->Shaper1B, Curve1[2]);
 
-    if (!FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits))
-        goto Error;
-    if (!FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits))
-        goto Error;
-    if (!FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits))
-        goto Error;
+    FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits);
+    FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits);
+    FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits);
 
-    // Convert matrix to nFixed14. Note that those values may take more than 16 bits as
+    // Convert matrix to nFixed14. Note that those values may take more than 16 bits 
     for (i=0; i < 3; i++) {
         for (j=0; j < 3; j++) {
             p ->Mat[i][j] = DOUBLE_TO_1FIXED14(Mat->v[i].n[j]);
@@ -1646,9 +1657,6 @@
     // Fill function pointers
     _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper);
     return TRUE;
-    Error:
-        _cmsFree(Dest->ContextID, p);
-        return FALSE;
 }
 
 //  8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast!
@@ -1761,8 +1769,7 @@
         *dwFlags |= cmsFLAGS_NOCACHE;
 
         // Setup the optimizarion routines
-        if (!SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat))
-            goto Error;
+        SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
     }
 
     cmsPipelineFree(Src);
@@ -1888,7 +1895,7 @@
 // The entry point for LUT optimization
 cmsBool _cmsOptimizePipeline(cmsContext ContextID,
                              cmsPipeline**    PtrLut,
-                             int              Intent,
+                             cmsUInt32Number  Intent,
                              cmsUInt32Number* InputFormat,
                              cmsUInt32Number* OutputFormat,
                              cmsUInt32Number* dwFlags)
diff --git a/third_party/lcms/src/cmspack.c b/third_party/lcms/src/cmspack.c
index e711ece..84b0097 100644
--- a/third_party/lcms/src/cmspack.c
+++ b/third_party/lcms/src/cmspack.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -97,21 +97,21 @@
                                   register cmsUInt8Number* accum,
                                   register cmsUInt32Number Stride)
 {
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
     cmsUInt16Number v;
-    int i;
+    cmsUInt32Number i;
 
     if (ExtraFirst) {
         accum += Extra;
     }
 
     for (i=0; i < nChan; i++) {
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         v = FROM_8_TO_16(*accum);
         v = Reverse ? REVERSE_FLAVOR_16(v) : v;
@@ -144,11 +144,11 @@
                                   register cmsUInt8Number* accum,
                                   register cmsUInt32Number Stride)
 {
-    int nChan     = T_CHANNELS(info -> InputFormat);
-    int DoSwap    = T_DOSWAP(info ->InputFormat);
-    int SwapFirst = T_SWAPFIRST(info ->InputFormat);
-    int Reverse   = T_FLAVOR(info ->InputFormat);
-    int i;
+    cmsUInt32Number nChan     = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap    = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->InputFormat);
+    cmsUInt32Number Reverse   = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number i;
     cmsUInt8Number* Init = accum;
 
     if (DoSwap ^ SwapFirst) {
@@ -157,7 +157,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
         cmsUInt16Number v = FROM_8_TO_16(*accum);
 
         wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
@@ -474,14 +474,14 @@
                                register cmsUInt8Number* accum,
                                register cmsUInt32Number Stride)
 {
-    int nChan       = T_CHANNELS(info -> InputFormat);
-    int SwapEndian  = T_ENDIAN16(info -> InputFormat);
-    int DoSwap      = T_DOSWAP(info ->InputFormat);
-    int Reverse     = T_FLAVOR(info ->InputFormat);
-    int SwapFirst   = T_SWAPFIRST(info -> InputFormat);
-    int Extra       = T_EXTRA(info -> InputFormat);
-    int ExtraFirst  = DoSwap ^ SwapFirst;
-    int i;
+   cmsUInt32Number nChan       = T_CHANNELS(info -> InputFormat);
+   cmsUInt32Number SwapEndian  = T_ENDIAN16(info -> InputFormat);
+   cmsUInt32Number DoSwap      = T_DOSWAP(info ->InputFormat);
+   cmsUInt32Number Reverse     = T_FLAVOR(info ->InputFormat);
+   cmsUInt32Number SwapFirst   = T_SWAPFIRST(info -> InputFormat);
+   cmsUInt32Number Extra       = T_EXTRA(info -> InputFormat);
+   cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
+   cmsUInt32Number i;
 
     if (ExtraFirst) {
         accum += Extra * sizeof(cmsUInt16Number);
@@ -489,7 +489,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
         cmsUInt16Number v = *(cmsUInt16Number*) accum;
 
         if (SwapEndian)
@@ -523,11 +523,11 @@
                                   register cmsUInt8Number* accum,
                                   register cmsUInt32Number Stride)
 {
-    int nChan = T_CHANNELS(info -> InputFormat);
-    int DoSwap= T_DOSWAP(info ->InputFormat);
-    int Reverse= T_FLAVOR(info ->InputFormat);
-    int SwapEndian = T_ENDIAN16(info -> InputFormat);
-    int i;
+    cmsUInt32Number nChan = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap= T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse= T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> InputFormat);
+    cmsUInt32Number i;
     cmsUInt8Number* Init = accum;
 
     if (DoSwap) {
@@ -536,7 +536,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
         cmsUInt16Number v = *(cmsUInt16Number*) accum;
 
         if (SwapEndian)
@@ -921,17 +921,17 @@
                                 register cmsUInt32Number Stride)
 {
 
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
-    int Planar     = T_PLANAR(info -> InputFormat);
+    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
     cmsFloat64Number v;
     cmsUInt16Number  vi;
-    int i, start = 0;
-   cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
+    cmsUInt32Number i, start = 0;
+    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
 
 
     if (ExtraFirst)
@@ -939,7 +939,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         if (Planar)
             v = (cmsFloat32Number) ((cmsFloat64Number*) accum)[(i + start) * Stride];
@@ -977,17 +977,17 @@
                                 register cmsUInt32Number Stride)
 {
 
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
-    int Planar     = T_PLANAR(info -> InputFormat);
+    cmsUInt32Number nChan  = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap   = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra   = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
     cmsFloat32Number v;
     cmsUInt16Number  vi;
-    int i, start = 0;
-   cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
+    cmsUInt32Number i, start = 0;
+    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
 
 
     if (ExtraFirst)
@@ -995,7 +995,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         if (Planar)
             v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
@@ -1054,15 +1054,15 @@
                                     cmsUInt32Number Stride)
 {
 
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
-    int Planar     = T_PLANAR(info -> InputFormat);
+    cmsUInt32Number nChan  = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap   = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra   = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
     cmsFloat32Number v;
-    int i, start = 0;
+    cmsUInt32Number i, start = 0;
     cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
 
 
@@ -1071,7 +1071,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         if (Planar)
             v = (cmsFloat32Number) ((cmsFloat32Number*) accum)[(i + start) * Stride];
@@ -1106,15 +1106,15 @@
                                     cmsUInt32Number Stride)
 {
 
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
-    int Planar     = T_PLANAR(info -> InputFormat);
+    cmsUInt32Number nChan  = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap   = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra   = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
     cmsFloat64Number v;
-    int i, start = 0;
+    cmsUInt32Number i, start = 0;
     cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
 
 
@@ -1123,7 +1123,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         if (Planar)
             v = (cmsFloat64Number) ((cmsFloat64Number*) accum)[(i + start)  * Stride];
@@ -1277,15 +1277,15 @@
                              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 ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number nChan  = T_CHANNELS(info -> OutputFormat);
+    cmsUInt32Number DoSwap   = T_DOSWAP(info ->OutputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->OutputFormat);
+    cmsUInt32Number Extra   = T_EXTRA(info -> OutputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
     cmsUInt8Number* swap1;
     cmsUInt8Number v = 0;
-    int i;
+    cmsUInt32Number i;
 
     swap1 = output;
 
@@ -1295,7 +1295,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         v = FROM_16_TO_8(wOut[index]);
 
@@ -1329,16 +1329,16 @@
                              register cmsUInt8Number* output,
                              register cmsUInt32Number Stride)
 {
-    int nChan      = T_CHANNELS(info -> OutputFormat);
-    int SwapEndian = T_ENDIAN16(info -> InputFormat);
-    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 ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number nChan  = T_CHANNELS(info -> OutputFormat);
+    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat);
+    cmsUInt32Number DoSwap   = T_DOSWAP(info ->OutputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->OutputFormat);
+    cmsUInt32Number Extra   = T_EXTRA(info -> OutputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
     cmsUInt16Number* swap1;
     cmsUInt16Number v = 0;
-    int i;
+    cmsUInt32Number i;
 
     swap1 = (cmsUInt16Number*) output;
 
@@ -1348,7 +1348,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         v = wOut[index];
 
@@ -1386,11 +1386,11 @@
                                 register cmsUInt8Number* output,
                                 register cmsUInt32Number Stride)
 {
-    int nChan     = T_CHANNELS(info -> OutputFormat);
-    int DoSwap    = T_DOSWAP(info ->OutputFormat);
-    int SwapFirst = T_SWAPFIRST(info ->OutputFormat);
-    int Reverse   = T_FLAVOR(info ->OutputFormat);
-    int i;
+    cmsUInt32Number nChan     = T_CHANNELS(info -> OutputFormat);
+    cmsUInt32Number DoSwap    = T_DOSWAP(info ->OutputFormat);
+    cmsUInt32Number SwapFirst = T_SWAPFIRST(info ->OutputFormat);
+    cmsUInt32Number Reverse   = T_FLAVOR(info ->OutputFormat);
+    cmsUInt32Number i;
     cmsUInt8Number* Init = output;
 
 
@@ -1401,7 +1401,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
         cmsUInt8Number v = FROM_16_TO_8(wOut[index]);
 
         *(cmsUInt8Number*)  output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v);
@@ -1420,11 +1420,11 @@
                                 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 SwapEndian = T_ENDIAN16(info -> OutputFormat);
-    int i;
+    cmsUInt32Number nChan      = T_CHANNELS(info -> OutputFormat);
+    cmsUInt32Number DoSwap     = T_DOSWAP(info ->OutputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->OutputFormat);
+    cmsUInt32Number SwapEndian = T_ENDIAN16(info -> OutputFormat);
+    cmsUInt32Number i;
     cmsUInt8Number* Init = output;
     cmsUInt16Number v;
 
@@ -1434,7 +1434,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         v = wOut[index];
 
@@ -1794,9 +1794,9 @@
                                     register cmsUInt8Number* output,
                                     register cmsUInt32Number Stride)
 {
-    *output++ = (wOut[0] & 0xFF);
-    *output++ = (wOut[1] & 0xFF);
-    *output++ = (wOut[2] & 0xFF);
+    *output++ = (wOut[0] & 0xFFU);
+    *output++ = (wOut[1] & 0xFFU);
+    *output++ = (wOut[2] & 0xFFU);
 
     return output;
 
@@ -1826,9 +1826,9 @@
                                         register cmsUInt8Number* output,
                                         register cmsUInt32Number Stride)
 {
-    *output++ = (wOut[2] & 0xFF);
-    *output++ = (wOut[1] & 0xFF);
-    *output++ = (wOut[0] & 0xFF);
+    *output++ = (wOut[2] & 0xFFU);
+    *output++ = (wOut[1] & 0xFFU);
+    *output++ = (wOut[0] & 0xFFU);
 
     return output;
 
@@ -1917,9 +1917,9 @@
                                             register cmsUInt8Number* output,
                                             register cmsUInt32Number Stride)
 {
-    *output++ = (wOut[0] & 0xFF);
-    *output++ = (wOut[1] & 0xFF);
-    *output++ = (wOut[2] & 0xFF);
+    *output++ = (wOut[0] & 0xFFU);
+    *output++ = (wOut[1] & 0xFFU);
+    *output++ = (wOut[2] & 0xFFU);
     output++;
 
     return output;
@@ -1953,9 +1953,9 @@
                                                      register cmsUInt32Number Stride)
 {
     output++;
-    *output++ = (wOut[0] & 0xFF);
-    *output++ = (wOut[1] & 0xFF);
-    *output++ = (wOut[2] & 0xFF);
+    *output++ = (wOut[0] & 0xFFU);
+    *output++ = (wOut[1] & 0xFFU);
+    *output++ = (wOut[2] & 0xFFU);
 
     return output;
 
@@ -1987,9 +1987,9 @@
                                                 register cmsUInt32Number Stride)
 {
     output++;
-    *output++ = (wOut[2] & 0xFF);
-    *output++ = (wOut[1] & 0xFF);
-    *output++ = (wOut[0] & 0xFF);
+    *output++ = (wOut[2] & 0xFFU);
+    *output++ = (wOut[1] & 0xFFU);
+    *output++ = (wOut[0] & 0xFFU);
 
     return output;
 
@@ -2021,9 +2021,9 @@
                                                          register cmsUInt8Number* output,
                                                          register cmsUInt32Number Stride)
 {
-    *output++ = (wOut[2] & 0xFF);
-    *output++ = (wOut[1] & 0xFF);
-    *output++ = (wOut[0] & 0xFF);
+    *output++ = (wOut[2] & 0xFFU);
+    *output++ = (wOut[1] & 0xFFU);
+    *output++ = (wOut[0] & 0xFFU);
     output++;
 
     return output;
@@ -2379,24 +2379,24 @@
                                 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;
+    cmsUInt32Number nChan      = T_CHANNELS(info -> OutputFormat);
+    cmsUInt32Number DoSwap     = T_DOSWAP(info ->OutputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->OutputFormat);
+    cmsUInt32Number Extra      = T_EXTRA(info -> OutputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
+    cmsUInt32Number Planar     = T_PLANAR(info -> OutputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
     cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;
     cmsFloat64Number v = 0;
     cmsFloat64Number* swap1 = (cmsFloat64Number*) output;
-    int i, start = 0;
+    cmsUInt32Number i, start = 0;
 
     if (ExtraFirst)
         start = Extra;
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         v = (cmsFloat64Number) wOut[index] / maximum;
 
@@ -2430,24 +2430,24 @@
                                 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;
+       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
+       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
+       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
+       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
+       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
+       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
+       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
        cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
        cmsFloat64Number v = 0;
        cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
-       int i, start = 0;
+       cmsUInt32Number i, start = 0;
 
        if (ExtraFirst)
               start = Extra;
 
        for (i = 0; i < nChan; i++) {
 
-              int index = DoSwap ? (nChan - i - 1) : i;
+              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
               v = (cmsFloat64Number)wOut[index] / maximum;
 
@@ -2483,24 +2483,24 @@
                                     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;
+       cmsUInt32Number nChan = T_CHANNELS(info->OutputFormat);
+       cmsUInt32Number DoSwap = T_DOSWAP(info->OutputFormat);
+       cmsUInt32Number Reverse = T_FLAVOR(info->OutputFormat);
+       cmsUInt32Number Extra = T_EXTRA(info->OutputFormat);
+       cmsUInt32Number SwapFirst = T_SWAPFIRST(info->OutputFormat);
+       cmsUInt32Number Planar = T_PLANAR(info->OutputFormat);
+       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
        cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
        cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
        cmsFloat64Number v = 0;
-       int i, start = 0;
+       cmsUInt32Number i, start = 0;
 
        if (ExtraFirst)
               start = Extra;
 
        for (i = 0; i < nChan; i++) {
 
-              int index = DoSwap ? (nChan - i - 1) : i;
+              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
               v = wOut[index] * maximum;
 
@@ -2532,24 +2532,24 @@
                                     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;
+       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
+       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
+       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
+       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
+       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
+       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
+       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
        cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
        cmsFloat64Number v = 0;
        cmsFloat64Number* swap1 = (cmsFloat64Number*)output;
-       int i, start = 0;
+       cmsUInt32Number i, start = 0;
 
        if (ExtraFirst)
               start = Extra;
 
        for (i = 0; i < nChan; i++) {
 
-              int index = DoSwap ? (nChan - i - 1) : i;
+              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
               v = wOut[index] * maximum;
 
@@ -2706,15 +2706,15 @@
                                 register cmsUInt32Number Stride)
 {
 
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
-    int Planar     = T_PLANAR(info -> InputFormat);
+    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
     cmsFloat32Number v;
-    int i, start = 0;
+    cmsUInt32Number i, start = 0;
     cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 655.35F : 65535.0F;
 
 
@@ -2723,7 +2723,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         if (Planar)
             v = _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );
@@ -2758,15 +2758,15 @@
                                     cmsUInt32Number Stride)
 {
 
-    int nChan      = T_CHANNELS(info -> InputFormat);
-    int DoSwap     = T_DOSWAP(info ->InputFormat);
-    int Reverse    = T_FLAVOR(info ->InputFormat);
-    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
-    int Extra      = T_EXTRA(info -> InputFormat);
-    int ExtraFirst = DoSwap ^ SwapFirst;
-    int Planar     = T_PLANAR(info -> InputFormat);
+    cmsUInt32Number nChan      = T_CHANNELS(info -> InputFormat);
+    cmsUInt32Number DoSwap     = T_DOSWAP(info ->InputFormat);
+    cmsUInt32Number Reverse    = T_FLAVOR(info ->InputFormat);
+    cmsUInt32Number SwapFirst  = T_SWAPFIRST(info -> InputFormat);
+    cmsUInt32Number Extra      = T_EXTRA(info -> InputFormat);
+    cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
+    cmsUInt32Number Planar     = T_PLANAR(info -> InputFormat);
     cmsFloat32Number v;
-    int i, start = 0;
+    cmsUInt32Number i, start = 0;
     cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
 
 
@@ -2775,7 +2775,7 @@
 
     for (i=0; i < nChan; i++) {
 
-        int index = DoSwap ? (nChan - i - 1) : i;
+        cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
         if (Planar)
             v =  _cmsHalf2Float ( ((cmsUInt16Number*) accum)[(i + start) * Stride] );
@@ -2808,24 +2808,24 @@
                                 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;
+       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
+       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
+       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
+       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
+       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
+       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
+       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
        cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;
        cmsFloat32Number v = 0;
        cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
-       int i, start = 0;
+       cmsUInt32Number i, start = 0;
 
        if (ExtraFirst)
               start = Extra;
 
        for (i = 0; i < nChan; i++) {
 
-              int index = DoSwap ? (nChan - i - 1) : i;
+              cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
               v = (cmsFloat32Number)wOut[index] / maximum;
 
@@ -2859,24 +2859,24 @@
                                     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;
+       cmsUInt32Number nChan      = T_CHANNELS(info->OutputFormat);
+       cmsUInt32Number DoSwap     = T_DOSWAP(info->OutputFormat);
+       cmsUInt32Number Reverse    = T_FLAVOR(info->OutputFormat);
+       cmsUInt32Number Extra      = T_EXTRA(info->OutputFormat);
+       cmsUInt32Number SwapFirst  = T_SWAPFIRST(info->OutputFormat);
+       cmsUInt32Number Planar     = T_PLANAR(info->OutputFormat);
+       cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
        cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;
        cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
        cmsFloat32Number v = 0;
-       int i, start = 0;
+       cmsUInt32Number i, start = 0;
 
        if (ExtraFirst)
               start = Extra;
 
        for (i = 0; i < nChan; i++) {
 
-              int index = DoSwap ? (nChan - i - 1) : i;
+           cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
 
               v = wOut[index] * maximum;
 
@@ -3147,8 +3147,6 @@
                              ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackHalfFromFloat },
 #endif
 
-
-
 };
 
 
@@ -3321,7 +3319,7 @@
 // Return whatever given formatter refers to 8 bits
 cmsBool  _cmsFormatterIs8bit(cmsUInt32Number Type)
 {
-    int Bytes = T_BYTES(Type);
+    cmsUInt32Number Bytes = T_BYTES(Type);
 
     return (Bytes == 1);
 }
@@ -3331,9 +3329,9 @@
 {
 
     cmsColorSpaceSignature ColorSpace      = cmsGetColorSpace(hProfile);
-    cmsUInt32Number        ColorSpaceBits  = _cmsLCMScolorSpace(ColorSpace);
+    cmsUInt32Number        ColorSpaceBits  = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);
     cmsUInt32Number        nOutputChans    = cmsChannelsOf(ColorSpace);
-    cmsUInt32Number        Float           = lIsFloat ? 1 : 0;
+    cmsUInt32Number        Float           = lIsFloat ? 1U : 0;
 
     // Create a fake formatter for result
     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
@@ -3343,10 +3341,11 @@
 cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
 {
 
-    cmsColorSpaceSignature ColorSpace      = cmsGetPCS(hProfile);
-    int                    ColorSpaceBits  = _cmsLCMScolorSpace(ColorSpace);
-    cmsUInt32Number        nOutputChans    = cmsChannelsOf(ColorSpace);
-    cmsUInt32Number        Float           = lIsFloat ? 1 : 0;
+    cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
+
+    cmsUInt32Number ColorSpaceBits = (cmsUInt32Number) _cmsLCMScolorSpace(ColorSpace);
+    cmsUInt32Number nOutputChans = cmsChannelsOf(ColorSpace);
+    cmsUInt32Number Float = lIsFloat ? 1U : 0;
 
     // Create a fake formatter for result
     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
diff --git a/third_party/lcms/src/cmspcs.c b/third_party/lcms/src/cmspcs.c
index 0cd8ecb..ea70484 100644
--- a/third_party/lcms/src/cmspcs.c
+++ b/third_party/lcms/src/cmspcs.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -656,9 +656,9 @@
 
 // This function returns a number of gridpoints to be used as LUT table. It assumes same number
 // of gripdpoints in all dimensions. Flags may override the choice.
-int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
+cmsUInt32Number _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
 {
-    int nChannels;
+    cmsUInt32Number nChannels;
 
     // Already specified?
     if (dwFlags & 0x00FF0000) {
@@ -802,7 +802,7 @@
        case PT_MCH14: return cmsSigMCHEData;
        case PT_MCH15: return cmsSigMCHFData;
 
-       default:  return (cmsColorSpaceSignature) (-1);
+       default:  return (cmsColorSpaceSignature) 0;
        }
 }
 
@@ -869,7 +869,7 @@
     case cmsSigMCHFData:
     case cmsSig15colorData:return PT_MCH15;
 
-    default:  return (cmsColorSpaceSignature) (-1);
+    default:  return (cmsColorSpaceSignature) 0;
     }
 }
 
diff --git a/third_party/lcms/src/cmsplugin.c b/third_party/lcms/src/cmsplugin.c
index 80dd8d4..d54b4d1 100644
--- a/third_party/lcms/src/cmsplugin.c
+++ b/third_party/lcms/src/cmsplugin.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -172,19 +172,29 @@
 
     _cmsAssert(io != NULL);
 
-    if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
-            return FALSE;
+    if (io->Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
+        return FALSE;
 
     if (n != NULL) {
 
         tmp = _cmsAdjustEndianess32(tmp);
-        *n = *(cmsFloat32Number*) (void*) &tmp;
-        if (isnan(*n))
-            return FALSE;
+        *n = *(cmsFloat32Number*)(void*)&tmp;
+        
+        // Safeguard which covers against absurd values
+        if (*n > 1E+20 || *n < -1E+20) return FALSE;
+
+        #if defined(_MSC_VER) && _MSC_VER < 1800
+           return TRUE;
+        #elif defined (__BORLANDC__)
+           return TRUE;
+        #else
+
+           // fpclassify() required by C99 (only provided by MSVC >= 1800, VS2013 onwards)
+           return ((fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL));
+        #endif        
     }
 
-    // fpclassify() required by C99
-    return (fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL);
+    return TRUE;
 }
 
 
@@ -197,7 +207,11 @@
     if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)
             return FALSE;
 
-    if (n != NULL) _cmsAdjustEndianess64(n, &tmp);
+    if (n != NULL) {
+
+        _cmsAdjustEndianess64(n, &tmp);
+    }
+
     return TRUE;
 }
 
@@ -212,7 +226,7 @@
             return FALSE;
 
     if (n != NULL) {
-        *n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp));
+        *n = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32(tmp));
     }
 
     return TRUE;
@@ -229,9 +243,9 @@
 
     if (XYZ != NULL) {
 
-        XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X));
-        XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y));
-        XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z));
+        XYZ->X = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.X));
+        XYZ->Y = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Y));
+        XYZ->Z = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Z));
     }
     return TRUE;
 }
@@ -320,7 +334,7 @@
 
     _cmsAssert(io != NULL);
 
-    tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n));
+    tmp = _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(n));
     if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
             return FALSE;
 
@@ -334,9 +348,9 @@
     _cmsAssert(io != NULL);
     _cmsAssert(XYZ != NULL);
 
-    xyz.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->X));
-    xyz.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Y));
-    xyz.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Z));
+    xyz.X = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->X));
+    xyz.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Y));
+    xyz.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Z));
 
     return io -> Write(io,  sizeof(cmsEncodedXYZNumber), &xyz);
 }
@@ -494,7 +508,7 @@
         return FALSE;   // Truncated, which is a fatal error for us
     }
 
-    rc = io ->Write(io, len, Buffer);
+    rc = io ->Write(io, (cmsUInt32Number) len, Buffer);
 
     va_end(args);
 
@@ -754,6 +768,30 @@
     struct _cmsContext_struct* ctx;
     struct _cmsContext_struct  fakeContext;
         
+    // See the comments regarding locking in lcms2_internal.h
+    // for an explanation of why we need the following code.
+#ifdef CMS_IS_WINDOWS_
+#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
+    {
+        static HANDLE _cmsWindowsInitMutex = NULL;
+        static volatile HANDLE* mutex = &_cmsWindowsInitMutex;
+
+        if (*mutex == NULL)
+        {
+            HANDLE p = CreateMutex(NULL, FALSE, NULL);
+            if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL)
+                CloseHandle(p);
+        }
+        if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)
+            return NULL;
+        if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL)
+            InitializeCriticalSection(&_cmsContextPoolHeadMutex);
+        if (*mutex == NULL || !ReleaseMutex(*mutex))
+            return NULL;
+    }
+#endif
+#endif
+
     _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
     
     fakeContext.chunks[UserPtr]     = UserData;
@@ -780,7 +818,7 @@
     ctx ->chunks[MemPlugin]   = &ctx->DefaultMemoryManager;
    
     // Now we can allocate the pool by using default memory manager
-    ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));  // default size about 32 pointers
+    ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));  // default size about 22 pointers
     if (ctx ->MemPool == NULL) {
 
          cmsDeleteContext(ctx);
diff --git a/third_party/lcms/src/cmsps2.c b/third_party/lcms/src/cmsps2.c
index 9635eaf..5802a14 100644
--- a/third_party/lcms/src/cmsps2.c
+++ b/third_party/lcms/src/cmsps2.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -400,7 +400,7 @@
 // Does write the intent
 
 static
-void EmitIntent(cmsIOHANDLER* m, int RenderingIntent)
+void EmitIntent(cmsIOHANDLER* m, cmsUInt32Number RenderingIntent)
 {
     const char *intent;
 
@@ -534,7 +534,7 @@
 // Compare gamma table
 
 static
-cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries)
+cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Number nEntries)
 {
     return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0;
 }
@@ -543,9 +543,9 @@
 // Does write a set of gamma curves
 
 static
-void EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[])
+void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[])
 {
-    int i;
+    cmsUInt32Number i;
 
     for( i=0; i < n; i++ )
     {
@@ -768,7 +768,7 @@
 
 
 static
-int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXYZ* BlackPoint)
+int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Intent, cmsCIEXYZ* BlackPoint)
 {
     const char* PreMaj;
     const char* PostMaj;
@@ -828,14 +828,14 @@
 // Generates a curve from a gray profile
 
 static
-    cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, int Intent)
+cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number Intent)
 {
     cmsToneCurve* Out = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL);
     cmsHPROFILE hXYZ  = cmsCreateXYZProfile();
     cmsHTRANSFORM xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOOPTIMIZE);
     int i;
 
-    if (Out != NULL) {
+    if (Out != NULL && xform != NULL) {
         for (i=0; i < 256; i++) {
 
             cmsUInt8Number Gray = (cmsUInt8Number) i;
@@ -847,8 +847,8 @@
         }
     }
 
-    cmsDeleteTransform(xform);
-    cmsCloseProfile(hXYZ);
+    if (xform) cmsDeleteTransform(xform);
+    if (hXYZ) cmsCloseProfile(hXYZ);
     return Out;
 }
 
@@ -858,7 +858,7 @@
 // a more perceptually uniform space... I do choose Lab.
 
 static
-int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags)
+int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHPROFILE hLab;
     cmsHTRANSFORM xform;
@@ -943,7 +943,6 @@
 
 
 // Does create CSA based on matrix-shaper. Allowed types are gray and RGB based
-
 static
 int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper)
 {
@@ -969,17 +968,17 @@
 
             memmove(&Mat, GetPtrToMatrix(Matrix), sizeof(Mat));
 
-            for (i=0; i < 3; i++)
-                for (j=0; j < 3; j++)
+            for (i = 0; i < 3; i++)
+                for (j = 0; j < 3; j++)
                     Mat.v[i].n[j] *= MAX_ENCODEABLE_XYZ;
 
-            rc = EmitCIEBasedABC(m,  (cmsFloat64Number *) &Mat,
-                                _cmsStageGetPtrToCurveSet(Shaper),
-                                 &BlackPointAdaptedToD50);
+            rc = EmitCIEBasedABC(m, (cmsFloat64Number *)&Mat,
+                _cmsStageGetPtrToCurveSet(Shaper),
+                &BlackPointAdaptedToD50);
         }
-        else  {
+        else {
 
-            cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace.");
+            cmsSignalError(m->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace.");
             return 0;
         }
 
@@ -992,12 +991,12 @@
 // This is a HP extension, and it works in Lab instead of XYZ
 
 static
-int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent)
+int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number Intent)
 {
     cmsHTRANSFORM xform;
     cmsHPROFILE   hLab;
-    int i, nColors;
-    char ColorName[32];
+    cmsUInt32Number i, nColors;
+    char ColorName[cmsMAX_PATH];
     cmsNAMEDCOLORLIST* NamedColorList;
 
     hLab  = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
@@ -1275,20 +1274,20 @@
 // 8 bits.
 
 static
-int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags)
+int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHPROFILE hLab;
     cmsHTRANSFORM xform;
-    int i, nChannels;
+    cmsUInt32Number i, nChannels;
     cmsUInt32Number OutputFormat;
     _cmsTRANSFORM* v;
     cmsPipeline* DeviceLink;
     cmsHPROFILE Profiles[3];
     cmsCIEXYZ BlackPointAdaptedToD50;
-    cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
-    cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
+    cmsBool lDoBPC = (cmsBool) (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
+    cmsBool lFixWhite = (cmsBool) !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
     cmsUInt32Number InFrm = TYPE_Lab_16;
-    int RelativeEncodingIntent;
+    cmsUInt32Number RelativeEncodingIntent;
     cmsColorSpaceSignature ColorSpace;
 
 
@@ -1384,10 +1383,10 @@
 
 // Builds a ASCII string containing colorant list in 0..1.0 range
 static
-void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[])
+void BuildColorantList(char *Colorant, cmsUInt32Number nColorant, cmsUInt16Number Out[])
 {
     char Buff[32];
-    int j;
+    cmsUInt32Number j;
 
     Colorant[0] = 0;
     if (nColorant > cmsMAXCHANNELS)
@@ -1409,12 +1408,12 @@
 // This is a HP extension.
 
 static
-int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent, cmsUInt32Number dwFlags)
+int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHTRANSFORM xform;
-    int i, nColors, nColorant;
+    cmsUInt32Number i, nColors, nColorant;
     cmsUInt32Number OutputFormat;
-    char ColorName[32];
+    char ColorName[cmsMAX_PATH];
     char Colorant[128];
     cmsNAMEDCOLORLIST* NamedColorList;
 
diff --git a/third_party/lcms/src/cmssamp.c b/third_party/lcms/src/cmssamp.c
index a9997fa..1fc5f5d 100644
--- a/third_party/lcms/src/cmssamp.c
+++ b/third_party/lcms/src/cmssamp.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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/third_party/lcms/src/cmssm.c b/third_party/lcms/src/cmssm.c
index 0f7cb7f..a0fdbc8 100644
--- a/third_party/lcms/src/cmssm.c
+++ b/third_party/lcms/src/cmssm.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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/third_party/lcms/src/cmstypes.c b/third_party/lcms/src/cmstypes.c
index 8b02f86..0c24da1 100644
--- a/third_party/lcms/src/cmstypes.c
+++ b/third_party/lcms/src/cmstypes.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -60,6 +60,11 @@
 // Helper macro to define a MPE handler. Callbacks do have a fixed naming convention
 #define TYPE_MPE_HANDLER(t, x)  { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 }
 
+// Infinites
+#define MINUS_INF   (-1E22F)
+#define PLUS_INF    (+1E22F)
+
+
 // Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head
 static
 cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos)
@@ -176,7 +181,8 @@
     cmsUInt32Number currentPosition;
 
     currentPosition = io->Tell(io);
-    // Verify there is enough space left to read two cmsUInt32Number items for Count items.
+
+    // Verify there is enough space left to read at least two cmsUInt32Number items for Count items.
     if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count)
         return FALSE;
 
@@ -238,7 +244,7 @@
 
     // Keep starting position of curve offsets
     DirectoryPos = io ->Tell(io);
-
+  
     // Write a fake directory to be filled latter on
     for (i=0; i < Count; i++) {
 
@@ -401,8 +407,8 @@
 static
 cmsBool  SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io)
 {
-    if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE;
-    if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE;
+    if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) _cmsDoubleTo15Fixed16(x))) return FALSE;
+    if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) _cmsDoubleTo15Fixed16(y))) return FALSE;
 
     return TRUE;
 }
@@ -961,14 +967,14 @@
     cmsBool  rc = FALSE;
     char Filler[68];
 
-    // Used below for writting zeroes
+    // Used below for writing zeroes
     memset(Filler, 0, sizeof(Filler));
 
     // Get the len of string
     len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 
     // 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
+    //(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
@@ -1124,8 +1130,8 @@
                if (!NewGamma) return NULL;
 
                if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) {
-                 cmsFreeToneCurve(NewGamma);
-                 return NULL;
+                   cmsFreeToneCurve(NewGamma);
+                   return NULL;
                }
 
                *nItems = 1;
@@ -1186,7 +1192,7 @@
 // ********************************************************************************
 
 
-// Decide which curve type to use on writting
+// Decide which curve type to use on writing
 static
 cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data)
 {
@@ -1468,7 +1474,8 @@
         if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
 
         // Check for overflow
-        if (Offset < (SizeOfHeader + 8)) goto Error;
+        if (Offset < (SizeOfHeader + 8)) goto Error;        
+        if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error;
 
         // True begin of the string
         BeginOfThisString = Offset - SizeOfHeader - 8;
@@ -1578,7 +1585,7 @@
 // Type cmsSigLut8Type
 // ********************************************************************************
 
-// Decide which LUT type to use on writting
+// Decide which LUT type to use on writing
 static
 cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data)
 {
@@ -1627,10 +1634,10 @@
 
 // Read 8 bit tables as gamma functions
 static
-cmsBool  Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels)
+cmsBool  Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, cmsUInt32Number nChannels)
 {
     cmsUInt8Number* Temp = NULL;
-    int i, j;
+    cmsUInt32Number i, j;
     cmsToneCurve* Tables[cmsMAXCHANNELS];
 
     if (nChannels > cmsMAXCHANNELS) return FALSE;
@@ -1821,8 +1828,10 @@
         _cmsFree(self ->ContextID, Temp);
         Temp = NULL;
 
-        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
+        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
+            _cmsFree(self ->ContextID, T);
             goto Error;
+        }
         _cmsFree(self ->ContextID, T);
     }
 
@@ -1851,7 +1860,7 @@
     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
     _cmsStageMatrixData* MatMPE = NULL;
     _cmsStageCLutData* clut = NULL;
-    int clutPoints;
+    cmsUInt32Number clutPoints;
 
     // Disassemble the LUT into components.
     mpe = NewLUT -> Elements;
@@ -1971,9 +1980,10 @@
 
 // Read 16 bit tables as gamma functions
 static
-cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
+cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, 
+                                    cmsUInt32Number nChannels, cmsUInt32Number nEntries)
 {
-    int i;
+    cmsUInt32Number i;
     cmsToneCurve* Tables[cmsMAXCHANNELS];
 
     // Maybe an empty table? (this is a lcms extension)
@@ -2015,10 +2025,10 @@
 static
 cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables)
 {
-    int j;
+    cmsUInt32Number j;
     cmsUInt32Number i;
     cmsUInt16Number val;
-    int nEntries;
+    cmsUInt32Number nEntries;
 
     _cmsAssert(Tables != NULL);
 
@@ -2139,7 +2149,7 @@
     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
     _cmsStageMatrixData* MatMPE = NULL;
     _cmsStageCLutData* clut = NULL;
-    int i, InputChannels, OutputChannels, clutPoints;
+    cmsUInt32Number i, InputChannels, OutputChannels, clutPoints;
 
     // Disassemble the LUT into components.
     mpe = NewLUT -> Elements;
@@ -2325,7 +2335,8 @@
 //  V4 stuff. Read CLUT part for LutAtoB and LutBtoA
 
 static
-cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels)
+cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, 
+                   cmsUInt32Number Offset, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels)
 {
     cmsUInt8Number  gridPoints8[cmsMAXCHANNELS]; // Number of grid points in each dimension.
     cmsUInt32Number GridPoints[cmsMAXCHANNELS], i;
@@ -2362,8 +2373,8 @@
         for (i=0; i < Data ->nEntries; i++) {
 
             if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) {
-              cmsStageFree(CLUT);
-              return NULL;
+                cmsStageFree(CLUT);
+                return NULL;
             }
             Data ->Tab.T[i] = FROM_8_TO_16(v);
         }
@@ -2679,7 +2690,7 @@
 cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 {
     cmsPipeline* Lut = (cmsPipeline*) Ptr;
-    int inputChan, outputChan;
+    cmsUInt32Number inputChan, outputChan;
     cmsStage *A = NULL, *B = NULL, *M = NULL;
     cmsStage * Matrix = NULL;
     cmsStage * CLUT = NULL;
@@ -2727,7 +2738,7 @@
 
     if (CLUT != NULL) {
         offsetC = io ->Tell(io) - BaseOffset;
-        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;
+        if (!WriteCLUT(self, io, (Lut ->SaveAs8Bits ? 1U : 2U), CLUT)) return FALSE;
 
     }
     if (M != NULL) {
@@ -2867,7 +2878,7 @@
 cmsBool  Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 {
     cmsPipeline* Lut = (cmsPipeline*) Ptr;
-    int inputChan, outputChan;
+    cmsUInt32Number inputChan, outputChan;
     cmsStage *A = NULL, *B = NULL, *M = NULL;
     cmsStage *Matrix = NULL;
     cmsStage *CLUT = NULL;
@@ -2909,7 +2920,7 @@
 
     if (CLUT != NULL) {
         offsetC = io ->Tell(io) - BaseOffset;
-        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;
+        if (!WriteCLUT(self, io, (Lut ->SaveAs8Bits ? 1U : 2U), CLUT)) return FALSE;
 
     }
     if (M != NULL) {
@@ -2984,7 +2995,7 @@
 {
     cmsUInt32Number i, Count;
     cmsNAMEDCOLORLIST* List;
-    char Name[33];
+    char Name[34];
     cmsUInt16Number PCS[3];
 
 
@@ -3025,7 +3036,7 @@
 cmsBool  Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 {
     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
-    int i, nColors;
+    cmsUInt32Number i, nColors;
 
     nColors = cmsNamedColorCount(NamedColorList);
 
@@ -3033,9 +3044,11 @@
 
     for (i=0; i < nColors; i++) {
 
-        char root[33];
+        char root[cmsMAX_PATH];
         cmsUInt16Number PCS[3];
 
+        memset(root, 0, sizeof(root));
+
         if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0;
         root[32] = 0;
 
@@ -3078,8 +3091,8 @@
 //The namedColor2Type is a count value and array of structures that provide color
 //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
 //device representation of the color are given. Both representations are 16-bit values.
-//The device representation corresponds to the header's 'color space of data' field.
-//This representation should be consistent with the 'number of device components'
+//The device representation corresponds to the header's "color space of data" field.
+//This representation should be consistent with the "number of device components"
 //field in the namedColor2Type. If this field is 0, device coordinates are not provided.
 //The PCS representation corresponds to the header's PCS field. The PCS representation
 //is always provided. Color names are fixed-length, 32-byte fields including null
@@ -3095,8 +3108,8 @@
     cmsUInt32Number      nDeviceCoords;  // Num of device coordinates
     char                 prefix[32];     // Prefix for each color name
     char                 suffix[32];     // Suffix for each color name
-    cmsNAMEDCOLORLIST*  v;
-    cmsUInt32Number i;
+    cmsNAMEDCOLORLIST*   v;
+    cmsUInt32Number      i;
 
 
     *nItems = 0;
@@ -3153,7 +3166,7 @@
     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
     char                prefix[33];     // Prefix for each color name
     char                suffix[33];     // Suffix for each color name
-    int i, nColors;
+    cmsUInt32Number     i, nColors;
 
     nColors = cmsNamedColorCount(NamedColorList);
 
@@ -3173,7 +3186,7 @@
 
        cmsUInt16Number PCS[3];
        cmsUInt16Number Colorant[cmsMAXCHANNELS];
-       char Root[33];
+       char Root[cmsMAX_PATH];
 
         if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
         Root[32] = 0;
@@ -3826,7 +3839,7 @@
 // ********************************************************************************
 //
 //This type represents a set of viewing condition parameters including:
-//CIE 'absolute'illuminant white point tristimulus values and CIE 'absolute'
+//CIE 'absolute' illuminant white point tristimulus values and CIE 'absolute'
 //surround tristimulus values.
 
 static
@@ -3927,7 +3940,7 @@
     cmsUInt16Number nSegments;
     cmsCurveSegment*  Segments;
     cmsToneCurve* Curve;
-    cmsFloat32Number PrevBreak = -1E22F;    // - infinite
+    cmsFloat32Number PrevBreak = MINUS_INF;    // - infinite
 
     // Take signature and channels for each element.
      if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL;
@@ -3952,7 +3965,7 @@
      }
 
      Segments[nSegments-1].x0 = PrevBreak;
-     Segments[nSegments-1].x1 = 1E22F;     // A big cmsFloat32Number number
+     Segments[nSegments-1].x1 = PLUS_INF;     // A big cmsFloat32Number number
 
      // Read segments
      for (i=0; i < nSegments; i++) {
@@ -4078,7 +4091,7 @@
     }
 
     _cmsFree(self ->ContextID, GammaTables);
-    *nItems = (mpe != NULL) ? 1 : 0;
+    *nItems = (mpe != NULL) ? 1U : 0;
     return mpe;
 
     cmsUNUSED_PARAMETER(SizeOfTag);
@@ -4214,7 +4227,7 @@
     if (InputChans >= cmsMAXCHANNELS) return NULL;
     if (OutputChans >= cmsMAXCHANNELS) return NULL;
 
-    nElems = InputChans * OutputChans;
+    nElems = (cmsUInt32Number) InputChans * OutputChans;
 
     Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number));
     if (Matrix == NULL) return NULL;
@@ -4318,22 +4331,22 @@
         goto Error;
 
     // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
-    nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;
+    nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? (cmsUInt32Number) MAX_INPUT_DIMENSIONS : InputChans;
 
     for (i = 0; i < nMaxGrids; i++) {
         if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
         GridPoints[i] = (cmsUInt32Number)Dimensions8[i];
     }
-
+    
     // Allocate the true CLUT
     mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
     if (mpe == NULL) goto Error;
 
-    // Read the data
+    // Read and sanitize the data
     clut = (_cmsStageCLutData*) mpe ->Data;
     for (i=0; i < clut ->nEntries; i++) {
 
-        if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
+        if (!_cmsReadFloat32Number(io, &clut->Tab.TFloat[i])) goto Error;       
     }
 
     *nItems = 1;
@@ -4470,15 +4483,19 @@
     NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
     if (NewLUT == NULL) return NULL;
 
-    if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error;
+    if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error;    
     if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error;
 
+    // Check channel count
+    if (InputChans != NewLUT->InputChannels ||
+        OutputChans != NewLUT->OutputChannels) goto Error;
+
     // Success
     *nItems = 1;
     return NewLUT;
 
     // Error
-Error:
+Error:    
     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
     *nItems = 0;
     return NULL;
@@ -4493,7 +4510,7 @@
 cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 {
     cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos;
-    int inputChan, outputChan;
+    cmsUInt32Number inputChan, outputChan;
     cmsUInt32Number ElemCount;
     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before;
     cmsStageSignature ElementSig;
@@ -4541,7 +4558,7 @@
 
                 _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
 
-                 // An unknow element was found.
+                 // An unknown element was found.
                  cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Found unknown MPE type '%s'", String);
                  goto Error;
         }
@@ -5276,38 +5293,38 @@
 
 
 // This is the list of built-in types
-static _cmsTagTypeLinkedList SupportedTagTypes[] = {
+static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
 
-{TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),        &SupportedTagTypes[1] },
-{TYPE_HANDLER(cmsSigColorantOrderType,         ColorantOrderType),   &SupportedTagTypes[2] },
-{TYPE_HANDLER(cmsSigS15Fixed16ArrayType,       S15Fixed16),          &SupportedTagTypes[3] },
-{TYPE_HANDLER(cmsSigU16Fixed16ArrayType,       U16Fixed16),          &SupportedTagTypes[4] },
-{TYPE_HANDLER(cmsSigTextType,                  Text),                &SupportedTagTypes[5] },
-{TYPE_HANDLER(cmsSigTextDescriptionType,       Text_Description),    &SupportedTagTypes[6] },
-{TYPE_HANDLER(cmsSigCurveType,                 Curve),               &SupportedTagTypes[7] },
-{TYPE_HANDLER(cmsSigParametricCurveType,       ParametricCurve),     &SupportedTagTypes[8] },
-{TYPE_HANDLER(cmsSigDateTimeType,              DateTime),            &SupportedTagTypes[9] },
-{TYPE_HANDLER(cmsSigLut8Type,                  LUT8),                &SupportedTagTypes[10] },
-{TYPE_HANDLER(cmsSigLut16Type,                 LUT16),               &SupportedTagTypes[11] },
-{TYPE_HANDLER(cmsSigColorantTableType,         ColorantTable),       &SupportedTagTypes[12] },
-{TYPE_HANDLER(cmsSigNamedColor2Type,           NamedColor),          &SupportedTagTypes[13] },
-{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU),                 &SupportedTagTypes[14] },
-{TYPE_HANDLER(cmsSigProfileSequenceDescType,   ProfileSequenceDesc), &SupportedTagTypes[15] },
-{TYPE_HANDLER(cmsSigSignatureType,             Signature),           &SupportedTagTypes[16] },
-{TYPE_HANDLER(cmsSigMeasurementType,           Measurement),         &SupportedTagTypes[17] },
-{TYPE_HANDLER(cmsSigDataType,                  Data),                &SupportedTagTypes[18] },
-{TYPE_HANDLER(cmsSigLutAtoBType,               LUTA2B),              &SupportedTagTypes[19] },
-{TYPE_HANDLER(cmsSigLutBtoAType,               LUTB2A),              &SupportedTagTypes[20] },
-{TYPE_HANDLER(cmsSigUcrBgType,                 UcrBg),               &SupportedTagTypes[21] },
-{TYPE_HANDLER(cmsSigCrdInfoType,               CrdInfo),             &SupportedTagTypes[22] },
-{TYPE_HANDLER(cmsSigMultiProcessElementType,   MPE),                 &SupportedTagTypes[23] },
-{TYPE_HANDLER(cmsSigScreeningType,             Screening),           &SupportedTagTypes[24] },
-{TYPE_HANDLER(cmsSigViewingConditionsType,     ViewingConditions),   &SupportedTagTypes[25] },
-{TYPE_HANDLER(cmsSigXYZType,                   XYZ),                 &SupportedTagTypes[26] },
-{TYPE_HANDLER(cmsCorbisBrokenXYZtype,          XYZ),                 &SupportedTagTypes[27] },
-{TYPE_HANDLER(cmsMonacoBrokenCurveType,        Curve),               &SupportedTagTypes[28] },
-{TYPE_HANDLER(cmsSigProfileSequenceIdType,     ProfileSequenceId),   &SupportedTagTypes[29] },
-{TYPE_HANDLER(cmsSigDictType,                  Dictionary),          &SupportedTagTypes[30] },
+{TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),       (_cmsTagTypeLinkedList*) &SupportedTagTypes[1] },
+{TYPE_HANDLER(cmsSigColorantOrderType,         ColorantOrderType),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[2] },
+{TYPE_HANDLER(cmsSigS15Fixed16ArrayType,       S15Fixed16),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[3] },
+{TYPE_HANDLER(cmsSigU16Fixed16ArrayType,       U16Fixed16),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[4] },
+{TYPE_HANDLER(cmsSigTextType,                  Text),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[5] },
+{TYPE_HANDLER(cmsSigTextDescriptionType,       Text_Description),   (_cmsTagTypeLinkedList*) &SupportedTagTypes[6] },
+{TYPE_HANDLER(cmsSigCurveType,                 Curve),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[7] },
+{TYPE_HANDLER(cmsSigParametricCurveType,       ParametricCurve),    (_cmsTagTypeLinkedList*) &SupportedTagTypes[8] },
+{TYPE_HANDLER(cmsSigDateTimeType,              DateTime),           (_cmsTagTypeLinkedList*) &SupportedTagTypes[9] },
+{TYPE_HANDLER(cmsSigLut8Type,                  LUT8),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[10] },
+{TYPE_HANDLER(cmsSigLut16Type,                 LUT16),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[11] },
+{TYPE_HANDLER(cmsSigColorantTableType,         ColorantTable),      (_cmsTagTypeLinkedList*) &SupportedTagTypes[12] },
+{TYPE_HANDLER(cmsSigNamedColor2Type,           NamedColor),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[13] },
+{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[14] },
+{TYPE_HANDLER(cmsSigProfileSequenceDescType,   ProfileSequenceDesc),(_cmsTagTypeLinkedList*) &SupportedTagTypes[15] },
+{TYPE_HANDLER(cmsSigSignatureType,             Signature),          (_cmsTagTypeLinkedList*) &SupportedTagTypes[16] },
+{TYPE_HANDLER(cmsSigMeasurementType,           Measurement),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[17] },
+{TYPE_HANDLER(cmsSigDataType,                  Data),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[18] },
+{TYPE_HANDLER(cmsSigLutAtoBType,               LUTA2B),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[19] },
+{TYPE_HANDLER(cmsSigLutBtoAType,               LUTB2A),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[20] },
+{TYPE_HANDLER(cmsSigUcrBgType,                 UcrBg),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[21] },
+{TYPE_HANDLER(cmsSigCrdInfoType,               CrdInfo),            (_cmsTagTypeLinkedList*) &SupportedTagTypes[22] },
+{TYPE_HANDLER(cmsSigMultiProcessElementType,   MPE),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[23] },
+{TYPE_HANDLER(cmsSigScreeningType,             Screening),          (_cmsTagTypeLinkedList*) &SupportedTagTypes[24] },
+{TYPE_HANDLER(cmsSigViewingConditionsType,     ViewingConditions),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[25] },
+{TYPE_HANDLER(cmsSigXYZType,                   XYZ),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[26] },
+{TYPE_HANDLER(cmsCorbisBrokenXYZtype,          XYZ),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[27] },
+{TYPE_HANDLER(cmsMonacoBrokenCurveType,        Curve),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[28] },
+{TYPE_HANDLER(cmsSigProfileSequenceIdType,     ProfileSequenceId),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[29] },
+{TYPE_HANDLER(cmsSigDictType,                  Dictionary),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
 {TYPE_HANDLER(cmsSigVcgtType,                  vcgt),                NULL }
 };
 
@@ -5399,7 +5416,7 @@
 {
     _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin);
 
-    return GetHandler(sig, ctx->TagTypes, SupportedTagTypes);
+    return GetHandler(sig, ctx->TagTypes, (_cmsTagTypeLinkedList*) SupportedTagTypes);
 }
 
 // ********************************************************************************
@@ -5414,7 +5431,7 @@
 
 } _cmsTagLinkedList;
 
-// This is the list of built-in tags
+// This is the list of built-in tags. The data of this list can be modified by plug-ins
 static _cmsTagLinkedList SupportedTags[] = {
 
     { cmsSigAToB0Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]},
@@ -5463,7 +5480,7 @@
     { cmsSigPreview2Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]},
 
     { cmsSigProfileDescriptionTag,  { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]},
-    { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]},
+    { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL},  &SupportedTags[34]},
     { cmsSigTechnologyTag,          { 1, 1, { cmsSigSignatureType }, NULL},  &SupportedTags[35]},
 
     { cmsSigColorimetricIntentImageStateTag,   { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[36]},
@@ -5500,10 +5517,10 @@
     { 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}, &SupportedTags[63]},
     { cmsSigArgyllArtsTag,          { 9, 1, { cmsSigS15Fixed16ArrayType},    NULL}, NULL}
 
-
 };
 
 /*
diff --git a/third_party/lcms/src/cmsvirt.c b/third_party/lcms/src/cmsvirt.c
index 9eff1f7..935effc 100644
--- a/third_party/lcms/src/cmsvirt.c
+++ b/third_party/lcms/src/cmsvirt.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -291,7 +291,7 @@
 {
     cmsHPROFILE hICC;
     cmsPipeline* Pipeline;
-    int nChannels;
+    cmsUInt32Number nChannels;
 
     hICC = cmsCreateProfilePlaceholder(ContextID);
     if (!hICC)
@@ -397,7 +397,7 @@
     cmsHPROFILE hICC;
     cmsPipeline* LUT;
     cmsStage* CLUT;
-    int nChannels;
+    cmsUInt32Number nChannels;
 
     if (ColorSpace != cmsSigCmykData) {
         cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
@@ -726,13 +726,13 @@
 // contrast, Saturation and white point displacement
 
 cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
-    int nLUTPoints,
-    cmsFloat64Number Bright,
-    cmsFloat64Number Contrast,
-    cmsFloat64Number Hue,
-    cmsFloat64Number Saturation,
-    int TempSrc,
-    int TempDest)
+                                                       cmsUInt32Number nLUTPoints,
+                                                       cmsFloat64Number Bright,
+                                                       cmsFloat64Number Contrast,
+                                                       cmsFloat64Number Hue,
+                                                       cmsFloat64Number Saturation,
+                                                       cmsUInt32Number TempSrc,
+                                                       cmsUInt32Number TempDest)
 {
     cmsHPROFILE hICC;
     cmsPipeline* Pipeline;
@@ -740,7 +740,7 @@
     cmsCIExyY WhitePnt;
     cmsStage* CLUT;
     cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
-    int i;
+    cmsUInt32Number i;
 
     bchsw.Brightness = Bright;
     bchsw.Contrast   = Contrast;
@@ -778,7 +778,7 @@
 
     for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
     CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
-    if (CLUT == NULL) return NULL;
+    if (CLUT == NULL) goto Error;
 
 
     if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
@@ -811,13 +811,13 @@
 }
 
 
-CMSAPI cmsHPROFILE   CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
+CMSAPI cmsHPROFILE   CMSEXPORT cmsCreateBCHSWabstractProfile(cmsUInt32Number nLUTPoints,
                                                              cmsFloat64Number Bright,
                                                              cmsFloat64Number Contrast,
                                                              cmsFloat64Number Hue,
                                                              cmsFloat64Number Saturation,
-                                                             int TempSrc,
-                                                             int TempDest)
+                                                             cmsUInt32Number TempSrc,
+                                                             cmsUInt32Number TempDest)
 {
     return cmsCreateBCHSWabstractProfileTHR(NULL, nLUTPoints, Bright, Contrast, Hue, Saturation, TempSrc, TempDest);
 }
@@ -830,8 +830,10 @@
     cmsHPROFILE hProfile;
     cmsPipeline* LUT = NULL;
     cmsStage* PostLin;
-    cmsToneCurve* EmptyTab;
+    cmsStage* OutLin;
+    cmsToneCurve* EmptyTab[3];
     cmsUInt16Number Zero[2] = { 0, 0 };
+    const cmsFloat64Number PickLstarMatrix[] = { 1, 0, 0 };
 
     hProfile = cmsCreateProfilePlaceholder(ContextID);
     if (!hProfile)                          // can't allocate
@@ -842,22 +844,28 @@
     if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error;
 
 
-
     cmsSetDeviceClass(hProfile, cmsSigOutputClass);
     cmsSetColorSpace(hProfile,  cmsSigGrayData);
     cmsSetPCS(hProfile,         cmsSigLabData);
 
-    // An empty LUTs is all we need
-    LUT = cmsPipelineAlloc(ContextID, 1, 1);
+    // Create a valid ICC 4 structure
+    LUT = cmsPipelineAlloc(ContextID, 3, 1);
     if (LUT == NULL) goto Error;
-
-    EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
-    PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
-    cmsFreeToneCurve(EmptyTab);
+    
+    EmptyTab[0] = EmptyTab[1] = EmptyTab[2] = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
+    PostLin = cmsStageAllocToneCurves(ContextID, 3, EmptyTab);
+    OutLin  = cmsStageAllocToneCurves(ContextID, 1, EmptyTab);
+    cmsFreeToneCurve(EmptyTab[0]);
 
     if (!cmsPipelineInsertStage(LUT, cmsAT_END, PostLin))
         goto Error;
 
+    if (!cmsPipelineInsertStage(LUT, cmsAT_END, cmsStageAllocMatrix(ContextID, 1, 3, PickLstarMatrix, NULL)))
+        goto Error;
+
+    if (!cmsPipelineInsertStage(LUT, cmsAT_END, OutLin))
+        goto Error;
+
     if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
     if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
 
@@ -938,7 +946,7 @@
 {
     _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
     cmsHPROFILE hICC = NULL;
-    int i, nColors;
+    cmsUInt32Number i, nColors;
     cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL;
 
     // Create an empty placeholder
@@ -1055,7 +1063,7 @@
 {
     cmsHPROFILE hProfile = NULL;
     cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut;
-    cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut;
+    int ColorSpaceBitsIn, ColorSpaceBitsOut;
     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
     cmsPipeline* LUT = NULL;
     cmsStage* mpe;
diff --git a/third_party/lcms/src/cmswtpnt.c b/third_party/lcms/src/cmswtpnt.c
index 6df2321..9f90d6a 100644
--- a/third_party/lcms/src/cmswtpnt.c
+++ b/third_party/lcms/src/cmswtpnt.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -76,7 +76,6 @@
         }
 
         // Obtain y(x)
-
         y = -3.000*(x*x) + 2.870*x - 0.275;
 
         // wave factors (not used, but here for futures extensions)
@@ -266,7 +265,7 @@
 // Build a White point, primary chromas transfer matrix from RGB to CIE XYZ
 // This is just an approximation, I am not handling all the non-linear
 // aspects of the RGB to XYZ process, and assumming that the gamma correction
-// has transitive property in the tranformation chain.
+// has transitive property in the transformation chain.
 //
 // the alghoritm:
 //
diff --git a/third_party/lcms/src/cmsxform.c b/third_party/lcms/src/cmsxform.c
index b3802f0..508117b 100644
--- a/third_party/lcms/src/cmsxform.c
+++ b/third_party/lcms/src/cmsxform.c
@@ -1,7 +1,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -255,6 +255,8 @@
 
     strideIn = 0;
     strideOut = 0;
+    memset(fIn, 0, sizeof(fIn));
+    memset(fOut, 0, sizeof(fIn));
 
     for (i = 0; i < LineCount; i++) {
 
@@ -319,6 +321,7 @@
 
     strideIn = 0;
     strideOut = 0;
+    memset(fIn, 0, sizeof(fIn));
 
     for (i = 0; i < LineCount; i++) {
 
@@ -356,6 +359,7 @@
 
     strideIn = 0;
     strideOut = 0;
+    memset(wIn, 0, sizeof(wIn));
 
     for (i = 0; i < LineCount; i++) {
 
@@ -393,6 +397,8 @@
 
     strideIn = 0;
     strideOut = 0;
+    memset(wIn, 0, sizeof(wIn));
+    memset(wOut, 0, sizeof(wOut));
 
     for (i = 0; i < LineCount; i++) {
 
@@ -454,6 +460,8 @@
 
     strideIn = 0;
     strideOut = 0;
+    memset(wIn, 0, sizeof(wIn));
+    memset(wOut, 0, sizeof(wOut));
 
     for (i = 0; i < LineCount; i++) {
 
@@ -762,9 +770,9 @@
        // Allocate needed memory
        _cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
        if (!p) {
-          cmsPipelineFree(lut);
-          return NULL;
-      }
+              cmsPipelineFree(lut);
+              return NULL;
+       }
 
        // Store the proposed pipeline
        p->Lut = lut;
@@ -797,7 +805,7 @@
                             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?
+                            // Save the day? (Ignore the warning)
                             if (Plugin->OldXform) {
                                    p->OldXform = (_cmsTransformFn) p->xform;
                                    p->xform = _cmsTransform2toTransformAdaptor;
@@ -844,7 +852,7 @@
         }
         else {
 
-            int BytesPerPixelInput;
+            cmsUInt32Number BytesPerPixelInput;
 
             p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
             p ->ToOutput  = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
@@ -894,13 +902,13 @@
 }
 
 static
-cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
+cmsBool GetXFormColorSpaces(cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
 {
     cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
     cmsColorSpaceSignature PostColorSpace;
-    int i;
+    cmsUInt32Number i;
 
-    if (nProfiles <= 0) return FALSE;
+    if (nProfiles == 0) return FALSE;
     if (hProfiles[0] == NULL) return FALSE;
 
     *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]);
@@ -949,7 +957,7 @@
 static
 cmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
 {
-    int Space1 = T_COLORSPACE(dwFormat);
+    int Space1 = (int) T_COLORSPACE(dwFormat);
     int Space2 = _cmsLCMScolorSpace(Check);
 
     if (Space1 == PT_ANY) return TRUE;
@@ -1205,7 +1213,7 @@
     hArray[0] = Input;
     hArray[1] = Output;
 
-    return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags);
+    return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1U : 2U, InputFormat, OutputFormat, Intent, dwFlags);
 }
 
 CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
diff --git a/third_party/lcms/src/lcms2_internal.h b/third_party/lcms/src/lcms2_internal.h
index 115ac59..bd1c86b 100644
--- a/third_party/lcms/src/lcms2_internal.h
+++ b/third_party/lcms/src/lcms2_internal.h
@@ -1,7 +1,7 @@
 
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2016 Marti Maria Saguer
+//  Copyright (c) 1998-2017 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"),
@@ -77,7 +77,7 @@
 // Maximum of channels for internal pipeline evaluation
 #define MAX_STAGE_CHANNELS  128
 
-// Unused parameter warning supression
+// Unused parameter warning suppression
 #define cmsUNUSED_PARAMETER(x) ((void)x)
 
 // The specification for "inline" is section 6.7.4 of the C99 standard (ISO/IEC 9899:1999).
@@ -96,8 +96,16 @@
 # ifndef vsnprintf
 #       define vsnprintf  _vsnprintf
 # endif
-#endif
 
+/// Properly define some macros to accommodate
+/// older MSVC versions.
+# if _MSC_VER <= 1700
+        #include <float.h>
+        #define isnan _isnan
+        #define isinf(x) (!_finite((x)))
+# endif
+
+#endif
 
 // A fast way to convert from/to 16 <-> 8 bits
 #define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb))
@@ -185,6 +193,34 @@
 #include <windows.h>
 
 
+// The locking scheme in LCMS requires a single 'top level' mutex
+// to work. This is actually implemented on Windows as a
+// CriticalSection, because they are lighter weight. With
+// pthreads, this is statically inited. Unfortunately, windows
+// can't officially statically init critical sections.
+//
+// We can work around this in 2 ways.
+//
+// 1) We can use a proper mutex purely to protect the init
+// of the CriticalSection. This in turns requires us to protect
+// the Mutex creation, which we can do using the snappily
+// named InterlockedCompareExchangePointer API (present on
+// windows XP and above).
+//
+// 2) In cases where we want to work on pre-Windows XP, we
+// can use an even more horrible hack described below.
+//
+// So why wouldn't we always use 2)? Because not calling
+// the init function for a critical section means it fails
+// testing with ApplicationVerifier (and presumably similar
+// tools).
+//
+// We therefore default to 1, and people who want to be able
+// to run on pre-Windows XP boxes can build with:
+//     CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
+// defined. This is automatically set for builds using
+// versions of MSVC that don't have this API available.
+//
 // From: http://locklessinc.com/articles/pthreads_on_windows/
 // The pthreads API has an initialization macro that has no correspondence to anything in 
 // the windows API. By investigating the internal definition of the critical section type, 
@@ -206,14 +242,30 @@
 
 typedef CRITICAL_SECTION _cmsMutex;
 
-#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
 
+#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
+// If we are building with a version of MSVC smaller
+// than 1400 (i.e. before VS2005) then we don't have
+// the InterlockedCompareExchangePointer API, so use
+// the old version.
+#    ifdef _MSC_VER
+#       if _MSC_VER < 1400
+#          define CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
+#       endif
+#    endif
+#endif
+
+#ifdef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
+#      define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0}
+#else
+#      define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG)NULL,-1,0,0,0,0}
+#endif
+
 cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
 {
 	EnterCriticalSection(m);
@@ -449,7 +501,7 @@
     void* chunks[MemoryClientMax];    // array of pointers to client chunks. Memory itself is hold in the suballocator. 
                                       // If NULL, then it reverts to global Context0
 
-    _cmsMemPluginChunkType DefaultMemoryManager;  // The allocators used for creating the context itself. Cannot be overriden
+    _cmsMemPluginChunkType DefaultMemoryManager;  // The allocators used for creating the context itself. Cannot be overridden
 };
 
 // Returns a pointer to a valid context structure, including the global one if id is zero. 
@@ -771,8 +823,8 @@
 
 // Interpolation ---------------------------------------------------------------------------------------------------------
 
-cmsInterpParams*     _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
-cmsInterpParams*     _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
+cmsInterpParams*     _cmsComputeInterpParams(cmsContext ContextID, cmsUInt32Number nSamples, cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags);
+cmsInterpParams*     _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags);
 void                 _cmsFreeInterpParams(cmsInterpParams* p);
 cmsBool              _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p);
 
@@ -831,13 +883,13 @@
 cmsStage*        _cmsStageAllocLabV2ToV4curves(cmsContext ContextID);
 cmsStage*        _cmsStageAllocLabV4ToV2(cmsContext ContextID);
 cmsStage*        _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS);
-cmsStage*        _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels);
-cmsStage*        _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan);
+cmsStage*        _cmsStageAllocIdentityCurves(cmsContext ContextID, cmsUInt32Number nChannels);
+cmsStage*        _cmsStageAllocIdentityCLut(cmsContext ContextID, cmsUInt32Number nChan);
 cmsStage*        _cmsStageNormalizeFromLabFloat(cmsContext ContextID);
 cmsStage*        _cmsStageNormalizeFromXyzFloat(cmsContext ContextID);
 cmsStage*        _cmsStageNormalizeToLabFloat(cmsContext ContextID);
 cmsStage*        _cmsStageNormalizeToXyzFloat(cmsContext ContextID);
-cmsStage*        _cmsStageClipNegatives(cmsContext ContextID, int nChannels);
+cmsStage*        _cmsStageClipNegatives(cmsContext ContextID, cmsUInt32Number nChannels);
 
 
 // For curve set only
@@ -872,9 +924,9 @@
 // Read tags using low-level function, provide necessary glue code to adapt versions, etc. All those return a brand new copy
 // of the LUTS, since ownership of original is up to the profile. The user should free allocated resources.
 
-cmsPipeline*      _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent);
-cmsPipeline*      _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent);
-cmsPipeline*      _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent);
+cmsPipeline*      _cmsReadInputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent);
+cmsPipeline*      _cmsReadOutputLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent);
+cmsPipeline*      _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent);
 
 // Special values
 cmsBool           _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile);
@@ -899,8 +951,8 @@
 
 // LUT optimization ------------------------------------------------------------------------------------------------
 
-cmsUInt16Number  _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples);
-int              _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
+cmsUInt16Number  _cmsQuantizeVal(cmsFloat64Number i, cmsUInt32Number MaxSamples);
+cmsUInt32Number  _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
 
 cmsBool          _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
                                       cmsUInt16Number **White,
@@ -909,7 +961,7 @@
 
 cmsBool          _cmsOptimizePipeline(cmsContext ContextID,
                                       cmsPipeline**    Lut,
-                                      int              Intent,
+                                      cmsUInt32Number  Intent,
                                       cmsUInt32Number* InputFormat,
                                       cmsUInt32Number* OutputFormat,
                                       cmsUInt32Number* dwFlags );