Update lcms (#544)
authorMatthieu Darbois <mayeut@users.noreply.github.com>
Sat, 30 Apr 2016 15:58:04 +0000 (17:58 +0200)
committerMatthieu Darbois <mayeut@users.noreply.github.com>
Sat, 30 Apr 2016 15:58:04 +0000 (17:58 +0200)
Update to mm2/Little-CMS@0e8234e090d6aab33f90e2eb0296f30aa0705e57

32 files changed:
tests/compare_images.c
tests/nonregression/md5refs.txt
thirdparty/liblcms2/COPYING
thirdparty/liblcms2/include/lcms2.h
thirdparty/liblcms2/include/lcms2_plugin.h
thirdparty/liblcms2/src/cmsalpha.c [new file with mode: 0644]
thirdparty/liblcms2/src/cmscam02.c
thirdparty/liblcms2/src/cmscgats.c
thirdparty/liblcms2/src/cmscnvrt.c
thirdparty/liblcms2/src/cmserr.c
thirdparty/liblcms2/src/cmsgmt.c
thirdparty/liblcms2/src/cmshalf.c
thirdparty/liblcms2/src/cmsintrp.c
thirdparty/liblcms2/src/cmsio0.c
thirdparty/liblcms2/src/cmsio1.c
thirdparty/liblcms2/src/cmslut.c
thirdparty/liblcms2/src/cmsmd5.c
thirdparty/liblcms2/src/cmsmtrx.c
thirdparty/liblcms2/src/cmsnamed.c
thirdparty/liblcms2/src/cmsopt.c
thirdparty/liblcms2/src/cmspack.c
thirdparty/liblcms2/src/cmspcs.c
thirdparty/liblcms2/src/cmsplugin.c
thirdparty/liblcms2/src/cmsps2.c
thirdparty/liblcms2/src/cmssamp.c
thirdparty/liblcms2/src/cmssm.c
thirdparty/liblcms2/src/cmstypes.c
thirdparty/liblcms2/src/cmsvirt.c
thirdparty/liblcms2/src/cmswtpnt.c
thirdparty/liblcms2/src/cmsxform.c
thirdparty/liblcms2/src/lcms2.def [deleted file]
thirdparty/liblcms2/src/lcms2_internal.h

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