summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2014-02-12 12:21:45 +0100
committerMarti Maria <info@littlecms.com>2014-02-12 12:21:45 +0100
commit078665ecf29b6a9ca31803e6ebd12f22f3da9961 (patch)
treed5036b7a482babdd8d99a693f3edeabf6877f1c1
parent579b3aad051b9fcf858ea308f9d8f6714f84c7a8 (diff)
downloadlcms2-078665ecf29b6a9ca31803e6ebd12f22f3da9961.tar.gz
Merge from Artifex branchlcms2.6rc0
-rw-r--r--AUTHORS2
-rw-r--r--ChangeLog9
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in2
-rw-r--r--Projects/VC2010/testbed/testbed.vcxproj5
-rw-r--r--Projects/VC2010/testbed/testbed.vcxproj.filters11
-rwxr-xr-xconfigure66
-rw-r--r--configure.ac48
-rwxr-xr-xdoc/LittleCMS2.5 API.pdfbin2354776 -> 0 bytes
-rwxr-xr-xdoc/LittleCMS2.5 Plugin API.pdfbin1373331 -> 0 bytes
-rwxr-xr-xdoc/LittleCMS2.5 tutorial.pdfbin1563508 -> 0 bytes
-rwxr-xr-xdoc/LittleCMS2.6 API.pdfbin0 -> 990129 bytes
-rwxr-xr-xdoc/LittleCMS2.6 Plugin API.pdfbin0 -> 506789 bytes
-rwxr-xr-xdoc/LittleCMS2.6 tutorial.pdfbin0 -> 837477 bytes
-rw-r--r--include/lcms2.h58
-rw-r--r--include/lcms2_plugin.h45
-rw-r--r--src/cmscam02.c10
-rw-r--r--src/cmscnvrt.c106
-rw-r--r--src/cmserr.c292
-rw-r--r--src/cmsgamma.c95
-rw-r--r--src/cmsgmt.c1180
-rw-r--r--src/cmsintrp.c45
-rw-r--r--src/cmsio0.c227
-rw-r--r--src/cmsio1.c2
-rw-r--r--src/cmsopt.c97
-rw-r--r--src/cmspack.c88
-rw-r--r--src/cmsplugin.c358
-rw-r--r--src/cmsps2.c4
-rw-r--r--src/cmstypes.c224
-rw-r--r--src/cmsvirt.c6
-rw-r--r--src/cmsxform.c259
-rw-r--r--src/lcms2.def666
-rw-r--r--src/lcms2_internal.h284
-rw-r--r--testbed/Makefile.am4
-rw-r--r--testbed/Makefile.in9
-rwxr-xr-xtestbed/ibm-t61.iccbin0 -> 20480 bytes
-rw-r--r--testbed/new.iccbin0 -> 20480 bytes
-rw-r--r--testbed/testcms2.c647
-rwxr-xr-xtestbed/testcms2.h84
-rwxr-xr-xtestbed/testplugin.c1476
-rw-r--r--testbed/testthread.cpp148
-rwxr-xr-xtestbed/zoo_icc.c310
-rw-r--r--utils/delphi/lcms2dll.pas693
-rw-r--r--utils/jpgicc/jpgicc.c9
-rw-r--r--utils/psicc/psicc.c2
-rw-r--r--utils/tificc/tificc.c2
-rw-r--r--utils/transicc/transicc.12
47 files changed, 5559 insertions, 2018 deletions
diff --git a/AUTHORS b/AUTHORS
index 8a6c3da..4f3820a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -32,9 +32,11 @@ XhmikosR
Stanislav Brabec (SuSe)
Leonhard Gruenschloss (Google)
Patrick Noffke
+Christopher James Halse Rogers
Special Thanks
--------------
+Artifex software
Jan Morovic
Jos Vernon (WebSupergoo)
Harald Schneider (Maxon)
diff --git a/ChangeLog b/ChangeLog
index 1fde607..4324a6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -131,4 +131,11 @@ Fixed some indexing out of bounds in floating point interpolation
Fixed a bug in PCS/Colorspace order when reading V2 Lab devicelinks
Added a way to retrieve matrix shaper always, no matter LUT is present
Changed endianess detection for PowerPC
-Fixed memory leaks on error handling \ No newline at end of file
+Fixed memory leaks on error handling
+Big revamp on Contexts, from Artifex
+New locking plug-in, from Artifex
+Added directories for tiff, jpeg in configure script
+
+-----------------------
+2.6 Featured release
+-----------------------
diff --git a/Makefile.am b/Makefile.am
index e0cba52..9b2b333 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
SUBDIRS = src include utils/tificc utils/transicc utils/linkicc utils/jpgicc utils/psicc testbed
# Additional files to distribute
-EXTRA_DIST = AUTHORS COPYING ChangeLog doc Projects include bin Lib INSTALL README.1ST lcms2.pc.in
+EXTRA_DIST = AUTHORS COPYING ChangeLog doc Projects include bin Lib INSTALL README.1ST autogen.sh lcms2.pc.in
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = lcms2.pc
diff --git a/Makefile.in b/Makefile.in
index 89b9605..b97d38e 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -300,7 +300,7 @@ AUTOMAKE_OPTIONS = 1.7.2 dist-zip foreign
SUBDIRS = src include utils/tificc utils/transicc utils/linkicc utils/jpgicc utils/psicc testbed
# Additional files to distribute
-EXTRA_DIST = AUTHORS COPYING ChangeLog doc Projects include bin Lib INSTALL README.1ST lcms2.pc.in
+EXTRA_DIST = AUTHORS COPYING ChangeLog doc Projects include bin Lib INSTALL README.1ST autogen.sh lcms2.pc.in
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = lcms2.pc
all: all-recursive
diff --git a/Projects/VC2010/testbed/testbed.vcxproj b/Projects/VC2010/testbed/testbed.vcxproj
index fc92b0c..c26e3cc 100644
--- a/Projects/VC2010/testbed/testbed.vcxproj
+++ b/Projects/VC2010/testbed/testbed.vcxproj
@@ -189,6 +189,11 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\testbed\testcms2.c" />
+ <ClCompile Include="..\..\..\testbed\testplugin.c" />
+ <ClCompile Include="..\..\..\testbed\zoo_icc.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\testbed\testcms2.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/Projects/VC2010/testbed/testbed.vcxproj.filters b/Projects/VC2010/testbed/testbed.vcxproj.filters
index 21cbdd4..fecb121 100644
--- a/Projects/VC2010/testbed/testbed.vcxproj.filters
+++ b/Projects/VC2010/testbed/testbed.vcxproj.filters
@@ -18,5 +18,16 @@
<ClCompile Include="..\..\..\testbed\testcms2.c">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\testbed\testplugin.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\testbed\zoo_icc.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\testbed\testcms2.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/configure b/configure
index 425273d..e9218e9 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for lcms2 2.5.
+# Generated by GNU Autoconf 2.69 for lcms2 2.6.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='lcms2'
PACKAGE_TARNAME='lcms2'
-PACKAGE_VERSION='2.5'
-PACKAGE_STRING='lcms2 2.5'
+PACKAGE_VERSION='2.6'
+PACKAGE_STRING='lcms2 2.6'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1338,7 +1338,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures lcms2 2.5 to adapt to many kinds of systems.
+\`configure' configures lcms2 2.6 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1408,7 +1408,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of lcms2 2.5:";;
+ short | recursive ) echo "Configuration of lcms2 2.6:";;
esac
cat <<\_ACEOF
@@ -1429,8 +1429,8 @@ Optional Features:
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --without-jpeg disable JPEG support
- --without-tiff disable TIFF support
+ --with-jpeg=DIR use jpeg installed in DIR
+ --with-tiff=DIR use tiff installed in DIR
--without-zlib disable ZLIB support
--with-pic try to use only PIC/non-PIC objects [default=use
both]
@@ -1517,7 +1517,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-lcms2 configure 2.5
+lcms2 configure 2.6
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2003,7 +2003,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by lcms2 $as_me 2.5, which was
+It was created by lcms2 $as_me 2.6, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2374,7 +2374,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# then set age to 0.
#
LIBRARY_CURRENT=2
-LIBRARY_REVISION=5
+LIBRARY_REVISION=6
LIBRARY_AGE=0
@@ -2918,7 +2918,7 @@ fi
# Define the identity of the package.
PACKAGE='lcms2'
- VERSION='2.5'
+ VERSION='2.6'
# Some tools Automake needs.
@@ -2950,21 +2950,45 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
-# Disable JPEG.
+# Point to JPEG installed in DIR or disable JPEG with --without-jpeg.
# Check whether --with-jpeg was given.
if test "${with_jpeg+set}" = set; then :
- withval=$with_jpeg; with_jpeg=$withval
+ withval=$with_jpeg;
+ if test "x$withval" = "xno" ; then
+ with_jpeg='no'
+ else
+ if test "x$withval" != "xyes" ; then
+ with_jpeg=$withval
+ JPEG_DIR=$withval
+ CPPFLAGS="$CPPFLAGS -I$JPEG_DIR/include"
+ LDFLAGS="$LDFLAGS -L$JPEG_DIR/lib"
+ fi
+ with_jpeg='yes'
+ fi
+
else
with_jpeg='yes'
fi
-# Disable TIFF.
+# Point to TIFF installed in DIR or disable TIFF with --without-tiff.
# Check whether --with-tiff was given.
if test "${with_tiff+set}" = set; then :
- withval=$with_tiff; with_tiff=$withval
+ withval=$with_tiff;
+ if test "x$withval" = "xno" ; then
+ with_tiff='no'
+ else
+ if test "x$withval" != "xyes" ; then
+ with_tiff=$withval
+ TIFF_DIR=$withval
+ CPPFLAGS="$CPPFLAGS -I$TIFF_DIR/include"
+ LDFLAGS="$LDFLAGS -L$TIFF_DIR/lib"
+ fi
+ with_tiff='yes'
+ fi
+
else
with_tiff='yes'
fi
@@ -15961,8 +15985,8 @@ have_jpeg='no'
LIB_JPEG=''
if test ! "$with_jpeg" = 'no'
then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JPEG support " >&5
-$as_echo_n "checking for JPEG support ... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JPEG support" >&5
+$as_echo_n "checking for JPEG support... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
$as_echo "" >&6; }
failed=0;
@@ -16443,8 +16467,8 @@ have_tiff='no'
LIB_TIFF=''
if test ! "$with_tiff" = 'no'
then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIFF support " >&5
-$as_echo_n "checking for TIFF support ... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TIFF support" >&5
+$as_echo_n "checking for TIFF support... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
$as_echo "" >&6; }
failed=0;
@@ -17256,7 +17280,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by lcms2 $as_me 2.5, which was
+This file was extended by lcms2 $as_me 2.6, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -17313,7 +17337,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-lcms2 config.status 2.5
+lcms2 config.status 2.6
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 7041865..777a962 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ AC_PREREQ(2.60)
#
# Set the package name and version
#
-AC_INIT(lcms2,2.5)
+AC_INIT(lcms2,2.6)
#
# Libtool library revision control info
@@ -31,7 +31,7 @@ AC_INIT(lcms2,2.5)
# then set age to 0.
#
LIBRARY_CURRENT=2
-LIBRARY_REVISION=5
+LIBRARY_REVISION=6
LIBRARY_AGE=0
AC_SUBST(LIBRARY_CURRENT)dnl
@@ -43,17 +43,41 @@ AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([foreign 1.7.2 no-define dist-zip])
-# Disable JPEG.
+# Point to JPEG installed in DIR or disable JPEG with --without-jpeg.
AC_ARG_WITH(jpeg,
- [ --without-jpeg disable JPEG support],
- [with_jpeg=$withval],
- [with_jpeg='yes'])
+ [ --with-jpeg=DIR use jpeg installed in DIR],
+ [
+ if [ test "x$withval" = "xno" ]; then
+ [with_jpeg='no']
+ else
+ if [ test "x$withval" != "xyes" ]; then
+ with_jpeg=$withval
+ JPEG_DIR=$withval
+ CPPFLAGS="$CPPFLAGS -I$JPEG_DIR/include"
+ LDFLAGS="$LDFLAGS -L$JPEG_DIR/lib"
+ fi
+ [with_jpeg='yes']
+ fi
+ ],
+ [with_jpeg='yes'])
-# Disable TIFF.
+# Point to TIFF installed in DIR or disable TIFF with --without-tiff.
AC_ARG_WITH(tiff,
- [ --without-tiff disable TIFF support],
- [with_tiff=$withval],
- [with_tiff='yes'])
+ [ --with-tiff=DIR use tiff installed in DIR],
+ [
+ if [ test "x$withval" = "xno" ]; then
+ [with_tiff='no']
+ else
+ if [ test "x$withval" != "xyes" ]; then
+ with_tiff=$withval
+ TIFF_DIR=$withval
+ CPPFLAGS="$CPPFLAGS -I$TIFF_DIR/include"
+ LDFLAGS="$LDFLAGS -L$TIFF_DIR/lib"
+ fi
+ [with_tiff='yes']
+ fi
+ ],
+ [with_tiff='yes'])
# Disable ZLIB
AC_ARG_WITH(zlib,
@@ -116,7 +140,7 @@ have_jpeg='no'
LIB_JPEG=''
if test ! "$with_jpeg" = 'no'
then
- AC_MSG_CHECKING(for JPEG support )
+ AC_MSG_CHECKING([for JPEG support])
AC_MSG_RESULT()
failed=0;
passed=0;
@@ -221,7 +245,7 @@ have_tiff='no'
LIB_TIFF=''
if test ! "$with_tiff" = 'no'
then
- AC_MSG_CHECKING(for TIFF support )
+ AC_MSG_CHECKING([for TIFF support])
AC_MSG_RESULT()
failed=0;
passed=0;
diff --git a/doc/LittleCMS2.5 API.pdf b/doc/LittleCMS2.5 API.pdf
deleted file mode 100755
index 581b244..0000000
--- a/doc/LittleCMS2.5 API.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/LittleCMS2.5 Plugin API.pdf b/doc/LittleCMS2.5 Plugin API.pdf
deleted file mode 100755
index 8017972..0000000
--- a/doc/LittleCMS2.5 Plugin API.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/LittleCMS2.5 tutorial.pdf b/doc/LittleCMS2.5 tutorial.pdf
deleted file mode 100755
index 13d7596..0000000
--- a/doc/LittleCMS2.5 tutorial.pdf
+++ /dev/null
Binary files differ
diff --git a/doc/LittleCMS2.6 API.pdf b/doc/LittleCMS2.6 API.pdf
new file mode 100755
index 0000000..e8e004b
--- /dev/null
+++ b/doc/LittleCMS2.6 API.pdf
Binary files differ
diff --git a/doc/LittleCMS2.6 Plugin API.pdf b/doc/LittleCMS2.6 Plugin API.pdf
new file mode 100755
index 0000000..3a31286
--- /dev/null
+++ b/doc/LittleCMS2.6 Plugin API.pdf
Binary files differ
diff --git a/doc/LittleCMS2.6 tutorial.pdf b/doc/LittleCMS2.6 tutorial.pdf
new file mode 100755
index 0000000..abb2c69
--- /dev/null
+++ b/doc/LittleCMS2.6 tutorial.pdf
Binary files differ
diff --git a/include/lcms2.h b/include/lcms2.h
index c801409..c993a4b 100644
--- a/include/lcms2.h
+++ b/include/lcms2.h
@@ -23,7 +23,7 @@
//
//---------------------------------------------------------------------------------
//
-// Version 2.6b
+// Version 2.6
//
#ifndef _lcms2_H
@@ -55,6 +55,10 @@
// Uncomment to get rid of the tables for "half" float support
// #define CMS_NO_HALF_SUPPORT 1
+// Uncomment to get cmsContext legacy behavior: just a void pointer passed through.
+// DON'T USE UNLESS STRICTLY NECESSARY!
+// #define CMS_CONTEXT_IN_LEGACY_MODE 1
+
// ********** End of configuration toggles ******************************
// Needed for streams
@@ -173,10 +177,6 @@ typedef int cmsBool;
// 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
-#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
-# define CMS_USE_BIG_ENDIAN 1
-#endif
-
#if defined(__sgi__) || defined(__sgi) || defined(sparc)
# define CMS_USE_BIG_ENDIAN 1
#endif
@@ -193,14 +193,18 @@ typedef int cmsBool;
#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC)
# define CMS_USE_BIG_ENDIAN 1
-# if defined (__GNUC__)
-# if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
-# // Don't use big endian for PowerPC little endian mode
+# 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
#endif
+// WORDS_BIGENDIAN takes precedence
+#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
+# define CMS_USE_BIG_ENDIAN 1
+#endif
#ifdef macintosh
# ifdef __BIG_ENDIAN__
@@ -624,7 +628,6 @@ typedef struct {
// Little CMS specific typedefs
-typedef void* cmsContext; // Context identifier for multithreaded environments
typedef void* cmsHANDLE ; // Generic handle
typedef void* cmsHPROFILE; // Opaque typedefs to hide internals
typedef void* cmsHTRANSFORM;
@@ -994,11 +997,29 @@ typedef struct {
CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
CMSAPI long int CMSEXPORT cmsfilelength(FILE* f);
-// Plug-In registering ---------------------------------------------------------------------------------------------------
+
+// Context handling --------------------------------------------------------------------------------------------------------
+
+// Each context holds its owns globals and its own plug-ins. There is a global context with the id = 0 for lecacy compatibility
+// though using the global context is not recomended. Proper context handling makes lcms more thread-safe.
+
+#ifdef CMS_CONTEXT_IN_LEGACY_MODE
+ typedef void* cmsContext;
+#else
+ typedef struct _cmsContext_struct* cmsContext;
+#endif
+
+CMSAPI cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData);
+CMSAPI void CMSEXPORT cmsDeleteContext(cmsContext ContexID);
+CMSAPI cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData);
+CMSAPI void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID);
+
+// Plug-In registering --------------------------------------------------------------------------------------------------
CMSAPI cmsBool CMSEXPORT cmsPlugin(void* Plugin);
CMSAPI cmsBool CMSEXPORT cmsPluginTHR(cmsContext ContextID, void* Plugin);
CMSAPI void CMSEXPORT cmsUnregisterPlugins(void);
+CMSAPI void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID);
// Error logging ----------------------------------------------------------------------------------------------------------
@@ -1035,6 +1056,7 @@ typedef void (* cmsLogErrorHandlerFunction)(cmsContext ContextID, cmsUInt32Numb
// Allows user to set any specific logger
CMSAPI void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn);
+CMSAPI void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn);
// Conversions --------------------------------------------------------------------------------------------------------------
@@ -1587,6 +1609,7 @@ CMSAPI cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransfo
// Call with NULL as parameters to get the intent count
CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
+CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
// Flags
@@ -1698,11 +1721,22 @@ CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform,
cmsUInt32Number Stride);
-CMSAPI void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
+CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
+
+CMSAPI void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID,
+ const cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]);
+CMSAPI void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID,
+ cmsUInt16Number AlarmCodes[cmsMAXCHANNELS]);
+
+
+
// Adaptation state for absolute colorimetric intent
CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d);
+CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d);
+
+
// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed
CMSAPI cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform);
diff --git a/include/lcms2_plugin.h b/include/lcms2_plugin.h
index 10e61cb..0c95d1f 100644
--- a/include/lcms2_plugin.h
+++ b/include/lcms2_plugin.h
@@ -202,6 +202,7 @@ typedef void* (* _cmsDupUserDataFn)(cmsContext ContextID, const void* Data);
#define cmsPluginMultiProcessElementSig 0x6D706548 // 'mpeH'
#define cmsPluginOptimizationSig 0x6F707448 // 'optH'
#define cmsPluginTransformSig 0x7A666D48 // 'xfmH'
+#define cmsPluginMutexSig 0x6D747A48 // 'mtxH'
typedef struct _cmsPluginBaseStruct {
@@ -218,19 +219,28 @@ typedef struct _cmsPluginBaseStruct {
//----------------------------------------------------------------------------------------------------------
// Memory handler. Each new plug-in type replaces current behaviour
+
+typedef void* (* _cmsMallocFnPtrType)(cmsContext ContextID, cmsUInt32Number size);
+typedef void (* _cmsFreeFnPtrType)(cmsContext ContextID, void *Ptr);
+typedef void* (* _cmsReallocFnPtrType)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
+
+typedef void* (* _cmsMalloZerocFnPtrType)(cmsContext ContextID, cmsUInt32Number size);
+typedef void* (* _cmsCallocFnPtrType)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
+typedef void* (* _cmsDupFnPtrType)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
+
typedef struct {
cmsPluginBase base;
// Required
- void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size);
- void (* FreePtr)(cmsContext ContextID, void *Ptr);
- void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
+ _cmsMallocFnPtrType MallocPtr;
+ _cmsFreeFnPtrType FreePtr;
+ _cmsReallocFnPtrType ReallocPtr;
// Optional
- void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size);
- void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
- void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
+ _cmsMalloZerocFnPtrType MallocZeroPtr;
+ _cmsCallocFnPtrType CallocPtr;
+ _cmsDupFnPtrType DupPtr;
} cmsPluginMemHandler;
@@ -593,6 +603,29 @@ typedef struct {
} cmsPluginTransform;
+//----------------------------------------------------------------------------------------------------------
+// Mutex
+
+typedef void* (* _cmsCreateMutexFnPtrType)(cmsContext ContextID);
+typedef void (* _cmsDestroyMutexFnPtrType)(cmsContext ContextID, void* mtx);
+typedef cmsBool (* _cmsLockMutexFnPtrType)(cmsContext ContextID, void* mtx);
+typedef void (* _cmsUnlockMutexFnPtrType)(cmsContext ContextID, void* mtx);
+
+typedef struct {
+ cmsPluginBase base;
+
+ _cmsCreateMutexFnPtrType CreateMutexPtr;
+ _cmsDestroyMutexFnPtrType DestroyMutexPtr;
+ _cmsLockMutexFnPtrType LockMutexPtr;
+ _cmsUnlockMutexFnPtrType UnlockMutexPtr;
+
+} cmsPluginMutex;
+
+CMSAPI void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID);
+CMSAPI void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx);
+CMSAPI cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx);
+CMSAPI void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx);
+
#ifndef CMS_USE_CPP_API
# ifdef __cplusplus
diff --git a/src/cmscam02.c b/src/cmscam02.c
index 2a8cf04..9d874aa 100644
--- a/src/cmscam02.c
+++ b/src/cmscam02.c
@@ -437,12 +437,13 @@ void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh
{
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
-
- memset(&clr, 0, sizeof(clr));
+
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
+ memset(&clr, 0, sizeof(clr));
+
clr.XYZ[0] = pIn ->X;
clr.XYZ[1] = pIn ->Y;
clr.XYZ[2] = pIn ->Z;
@@ -462,12 +463,13 @@ void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ
{
CAM02COLOR clr;
cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
-
- memset(&clr, 0, sizeof(clr));
+
_cmsAssert(lpMod != NULL);
_cmsAssert(pIn != NULL);
_cmsAssert(pOut != NULL);
+ memset(&clr, 0, sizeof(clr));
+
clr.J = pIn -> J;
clr.C = pIn -> C;
clr.h = pIn -> h;
diff --git a/src/cmscnvrt.c b/src/cmscnvrt.c
index 4696cc8..1a93e83 100644
--- a/src/cmscnvrt.c
+++ b/src/cmscnvrt.c
@@ -108,15 +108,68 @@ static cmsIntentsList DefaultIntents[] = {
// A pointer to the begining of the list
-static cmsIntentsList *Intents = DefaultIntents;
+_cmsIntentsPluginChunkType _cmsIntentsPluginChunk = { NULL };
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginIntentsList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsIntentsPluginChunkType newHead = { NULL };
+ cmsIntentsList* entry;
+ cmsIntentsList* Anterior = NULL;
+ _cmsIntentsPluginChunkType* head = (_cmsIntentsPluginChunkType*) src->chunks[IntentPlugin];
+
+ // Walk the list copying all nodes
+ for (entry = head->Intents;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ cmsIntentsList *newEntry = ( cmsIntentsList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsIntentsList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.Intents == NULL)
+ newHead.Intents = newEntry;
+ }
+
+ ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsIntentsPluginChunkType));
+}
+
+void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginIntentsList(ctx, src);
+ }
+ else {
+ static _cmsIntentsPluginChunkType IntentsPluginChunkType = { NULL };
+ ctx ->chunks[IntentPlugin] = _cmsSubAllocDup(ctx ->MemPool, &IntentsPluginChunkType, sizeof(_cmsIntentsPluginChunkType));
+ }
+}
+
// Search the list for a suitable intent. Returns NULL if not found
static
-cmsIntentsList* SearchIntent(cmsUInt32Number Intent)
+cmsIntentsList* SearchIntent(cmsContext ContextID, cmsUInt32Number Intent)
{
+ _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin);
cmsIntentsList* pt;
- for (pt = Intents; pt != NULL; pt = pt -> Next)
+ for (pt = ctx -> Intents; pt != NULL; pt = pt -> Next)
+ if (pt ->Intent == Intent) return pt;
+
+ for (pt = DefaultIntents; pt != NULL; pt = pt -> Next)
if (pt ->Intent == Intent) return pt;
return NULL;
@@ -1002,7 +1055,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID,
// this case would present some issues if the custom intent tries to do things like
// preserve primaries. This solution is not perfect, but works well on most cases.
- Intent = SearchIntent(TheIntents[0]);
+ Intent = SearchIntent(ContextID, TheIntents[0]);
if (Intent == NULL) {
cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]);
return NULL;
@@ -1017,12 +1070,14 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID,
// Get information about available intents. nMax is the maximum space for the supplied "Codes"
// and "Descriptions" the function returns the total number of intents, which may be greater
// than nMax, although the matrices are not populated beyond this level.
-cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
+cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID, cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
{
+ _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(ContextID, IntentPlugin);
cmsIntentsList* pt;
cmsUInt32Number nIntents;
- for (nIntents=0, pt = Intents; pt != NULL; pt = pt -> Next)
+
+ for (nIntents=0, pt = ctx->Intents; pt != NULL; pt = pt -> Next)
{
if (nIntents < nMax) {
if (Codes != NULL)
@@ -1035,37 +1090,52 @@ cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32
nIntents++;
}
+ for (nIntents=0, pt = DefaultIntents; pt != NULL; pt = pt -> Next)
+ {
+ if (nIntents < nMax) {
+ if (Codes != NULL)
+ Codes[nIntents] = pt ->Intent;
+
+ if (Descriptions != NULL)
+ Descriptions[nIntents] = pt ->Description;
+ }
+
+ nIntents++;
+ }
return nIntents;
}
+cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
+{
+ return cmsGetSupportedIntentsTHR(NULL, nMax, Codes, Descriptions);
+}
+
// The plug-in registration. User can add new intents or override default routines
cmsBool _cmsRegisterRenderingIntentPlugin(cmsContext id, cmsPluginBase* Data)
{
+ _cmsIntentsPluginChunkType* ctx = ( _cmsIntentsPluginChunkType*) _cmsContextGetClientChunk(id, IntentPlugin);
cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data;
cmsIntentsList* fl;
- // Do we have to reset the intents?
+ // Do we have to reset the custom intents?
if (Data == NULL) {
- Intents = DefaultIntents;
- return TRUE;
+ ctx->Intents = NULL;
+ return TRUE;
}
- fl = SearchIntent(Plugin ->Intent);
+ fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
+ if (fl == NULL) return FALSE;
- if (fl == NULL) {
- fl = (cmsIntentsList*) _cmsPluginMalloc(id, sizeof(cmsIntentsList));
- if (fl == NULL) return FALSE;
- }
fl ->Intent = Plugin ->Intent;
- strncpy(fl ->Description, Plugin ->Description, 255);
- fl ->Description[255] = 0;
+ strncpy(fl ->Description, Plugin ->Description, sizeof(fl ->Description)-1);
+ fl ->Description[sizeof(fl ->Description)-1] = 0;
fl ->Link = Plugin ->Link;
- fl ->Next = Intents;
- Intents = fl;
+ fl ->Next = ctx ->Intents;
+ ctx ->Intents = fl;
return TRUE;
}
diff --git a/src/cmserr.c b/src/cmserr.c
index 166793f..4bfc0a7 100644
--- a/src/cmserr.c
+++ b/src/cmserr.c
@@ -31,13 +31,14 @@
// compare two strings ignoring case
int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2)
{
- register const unsigned char *us1 = (const unsigned char *)s1,
- *us2 = (const unsigned char *)s2;
+ register const unsigned char *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
- while (toupper(*us1) == toupper(*us2++))
- if (*us1++ == '\0')
- return (0);
- return (toupper(*us1) - toupper(*--us2));
+ while (toupper(*us1) == toupper(*us2++))
+ if (*us1++ == '\0')
+ return 0;
+
+ return (toupper(*us1) - toupper(*--us2));
}
// long int because C99 specifies ftell in such way (7.19.9.2)
@@ -62,9 +63,8 @@ long int CMSEXPORT cmsfilelength(FILE* f)
//
// This is the interface to low-level memory management routines. By default a simple
// wrapping to malloc/free/realloc is provided, although there is a limit on the max
-// amount of memoy that can be reclaimed. This is mostly as a safety feature to
-// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms
-// would never need.
+// amount of memoy that can be reclaimed. This is mostly as a safety feature to prevent
+// bogus or evil code to allocate huge blocks that otherwise lcms would never need.
#define MAX_MEMORY_FOR_ALLOC ((cmsUInt32Number)(1024U*1024U*512U))
@@ -74,7 +74,7 @@ long int CMSEXPORT cmsfilelength(FILE* f)
// required to be implemented: malloc, realloc and free, although the user may want to
// replace the optional mallocZero, calloc and dup as well.
-cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// *********************************************************************************
@@ -114,7 +114,7 @@ void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr)
cmsUNUSED_PARAMETER(ContextID);
}
-// The default realloc function. Again it check for exploits. If Ptr is NULL,
+// The default realloc function. Again it checks for exploits. If Ptr is NULL,
// realloc behaves the same way as malloc and allocates a new block of size bytes.
static
void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
@@ -167,28 +167,73 @@ void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number si
return mem;
}
-// Pointers to malloc and _cmsFree functions in current environment
-static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocDefaultFn;
-static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size) = _cmsMallocZeroDefaultFn;
-static void (* FreePtr)(cmsContext ContextID, void *Ptr) = _cmsFreeDefaultFn;
-static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize) = _cmsReallocDefaultFn;
-static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn;
-static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size) = _cmsDupDefaultFn;
+
+// Pointers to memory manager functions in Context0
+_cmsMemPluginChunkType _cmsMemPluginChunk = { _cmsMallocDefaultFn, _cmsMallocZeroDefaultFn, _cmsFreeDefaultFn,
+ _cmsReallocDefaultFn, _cmsCallocDefaultFn, _cmsDupDefaultFn
+ };
+
+
+// Reset and duplicate memory manager
+void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
+{
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+
+ // Duplicate
+ ctx ->chunks[MemPlugin] = _cmsSubAllocDup(ctx ->MemPool, src ->chunks[MemPlugin], sizeof(_cmsMemPluginChunkType));
+ }
+ else {
+
+ // To reset it, we use the default allocators, which cannot be overriden
+ ctx ->chunks[MemPlugin] = &ctx ->DefaultMemoryManager;
+ }
+}
+
+// Auxiliar to fill memory management functions from plugin (or context 0 defaults)
+void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr)
+{
+ if (Plugin == NULL) {
+
+ memcpy(ptr, &_cmsMemPluginChunk, sizeof(_cmsMemPluginChunk));
+ }
+ else {
+
+ ptr ->MallocPtr = Plugin -> MallocPtr;
+ ptr ->FreePtr = Plugin -> FreePtr;
+ ptr ->ReallocPtr = Plugin -> ReallocPtr;
+
+ // Make sure we revert to defaults
+ ptr ->MallocZeroPtr= _cmsMallocZeroDefaultFn;
+ ptr ->CallocPtr = _cmsCallocDefaultFn;
+ ptr ->DupPtr = _cmsDupDefaultFn;
+
+ if (Plugin ->MallocZeroPtr != NULL) ptr ->MallocZeroPtr = Plugin -> MallocZeroPtr;
+ if (Plugin ->CallocPtr != NULL) ptr ->CallocPtr = Plugin -> CallocPtr;
+ if (Plugin ->DupPtr != NULL) ptr ->DupPtr = Plugin -> DupPtr;
+
+ }
+}
+
// Plug-in replacement entry
-cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
+cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase *Data)
{
- cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
+ cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
+ _cmsMemPluginChunkType* ptr;
- // NULL forces to reset to defaults
+ // NULL forces to reset to defaults. In this special case, the defaults are stored in the context structure.
+ // Remaining plug-ins does NOT have any copy in the context structure, but this is somehow special as the
+ // context internal data should be malloce'd by using those functions.
if (Data == NULL) {
- MallocPtr = _cmsMallocDefaultFn;
- MallocZeroPtr= _cmsMallocZeroDefaultFn;
- FreePtr = _cmsFreeDefaultFn;
- ReallocPtr = _cmsReallocDefaultFn;
- CallocPtr = _cmsCallocDefaultFn;
- DupPtr = _cmsDupDefaultFn;
+ struct _cmsContext_struct* ctx = ( struct _cmsContext_struct*) ContextID;
+
+ // Return to the default allocators
+ if (ContextID != NULL) {
+ ctx->chunks[MemPlugin] = (void*) &ctx->DefaultMemoryManager;
+ }
return TRUE;
}
@@ -198,51 +243,56 @@ cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
Plugin -> ReallocPtr == NULL) return FALSE;
// Set replacement functions
- MallocPtr = Plugin -> MallocPtr;
- FreePtr = Plugin -> FreePtr;
- ReallocPtr = Plugin -> ReallocPtr;
-
- if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr;
- if (Plugin ->CallocPtr != NULL) CallocPtr = Plugin -> CallocPtr;
- if (Plugin ->DupPtr != NULL) DupPtr = Plugin -> DupPtr;
+ ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ if (ptr == NULL)
+ return FALSE;
+ _cmsInstallAllocFunctions(Plugin, ptr);
return TRUE;
}
// Generic allocate
void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size)
{
- return MallocPtr(ContextID, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr ->MallocPtr(ContextID, size);
}
// Generic allocate & zero
void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size)
{
- return MallocZeroPtr(ContextID, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr->MallocZeroPtr(ContextID, size);
}
// Generic calloc
void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
{
- return CallocPtr(ContextID, num, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr->CallocPtr(ContextID, num, size);
}
// Generic reallocate
void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
{
- return ReallocPtr(ContextID, Ptr, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr->ReallocPtr(ContextID, Ptr, size);
}
// Generic free memory
void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr)
{
- if (Ptr != NULL) FreePtr(ContextID, Ptr);
+ if (Ptr != NULL) {
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ ptr ->FreePtr(ContextID, Ptr);
+ }
}
// Generic block duplication
void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size)
{
- return DupPtr(ContextID, Org, size);
+ _cmsMemPluginChunkType* ptr = (_cmsMemPluginChunkType*) _cmsContextGetClientChunk(ContextID, MemPlugin);
+ return ptr ->DupPtr(ContextID, Org, size);
}
// ********************************************************************************************
@@ -351,6 +401,26 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
return (void*) ptr;
}
+// Duplicate in pool
+void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size)
+{
+ void *NewPtr;
+
+ // Dup of null pointer is also NULL
+ if (ptr == NULL)
+ return NULL;
+
+ NewPtr = _cmsSubAlloc(s, size);
+
+ if (ptr != NULL && NewPtr != NULL) {
+ memcpy(NewPtr, ptr, size);
+ }
+
+ return NewPtr;
+}
+
+
+
// Error logging ******************************************************************
// There is no error handling at all. When a funtion fails, it returns proper value.
@@ -372,8 +442,26 @@ void* _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
// This is our default log error
static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
-// The current handler in actual environment
-static cmsLogErrorHandlerFunction LogErrorHandler = DefaultLogErrorHandlerFunction;
+// Context0 storage, which is global
+_cmsLogErrorChunkType _cmsLogErrorChunk = { DefaultLogErrorHandlerFunction };
+
+// Allocates and inits error logger container for a given context. If src is NULL, only initializes the value
+// to the default. Otherwise, it duplicates the value. The interface is standard across all context clients
+void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsLogErrorChunkType LogErrorChunk = { DefaultLogErrorHandlerFunction };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[Logger];
+ }
+ else {
+ from = &LogErrorChunk;
+ }
+
+ ctx ->chunks[Logger] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsLogErrorChunkType));
+}
// The default error logger does nothing.
static
@@ -387,13 +475,24 @@ void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorC
cmsUNUSED_PARAMETER(Text);
}
-// Change log error
+// Change log error, context based
+void CMSEXPORT cmsSetLogErrorHandlerTHR(cmsContext ContextID, cmsLogErrorHandlerFunction Fn)
+{
+ _cmsLogErrorChunkType* lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
+
+ if (lhg != NULL) {
+
+ if (Fn == NULL)
+ lhg -> LogErrorHandler = DefaultLogErrorHandlerFunction;
+ else
+ lhg -> LogErrorHandler = Fn;
+ }
+}
+
+// Change log error, legacy
void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn)
{
- if (Fn == NULL)
- LogErrorHandler = DefaultLogErrorHandlerFunction;
- else
- LogErrorHandler = Fn;
+ cmsSetLogErrorHandlerTHR(NULL, Fn);
}
// Log an error
@@ -402,13 +501,18 @@ void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, c
{
va_list args;
char Buffer[MAX_ERROR_MESSAGE_LEN];
+ _cmsLogErrorChunkType* lhg;
+
va_start(args, ErrorText);
vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args);
va_end(args);
- // Call handler
- LogErrorHandler(ContextID, ErrorCode, Buffer);
+ // Check for the context, if specified go there. If not, go for the global
+ lhg = (_cmsLogErrorChunkType*) _cmsContextGetClientChunk(ContextID, Logger);
+ if (lhg ->LogErrorHandler) {
+ lhg ->LogErrorHandler(ContextID, ErrorCode, Buffer);
+ }
}
// Utility function to print signatures
@@ -426,3 +530,93 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig)
String[4] = 0;
}
+//--------------------------------------------------------------------------------------------------
+
+// Pointers to memory manager functions in Context0
+_cmsMutexPluginChunkType _cmsMutexPluginChunk = { NULL, NULL, NULL, NULL };
+
+// Allocate and init mutex container.
+void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsMutexPluginChunkType MutexChunk = { NULL, NULL, NULL, NULL };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[MutexPlugin];
+ }
+ else {
+ from = &MutexChunk;
+ }
+
+ ctx ->chunks[MutexPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsMutexPluginChunkType));
+}
+
+// Register new ways to transform
+cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Data)
+{
+ cmsPluginMutex* Plugin = (cmsPluginMutex*) Data;
+ _cmsMutexPluginChunkType* ctx = ( _cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (Data == NULL) {
+
+ // No lock routines
+ ctx->CreateMutexPtr = NULL;
+ ctx->DestroyMutexPtr = NULL;
+ ctx->LockMutexPtr = NULL;
+ ctx ->UnlockMutexPtr = NULL;
+ return TRUE;
+ }
+
+ // Factory callback is required
+ if (Plugin ->CreateMutexPtr == NULL || Plugin ->DestroyMutexPtr == NULL ||
+ Plugin ->LockMutexPtr == NULL || Plugin ->UnlockMutexPtr == NULL) return FALSE;
+
+
+ ctx->CreateMutexPtr = Plugin->CreateMutexPtr;
+ ctx->DestroyMutexPtr = Plugin ->DestroyMutexPtr;
+ ctx ->LockMutexPtr = Plugin ->LockMutexPtr;
+ ctx ->UnlockMutexPtr = Plugin ->UnlockMutexPtr;
+
+ // All is ok
+ return TRUE;
+}
+
+// Generic Mutex fns
+void* CMSEXPORT _cmsCreateMutex(cmsContext ContextID)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->CreateMutexPtr == NULL) return NULL;
+
+ return ptr ->CreateMutexPtr(ContextID);
+}
+
+void CMSEXPORT _cmsDestroyMutex(cmsContext ContextID, void* mtx)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->DestroyMutexPtr != NULL) {
+
+ ptr ->DestroyMutexPtr(ContextID, mtx);
+ }
+}
+
+cmsBool CMSEXPORT _cmsLockMutex(cmsContext ContextID, void* mtx)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->LockMutexPtr == NULL) return TRUE;
+
+ return ptr ->LockMutexPtr(ContextID, mtx);
+}
+
+void CMSEXPORT _cmsUnlockMutex(cmsContext ContextID, void* mtx)
+{
+ _cmsMutexPluginChunkType* ptr = (_cmsMutexPluginChunkType*) _cmsContextGetClientChunk(ContextID, MutexPlugin);
+
+ if (ptr ->UnlockMutexPtr != NULL) {
+
+ ptr ->UnlockMutexPtr(ContextID, mtx);
+ }
+}
diff --git a/src/cmsgamma.c b/src/cmsgamma.c
index e153103..7869166 100644
--- a/src/cmsgamma.c
+++ b/src/cmsgamma.c
@@ -53,7 +53,6 @@ typedef struct _cmsParametricCurvesCollection_st {
} _cmsParametricCurvesCollection;
-
// This is the default (built-in) evaluator
static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R);
@@ -66,22 +65,77 @@ static _cmsParametricCurvesCollection DefaultCurves = {
NULL // Next in chain
};
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginCurvesList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsCurvesPluginChunkType newHead = { NULL };
+ _cmsParametricCurvesCollection* entry;
+ _cmsParametricCurvesCollection* Anterior = NULL;
+ _cmsCurvesPluginChunkType* head = (_cmsCurvesPluginChunkType*) src->chunks[CurvesPlugin];
+
+ _cmsAssert(head != NULL);
+
+ // Walk the list copying all nodes
+ for (entry = head->ParametricCurves;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsParametricCurvesCollection *newEntry = ( _cmsParametricCurvesCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsParametricCurvesCollection));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.ParametricCurves == NULL)
+ newHead.ParametricCurves = newEntry;
+ }
+
+ ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsCurvesPluginChunkType));
+}
+
+// The allocator have to follow the chain
+void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginCurvesList(ctx, src);
+ }
+ else {
+ static _cmsCurvesPluginChunkType CurvesPluginChunk = { NULL };
+ ctx ->chunks[CurvesPlugin] = _cmsSubAllocDup(ctx ->MemPool, &CurvesPluginChunk, sizeof(_cmsCurvesPluginChunkType));
+ }
+}
+
+
// The linked list head
-static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
+_cmsCurvesPluginChunkType _cmsCurvesPluginChunk = { NULL };
// As a way to install new parametric curves
-cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
+ _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin);
cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
_cmsParametricCurvesCollection* fl;
if (Data == NULL) {
- ParametricCurves = &DefaultCurves;
+ ctx -> ParametricCurves = NULL;
return TRUE;
}
- fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(id, sizeof(_cmsParametricCurvesCollection));
+ fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsParametricCurvesCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
@@ -97,8 +151,8 @@ cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext id, cmsPluginBase* Data)
memmove(fl->ParameterCount, Plugin ->ParameterCount, fl->nFunctions * sizeof(cmsUInt32Number));
// Keep linked list
- fl ->Next = ParametricCurves;
- ParametricCurves = fl;
+ fl ->Next = ctx->ParametricCurves;
+ ctx->ParametricCurves = fl;
// All is ok
return TRUE;
@@ -120,12 +174,24 @@ int IsInSet(int Type, _cmsParametricCurvesCollection* c)
// Search for the collection which contains a specific type
static
-_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index)
+_cmsParametricCurvesCollection *GetParametricCurveByType(cmsContext ContextID, int Type, int* index)
{
_cmsParametricCurvesCollection* c;
int Position;
+ _cmsCurvesPluginChunkType* ctx = ( _cmsCurvesPluginChunkType*) _cmsContextGetClientChunk(ContextID, CurvesPlugin);
+
+ for (c = ctx->ParametricCurves; c != NULL; c = c ->Next) {
+
+ Position = IsInSet(Type, c);
- for (c = ParametricCurves; c != NULL; c = c ->Next) {
+ if (Position != -1) {
+ if (index != NULL)
+ *index = Position;
+ return c;
+ }
+ }
+ // If none found, revert for defaults
+ for (c = &DefaultCurves; c != NULL; c = c ->Next) {
Position = IsInSet(Type, c);
@@ -222,7 +288,7 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntr
p ->Segments[i].SampledPoints = NULL;
- c = GetParametricCurveByType(Segments[i].Type, NULL);
+ c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL);
if (c != NULL)
p ->Evals[i] = c ->Evaluator;
}
@@ -648,12 +714,12 @@ cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt
cmsCurveSegment Seg0;
int Pos = 0;
cmsUInt32Number size;
- _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos);
+ _cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos);
_cmsAssert(Params != NULL);
if (c == NULL) {
- cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
+ cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
return NULL;
}
@@ -843,7 +909,10 @@ cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, con
_cmsAssert(InCurve != NULL);
// Try to reverse it analytically whatever possible
- if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) {
+
+ if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 &&
+ /* InCurve -> Segments[0].Type <= 5 */
+ GetParametricCurveByType(InCurve ->InterpParams->ContextID, InCurve ->Segments[0].Type, NULL) != NULL) {
return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID,
-(InCurve -> Segments[0].Type),
diff --git a/src/cmsgmt.c b/src/cmsgmt.c
index 2966f0c..0942765 100644
--- a/src/cmsgmt.c
+++ b/src/cmsgmt.c
@@ -1,590 +1,590 @@
-//---------------------------------------------------------------------------------
-//
-// Little Color Management System
-// Copyright (c) 1998-2012 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"
-
-
-// Auxiliar: append a Lab identity after the given sequence of profiles
-// and return the transform. Lab profile is closed, rest of profiles are kept open.
-cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID,
- cmsUInt32Number nProfiles,
- cmsUInt32Number InputFormat,
- cmsUInt32Number OutputFormat,
- const cmsUInt32Number Intents[],
- const cmsHPROFILE hProfiles[],
- const cmsBool BPC[],
- const cmsFloat64Number AdaptationStates[],
- cmsUInt32Number dwFlags)
-{
- cmsHTRANSFORM xform;
- cmsHPROFILE hLab;
- cmsHPROFILE ProfileList[256];
- cmsBool BPCList[256];
- cmsFloat64Number AdaptationList[256];
- cmsUInt32Number IntentList[256];
- cmsUInt32Number i;
-
- // This is a rather big number and there is no need of dynamic memory
- // since we are adding a profile, 254 + 1 = 255 and this is the limit
- if (nProfiles > 254) return NULL;
-
- // The output space
- hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
- if (hLab == NULL) return NULL;
-
- // Create a copy of parameters
- for (i=0; i < nProfiles; i++) {
-
- ProfileList[i] = hProfiles[i];
- BPCList[i] = BPC[i];
- AdaptationList[i] = AdaptationStates[i];
- IntentList[i] = Intents[i];
- }
-
- // Place Lab identity at chain's end.
- ProfileList[nProfiles] = hLab;
- BPCList[nProfiles] = 0;
- AdaptationList[nProfiles] = 1.0;
- IntentList[nProfiles] = INTENT_RELATIVE_COLORIMETRIC;
-
- // Create the transform
- xform = cmsCreateExtendedTransform(ContextID, nProfiles + 1, ProfileList,
- BPCList,
- IntentList,
- AdaptationList,
- NULL, 0,
- InputFormat,
- OutputFormat,
- dwFlags);
-
- cmsCloseProfile(hLab);
-
- return xform;
-}
-
-
-// Compute K -> L* relationship. Flags may include black point compensation. In this case,
-// the relationship is assumed from the profile with BPC to a black point zero.
-static
-cmsToneCurve* ComputeKToLstar(cmsContext ContextID,
- cmsUInt32Number nPoints,
- cmsUInt32Number nProfiles,
- const cmsUInt32Number Intents[],
- const cmsHPROFILE hProfiles[],
- const cmsBool BPC[],
- const cmsFloat64Number AdaptationStates[],
- cmsUInt32Number dwFlags)
-{
- cmsToneCurve* out = NULL;
- cmsUInt32Number i;
- cmsHTRANSFORM xform;
- cmsCIELab Lab;
- cmsFloat32Number cmyk[4];
- cmsFloat32Number* SampledPoints;
-
- xform = _cmsChain2Lab(ContextID, nProfiles, TYPE_CMYK_FLT, TYPE_Lab_DBL, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
- if (xform == NULL) return NULL;
-
- SampledPoints = (cmsFloat32Number*) _cmsCalloc(ContextID, nPoints, sizeof(cmsFloat32Number));
- if (SampledPoints == NULL) goto Error;
-
- for (i=0; i < nPoints; i++) {
-
- cmyk[0] = 0;
- cmyk[1] = 0;
- cmyk[2] = 0;
- cmyk[3] = (cmsFloat32Number) ((i * 100.0) / (nPoints-1));
-
- cmsDoTransform(xform, cmyk, &Lab, 1);
- SampledPoints[i]= (cmsFloat32Number) (1.0 - Lab.L / 100.0); // Negate K for easier operation
- }
-
- out = cmsBuildTabulatedToneCurveFloat(ContextID, nPoints, SampledPoints);
-
-Error:
-
- cmsDeleteTransform(xform);
- if (SampledPoints) _cmsFree(ContextID, SampledPoints);
-
- return out;
-}
-
-
-// Compute Black tone curve on a CMYK -> CMYK transform. This is done by
-// using the proof direction on both profiles to find K->L* relationship
-// then joining both curves. dwFlags may include black point compensation.
-cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID,
- cmsUInt32Number nPoints,
- cmsUInt32Number nProfiles,
- const cmsUInt32Number Intents[],
- const cmsHPROFILE hProfiles[],
- const cmsBool BPC[],
- const cmsFloat64Number AdaptationStates[],
- cmsUInt32Number dwFlags)
-{
- cmsToneCurve *in, *out, *KTone;
-
- // Make sure CMYK -> CMYK
- if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
- cmsGetColorSpace(hProfiles[nProfiles-1])!= cmsSigCmykData) return NULL;
-
-
- // Make sure last is an output profile
- if (cmsGetDeviceClass(hProfiles[nProfiles - 1]) != cmsSigOutputClass) return NULL;
-
- // Create individual curves. BPC works also as each K to L* is
- // computed as a BPC to zero black point in case of L*
- in = ComputeKToLstar(ContextID, nPoints, nProfiles - 1, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
- if (in == NULL) return NULL;
-
- out = ComputeKToLstar(ContextID, nPoints, 1,
- Intents + (nProfiles - 1),
- hProfiles + (nProfiles - 1),
- BPC + (nProfiles - 1),
- AdaptationStates + (nProfiles - 1),
- dwFlags);
- if (out == NULL) {
- cmsFreeToneCurve(in);
- return NULL;
- }
-
- // Build the relationship. This effectively limits the maximum accuracy to 16 bits, but
- // since this is used on black-preserving LUTs, we are not loosing accuracy in any case
- KTone = cmsJoinToneCurve(ContextID, in, out, nPoints);
-
- // Get rid of components
- cmsFreeToneCurve(in); cmsFreeToneCurve(out);
-
- // Something went wrong...
- if (KTone == NULL) return NULL;
-
- // Make sure it is monotonic
- if (!cmsIsToneCurveMonotonic(KTone)) {
- cmsFreeToneCurve(KTone);
- return NULL;
- }
-
- return KTone;
-}
-
-
-// Gamut LUT Creation -----------------------------------------------------------------------------------------
-
-// Used by gamut & softproofing
-
-typedef struct {
-
- cmsHTRANSFORM hInput; // From whatever input color space. 16 bits to DBL
- cmsHTRANSFORM hForward, hReverse; // Transforms going from Lab to colorant and back
- cmsFloat64Number Thereshold; // The thereshold after which is considered out of gamut
-
- } GAMUTCHAIN;
-
-// This sampler does compute gamut boundaries by comparing original
-// values with a transform going back and forth. Values above ERR_THERESHOLD
-// of maximum are considered out of gamut.
-
-#define ERR_THERESHOLD 5
-
-
-static
-int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
-{
- GAMUTCHAIN* t = (GAMUTCHAIN* ) Cargo;
- cmsCIELab LabIn1, LabOut1;
- cmsCIELab LabIn2, LabOut2;
- cmsUInt16Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS];
- cmsFloat64Number dE1, dE2, ErrorRatio;
-
- // Assume in-gamut by default.
- ErrorRatio = 1.0;
-
- // Convert input to Lab
- cmsDoTransform(t -> hInput, In, &LabIn1, 1);
-
- // converts from PCS to colorant. This always
- // does return in-gamut values,
- cmsDoTransform(t -> hForward, &LabIn1, Proof, 1);
-
- // Now, do the inverse, from colorant to PCS.
- cmsDoTransform(t -> hReverse, Proof, &LabOut1, 1);
-
- memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab));
-
- // Try again, but this time taking Check as input
- cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1);
- cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1);
-
- // Take difference of direct value
- dE1 = cmsDeltaE(&LabIn1, &LabOut1);
-
- // Take difference of converted value
- dE2 = cmsDeltaE(&LabIn2, &LabOut2);
-
-
- // if dE1 is small and dE2 is small, value is likely to be in gamut
- if (dE1 < t->Thereshold && dE2 < t->Thereshold)
- Out[0] = 0;
- else {
-
- // if dE1 is small and dE2 is big, undefined. Assume in gamut
- if (dE1 < t->Thereshold && dE2 > t->Thereshold)
- Out[0] = 0;
- else
- // dE1 is big and dE2 is small, clearly out of gamut
- if (dE1 > t->Thereshold && dE2 < t->Thereshold)
- Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5);
- else {
-
- // dE1 is big and dE2 is also big, could be due to perceptual mapping
- // so take error ratio
- if (dE2 == 0.0)
- ErrorRatio = dE1;
- else
- ErrorRatio = dE1 / dE2;
-
- if (ErrorRatio > t->Thereshold)
- Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5);
- else
- Out[0] = 0;
- }
- }
-
-
- return TRUE;
-}
-
-// Does compute a gamut LUT going back and forth across pcs -> relativ. colorimetric intent -> pcs
-// the dE obtained is then annotated on the LUT. Values truely out of gamut are clipped to dE = 0xFFFE
-// and values changed are supposed to be handled by any gamut remapping, so, are out of gamut as well.
-//
-// **WARNING: This algorithm does assume that gamut remapping algorithms does NOT move in-gamut colors,
-// of course, many perceptual and saturation intents does not work in such way, but relativ. ones should.
-
-cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
- cmsHPROFILE hProfiles[],
- cmsBool BPC[],
- cmsUInt32Number Intents[],
- cmsFloat64Number AdaptationStates[],
- cmsUInt32Number nGamutPCSposition,
- cmsHPROFILE hGamut)
-{
- cmsHPROFILE hLab;
- cmsPipeline* Gamut;
- cmsStage* CLUT;
- cmsUInt32Number dwFormat;
- GAMUTCHAIN Chain;
- int nChannels, nGridpoints;
- cmsColorSpaceSignature ColorSpace;
- cmsUInt32Number i;
- cmsHPROFILE ProfileList[256];
- cmsBool BPCList[256];
- cmsFloat64Number AdaptationList[256];
- cmsUInt32Number IntentList[256];
-
- memset(&Chain, 0, sizeof(GAMUTCHAIN));
-
-
- if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) {
- cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition);
- return NULL;
- }
-
- hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
- if (hLab == NULL) return NULL;
-
-
- // The figure of merit. On matrix-shaper profiles, should be almost zero as
- // the conversion is pretty exact. On LUT based profiles, different resolutions
- // of input and output CLUT may result in differences.
-
- if (cmsIsMatrixShaper(hGamut)) {
-
- Chain.Thereshold = 1.0;
- }
- else {
- Chain.Thereshold = ERR_THERESHOLD;
- }
-
-
- // Create a copy of parameters
- for (i=0; i < nGamutPCSposition; i++) {
- ProfileList[i] = hProfiles[i];
- BPCList[i] = BPC[i];
- AdaptationList[i] = AdaptationStates[i];
- IntentList[i] = Intents[i];
- }
-
- // Fill Lab identity
- ProfileList[nGamutPCSposition] = hLab;
- BPCList[nGamutPCSposition] = 0;
- AdaptationList[nGamutPCSposition] = 1.0;
- IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
-
-
- ColorSpace = cmsGetColorSpace(hGamut);
-
- nChannels = cmsChannelsOf(ColorSpace);
- nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
- dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2));
-
- // 16 bits to Lab double
- Chain.hInput = cmsCreateExtendedTransform(ContextID,
- nGamutPCSposition + 1,
- ProfileList,
- BPCList,
- IntentList,
- AdaptationList,
- NULL, 0,
- dwFormat, TYPE_Lab_DBL,
- cmsFLAGS_NOCACHE);
-
-
- // Does create the forward step. Lab double to device
- dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2));
- Chain.hForward = cmsCreateTransformTHR(ContextID,
- hLab, TYPE_Lab_DBL,
- hGamut, dwFormat,
- INTENT_RELATIVE_COLORIMETRIC,
- cmsFLAGS_NOCACHE);
-
- // Does create the backwards step
- Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat,
- hLab, TYPE_Lab_DBL,
- INTENT_RELATIVE_COLORIMETRIC,
- cmsFLAGS_NOCACHE);
-
-
- // All ok?
- if (Chain.hInput && Chain.hForward && Chain.hReverse) {
-
- // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
- // dE when doing a transform back and forth on the colorimetric intent.
-
- Gamut = cmsPipelineAlloc(ContextID, 3, 1);
- if (Gamut != NULL) {
-
- CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
- if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) {
- cmsPipelineFree(Gamut);
- Gamut = NULL;
- }
- else {
- cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
- }
- }
- }
- else
- Gamut = NULL; // Didn't work...
-
- // Free all needed stuff.
- if (Chain.hInput) cmsDeleteTransform(Chain.hInput);
- if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
- if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);
- if (hLab) cmsCloseProfile(hLab);
-
- // And return computed hull
- return Gamut;
-}
-
-// Total Area Coverage estimation ----------------------------------------------------------------
-
-typedef struct {
- cmsUInt32Number nOutputChans;
- cmsHTRANSFORM hRoundTrip;
- cmsFloat32Number MaxTAC;
- cmsFloat32Number MaxInput[cmsMAXCHANNELS];
-
-} cmsTACestimator;
-
-
-// This callback just accounts the maximum ink dropped in the given node. It does not populate any
-// memory, as the destination table is NULL. Its only purpose it to know the global maximum.
-static
-int EstimateTAC(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo)
-{
- cmsTACestimator* bp = (cmsTACestimator*) Cargo;
- cmsFloat32Number RoundTrip[cmsMAXCHANNELS];
- cmsUInt32Number i;
- cmsFloat32Number Sum;
-
-
- // Evaluate the xform
- cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1);
-
- // All all amounts of ink
- for (Sum=0, i=0; i < bp ->nOutputChans; i++)
- Sum += RoundTrip[i];
-
- // If above maximum, keep track of input values
- if (Sum > bp ->MaxTAC) {
-
- bp ->MaxTAC = Sum;
-
- for (i=0; i < bp ->nOutputChans; i++) {
- bp ->MaxInput[i] = In[i];
- }
- }
-
- return TRUE;
-
- cmsUNUSED_PARAMETER(Out);
-}
-
-
-// Detect Total area coverage of the profile
-cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile)
-{
- cmsTACestimator bp;
- cmsUInt32Number dwFormatter;
- cmsUInt32Number GridPoints[MAX_INPUT_DIMENSIONS];
- cmsHPROFILE hLab;
- cmsContext ContextID = cmsGetProfileContextID(hProfile);
-
- // TAC only works on output profiles
- if (cmsGetDeviceClass(hProfile) != cmsSigOutputClass) {
- return 0;
- }
-
- // Create a fake formatter for result
- dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE);
-
- bp.nOutputChans = T_CHANNELS(dwFormatter);
- bp.MaxTAC = 0; // Initial TAC is 0
-
- // for safety
- if (bp.nOutputChans >= cmsMAXCHANNELS) return 0;
-
- hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
- if (hLab == NULL) return 0;
- // Setup a roundtrip on perceptual intent in output profile for TAC estimation
- bp.hRoundTrip = cmsCreateTransformTHR(ContextID, hLab, TYPE_Lab_16,
- hProfile, dwFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
-
- cmsCloseProfile(hLab);
- if (bp.hRoundTrip == NULL) return 0;
-
- // For L* we only need black and white. For C* we need many points
- GridPoints[0] = 6;
- GridPoints[1] = 74;
- GridPoints[2] = 74;
-
-
- if (!cmsSliceSpace16(3, GridPoints, EstimateTAC, &bp)) {
- bp.MaxTAC = 0;
- }
-
- cmsDeleteTransform(bp.hRoundTrip);
-
- // Results in %
- return bp.MaxTAC;
-}
-
-
-// Carefully, clamp on CIELab space.
-
-cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,
- double amax, double amin,
- double bmax, double bmin)
-{
-
- // Whole Luma surface to zero
-
- if (Lab -> L < 0) {
-
- Lab-> L = Lab->a = Lab-> b = 0.0;
- return FALSE;
- }
-
- // Clamp white, DISCARD HIGHLIGHTS. This is done
- // in such way because icc spec doesn't allow the
- // use of L>100 as a highlight means.
-
- if (Lab->L > 100)
- Lab -> L = 100;
-
- // Check out gamut prism, on a, b faces
-
- if (Lab -> a < amin || Lab->a > amax||
- Lab -> b < bmin || Lab->b > bmax) {
-
- cmsCIELCh LCh;
- double h, slope;
-
- // Falls outside a, b limits. Transports to LCh space,
- // and then do the clipping
-
-
- if (Lab -> a == 0.0) { // Is hue exactly 90?
-
- // atan will not work, so clamp here
- Lab -> b = Lab->b < 0 ? bmin : bmax;
- return TRUE;
- }
-
- cmsLab2LCh(&LCh, Lab);
-
- slope = Lab -> b / Lab -> a;
- h = LCh.h;
-
- // There are 4 zones
-
- if ((h >= 0. && h < 45.) ||
- (h >= 315 && h <= 360.)) {
-
- // clip by amax
- Lab -> a = amax;
- Lab -> b = amax * slope;
- }
- else
- if (h >= 45. && h < 135.)
- {
- // clip by bmax
- Lab -> b = bmax;
- Lab -> a = bmax / slope;
- }
- else
- if (h >= 135. && h < 225.) {
- // clip by amin
- Lab -> a = amin;
- Lab -> b = amin * slope;
-
- }
- else
- if (h >= 225. && h < 315.) {
- // clip by bmin
- Lab -> b = bmin;
- Lab -> a = bmin / slope;
- }
- else {
- cmsSignalError(0, cmsERROR_RANGE, "Invalid angle");
- return FALSE;
- }
-
- }
-
- return TRUE;
-}
+//---------------------------------------------------------------------------------
+//
+// Little Color Management System
+// Copyright (c) 1998-2012 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"
+
+
+// Auxiliar: append a Lab identity after the given sequence of profiles
+// and return the transform. Lab profile is closed, rest of profiles are kept open.
+cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID,
+ cmsUInt32Number nProfiles,
+ cmsUInt32Number InputFormat,
+ cmsUInt32Number OutputFormat,
+ const cmsUInt32Number Intents[],
+ const cmsHPROFILE hProfiles[],
+ const cmsBool BPC[],
+ const cmsFloat64Number AdaptationStates[],
+ cmsUInt32Number dwFlags)
+{
+ cmsHTRANSFORM xform;
+ cmsHPROFILE hLab;
+ cmsHPROFILE ProfileList[256];
+ cmsBool BPCList[256];
+ cmsFloat64Number AdaptationList[256];
+ cmsUInt32Number IntentList[256];
+ cmsUInt32Number i;
+
+ // This is a rather big number and there is no need of dynamic memory
+ // since we are adding a profile, 254 + 1 = 255 and this is the limit
+ if (nProfiles > 254) return NULL;
+
+ // The output space
+ hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
+ if (hLab == NULL) return NULL;
+
+ // Create a copy of parameters
+ for (i=0; i < nProfiles; i++) {
+
+ ProfileList[i] = hProfiles[i];
+ BPCList[i] = BPC[i];
+ AdaptationList[i] = AdaptationStates[i];
+ IntentList[i] = Intents[i];
+ }
+
+ // Place Lab identity at chain's end.
+ ProfileList[nProfiles] = hLab;
+ BPCList[nProfiles] = 0;
+ AdaptationList[nProfiles] = 1.0;
+ IntentList[nProfiles] = INTENT_RELATIVE_COLORIMETRIC;
+
+ // Create the transform
+ xform = cmsCreateExtendedTransform(ContextID, nProfiles + 1, ProfileList,
+ BPCList,
+ IntentList,
+ AdaptationList,
+ NULL, 0,
+ InputFormat,
+ OutputFormat,
+ dwFlags);
+
+ cmsCloseProfile(hLab);
+
+ return xform;
+}
+
+
+// Compute K -> L* relationship. Flags may include black point compensation. In this case,
+// the relationship is assumed from the profile with BPC to a black point zero.
+static
+cmsToneCurve* ComputeKToLstar(cmsContext ContextID,
+ cmsUInt32Number nPoints,
+ cmsUInt32Number nProfiles,
+ const cmsUInt32Number Intents[],
+ const cmsHPROFILE hProfiles[],
+ const cmsBool BPC[],
+ const cmsFloat64Number AdaptationStates[],
+ cmsUInt32Number dwFlags)
+{
+ cmsToneCurve* out = NULL;
+ cmsUInt32Number i;
+ cmsHTRANSFORM xform;
+ cmsCIELab Lab;
+ cmsFloat32Number cmyk[4];
+ cmsFloat32Number* SampledPoints;
+
+ xform = _cmsChain2Lab(ContextID, nProfiles, TYPE_CMYK_FLT, TYPE_Lab_DBL, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
+ if (xform == NULL) return NULL;
+
+ SampledPoints = (cmsFloat32Number*) _cmsCalloc(ContextID, nPoints, sizeof(cmsFloat32Number));
+ if (SampledPoints == NULL) goto Error;
+
+ for (i=0; i < nPoints; i++) {
+
+ cmyk[0] = 0;
+ cmyk[1] = 0;
+ cmyk[2] = 0;
+ cmyk[3] = (cmsFloat32Number) ((i * 100.0) / (nPoints-1));
+
+ cmsDoTransform(xform, cmyk, &Lab, 1);
+ SampledPoints[i]= (cmsFloat32Number) (1.0 - Lab.L / 100.0); // Negate K for easier operation
+ }
+
+ out = cmsBuildTabulatedToneCurveFloat(ContextID, nPoints, SampledPoints);
+
+Error:
+
+ cmsDeleteTransform(xform);
+ if (SampledPoints) _cmsFree(ContextID, SampledPoints);
+
+ return out;
+}
+
+
+// Compute Black tone curve on a CMYK -> CMYK transform. This is done by
+// using the proof direction on both profiles to find K->L* relationship
+// then joining both curves. dwFlags may include black point compensation.
+cmsToneCurve* _cmsBuildKToneCurve(cmsContext ContextID,
+ cmsUInt32Number nPoints,
+ cmsUInt32Number nProfiles,
+ const cmsUInt32Number Intents[],
+ const cmsHPROFILE hProfiles[],
+ const cmsBool BPC[],
+ const cmsFloat64Number AdaptationStates[],
+ cmsUInt32Number dwFlags)
+{
+ cmsToneCurve *in, *out, *KTone;
+
+ // Make sure CMYK -> CMYK
+ if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
+ cmsGetColorSpace(hProfiles[nProfiles-1])!= cmsSigCmykData) return NULL;
+
+
+ // Make sure last is an output profile
+ if (cmsGetDeviceClass(hProfiles[nProfiles - 1]) != cmsSigOutputClass) return NULL;
+
+ // Create individual curves. BPC works also as each K to L* is
+ // computed as a BPC to zero black point in case of L*
+ in = ComputeKToLstar(ContextID, nPoints, nProfiles - 1, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
+ if (in == NULL) return NULL;
+
+ out = ComputeKToLstar(ContextID, nPoints, 1,
+ Intents + (nProfiles - 1),
+ &hProfiles [nProfiles - 1],
+ BPC + (nProfiles - 1),
+ AdaptationStates + (nProfiles - 1),
+ dwFlags);
+ if (out == NULL) {
+ cmsFreeToneCurve(in);
+ return NULL;
+ }
+
+ // Build the relationship. This effectively limits the maximum accuracy to 16 bits, but
+ // since this is used on black-preserving LUTs, we are not loosing accuracy in any case
+ KTone = cmsJoinToneCurve(ContextID, in, out, nPoints);
+
+ // Get rid of components
+ cmsFreeToneCurve(in); cmsFreeToneCurve(out);
+
+ // Something went wrong...
+ if (KTone == NULL) return NULL;
+
+ // Make sure it is monotonic
+ if (!cmsIsToneCurveMonotonic(KTone)) {
+ cmsFreeToneCurve(KTone);
+ return NULL;
+ }
+
+ return KTone;
+}
+
+
+// Gamut LUT Creation -----------------------------------------------------------------------------------------
+
+// Used by gamut & softproofing
+
+typedef struct {
+
+ cmsHTRANSFORM hInput; // From whatever input color space. 16 bits to DBL
+ cmsHTRANSFORM hForward, hReverse; // Transforms going from Lab to colorant and back
+ cmsFloat64Number Thereshold; // The thereshold after which is considered out of gamut
+
+ } GAMUTCHAIN;
+
+// This sampler does compute gamut boundaries by comparing original
+// values with a transform going back and forth. Values above ERR_THERESHOLD
+// of maximum are considered out of gamut.
+
+#define ERR_THERESHOLD 5
+
+
+static
+int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
+{
+ GAMUTCHAIN* t = (GAMUTCHAIN* ) Cargo;
+ cmsCIELab LabIn1, LabOut1;
+ cmsCIELab LabIn2, LabOut2;
+ cmsUInt16Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS];
+ cmsFloat64Number dE1, dE2, ErrorRatio;
+
+ // Assume in-gamut by default.
+ ErrorRatio = 1.0;
+
+ // Convert input to Lab
+ cmsDoTransform(t -> hInput, In, &LabIn1, 1);
+
+ // converts from PCS to colorant. This always
+ // does return in-gamut values,
+ cmsDoTransform(t -> hForward, &LabIn1, Proof, 1);
+
+ // Now, do the inverse, from colorant to PCS.
+ cmsDoTransform(t -> hReverse, Proof, &LabOut1, 1);
+
+ memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab));
+
+ // Try again, but this time taking Check as input
+ cmsDoTransform(t -> hForward, &LabOut1, Proof2, 1);
+ cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1);
+
+ // Take difference of direct value
+ dE1 = cmsDeltaE(&LabIn1, &LabOut1);
+
+ // Take difference of converted value
+ dE2 = cmsDeltaE(&LabIn2, &LabOut2);
+
+
+ // if dE1 is small and dE2 is small, value is likely to be in gamut
+ if (dE1 < t->Thereshold && dE2 < t->Thereshold)
+ Out[0] = 0;
+ else {
+
+ // if dE1 is small and dE2 is big, undefined. Assume in gamut
+ if (dE1 < t->Thereshold && dE2 > t->Thereshold)
+ Out[0] = 0;
+ else
+ // dE1 is big and dE2 is small, clearly out of gamut
+ if (dE1 > t->Thereshold && dE2 < t->Thereshold)
+ Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5);
+ else {
+
+ // dE1 is big and dE2 is also big, could be due to perceptual mapping
+ // so take error ratio
+ if (dE2 == 0.0)
+ ErrorRatio = dE1;
+ else
+ ErrorRatio = dE1 / dE2;
+
+ if (ErrorRatio > t->Thereshold)
+ Out[0] = (cmsUInt16Number) _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5);
+ else
+ Out[0] = 0;
+ }
+ }
+
+
+ return TRUE;
+}
+
+// Does compute a gamut LUT going back and forth across pcs -> relativ. colorimetric intent -> pcs
+// the dE obtained is then annotated on the LUT. Values truely out of gamut are clipped to dE = 0xFFFE
+// and values changed are supposed to be handled by any gamut remapping, so, are out of gamut as well.
+//
+// **WARNING: This algorithm does assume that gamut remapping algorithms does NOT move in-gamut colors,
+// of course, many perceptual and saturation intents does not work in such way, but relativ. ones should.
+
+cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
+ cmsHPROFILE hProfiles[],
+ cmsBool BPC[],
+ cmsUInt32Number Intents[],
+ cmsFloat64Number AdaptationStates[],
+ cmsUInt32Number nGamutPCSposition,
+ cmsHPROFILE hGamut)
+{
+ cmsHPROFILE hLab;
+ cmsPipeline* Gamut;
+ cmsStage* CLUT;
+ cmsUInt32Number dwFormat;
+ GAMUTCHAIN Chain;
+ int nChannels, nGridpoints;
+ cmsColorSpaceSignature ColorSpace;
+ cmsUInt32Number i;
+ cmsHPROFILE ProfileList[256];
+ cmsBool BPCList[256];
+ cmsFloat64Number AdaptationList[256];
+ cmsUInt32Number IntentList[256];
+
+ memset(&Chain, 0, sizeof(GAMUTCHAIN));
+
+
+ if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) {
+ cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition);
+ return NULL;
+ }
+
+ hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
+ if (hLab == NULL) return NULL;
+
+
+ // The figure of merit. On matrix-shaper profiles, should be almost zero as
+ // the conversion is pretty exact. On LUT based profiles, different resolutions
+ // of input and output CLUT may result in differences.
+
+ if (cmsIsMatrixShaper(hGamut)) {
+
+ Chain.Thereshold = 1.0;
+ }
+ else {
+ Chain.Thereshold = ERR_THERESHOLD;
+ }
+
+
+ // Create a copy of parameters
+ for (i=0; i < nGamutPCSposition; i++) {
+ ProfileList[i] = hProfiles[i];
+ BPCList[i] = BPC[i];
+ AdaptationList[i] = AdaptationStates[i];
+ IntentList[i] = Intents[i];
+ }
+
+ // Fill Lab identity
+ ProfileList[nGamutPCSposition] = hLab;
+ BPCList[nGamutPCSposition] = 0;
+ AdaptationList[nGamutPCSposition] = 1.0;
+ IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
+
+
+ ColorSpace = cmsGetColorSpace(hGamut);
+
+ nChannels = cmsChannelsOf(ColorSpace);
+ nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
+ dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2));
+
+ // 16 bits to Lab double
+ Chain.hInput = cmsCreateExtendedTransform(ContextID,
+ nGamutPCSposition + 1,
+ ProfileList,
+ BPCList,
+ IntentList,
+ AdaptationList,
+ NULL, 0,
+ dwFormat, TYPE_Lab_DBL,
+ cmsFLAGS_NOCACHE);
+
+
+ // Does create the forward step. Lab double to device
+ dwFormat = (CHANNELS_SH(nChannels)|BYTES_SH(2));
+ Chain.hForward = cmsCreateTransformTHR(ContextID,
+ hLab, TYPE_Lab_DBL,
+ hGamut, dwFormat,
+ INTENT_RELATIVE_COLORIMETRIC,
+ cmsFLAGS_NOCACHE);
+
+ // Does create the backwards step
+ Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat,
+ hLab, TYPE_Lab_DBL,
+ INTENT_RELATIVE_COLORIMETRIC,
+ cmsFLAGS_NOCACHE);
+
+
+ // All ok?
+ if (Chain.hInput && Chain.hForward && Chain.hReverse) {
+
+ // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
+ // dE when doing a transform back and forth on the colorimetric intent.
+
+ Gamut = cmsPipelineAlloc(ContextID, 3, 1);
+ if (Gamut != NULL) {
+
+ CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
+ if (!cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT)) {
+ cmsPipelineFree(Gamut);
+ Gamut = NULL;
+ }
+ else {
+ cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
+ }
+ }
+ }
+ else
+ Gamut = NULL; // Didn't work...
+
+ // Free all needed stuff.
+ if (Chain.hInput) cmsDeleteTransform(Chain.hInput);
+ if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
+ if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);
+ if (hLab) cmsCloseProfile(hLab);
+
+ // And return computed hull
+ return Gamut;
+}
+
+// Total Area Coverage estimation ----------------------------------------------------------------
+
+typedef struct {
+ cmsUInt32Number nOutputChans;
+ cmsHTRANSFORM hRoundTrip;
+ cmsFloat32Number MaxTAC;
+ cmsFloat32Number MaxInput[cmsMAXCHANNELS];
+
+} cmsTACestimator;
+
+
+// This callback just accounts the maximum ink dropped in the given node. It does not populate any
+// memory, as the destination table is NULL. Its only purpose it to know the global maximum.
+static
+int EstimateTAC(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo)
+{
+ cmsTACestimator* bp = (cmsTACestimator*) Cargo;
+ cmsFloat32Number RoundTrip[cmsMAXCHANNELS];
+ cmsUInt32Number i;
+ cmsFloat32Number Sum;
+
+
+ // Evaluate the xform
+ cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1);
+
+ // All all amounts of ink
+ for (Sum=0, i=0; i < bp ->nOutputChans; i++)
+ Sum += RoundTrip[i];
+
+ // If above maximum, keep track of input values
+ if (Sum > bp ->MaxTAC) {
+
+ bp ->MaxTAC = Sum;
+
+ for (i=0; i < bp ->nOutputChans; i++) {
+ bp ->MaxInput[i] = In[i];
+ }
+ }
+
+ return TRUE;
+
+ cmsUNUSED_PARAMETER(Out);
+}
+
+
+// Detect Total area coverage of the profile
+cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile)
+{
+ cmsTACestimator bp;
+ cmsUInt32Number dwFormatter;
+ cmsUInt32Number GridPoints[MAX_INPUT_DIMENSIONS];
+ cmsHPROFILE hLab;
+ cmsContext ContextID = cmsGetProfileContextID(hProfile);
+
+ // TAC only works on output profiles
+ if (cmsGetDeviceClass(hProfile) != cmsSigOutputClass) {
+ return 0;
+ }
+
+ // Create a fake formatter for result
+ dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE);
+
+ bp.nOutputChans = T_CHANNELS(dwFormatter);
+ bp.MaxTAC = 0; // Initial TAC is 0
+
+ // for safety
+ if (bp.nOutputChans >= cmsMAXCHANNELS) return 0;
+
+ hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
+ if (hLab == NULL) return 0;
+ // Setup a roundtrip on perceptual intent in output profile for TAC estimation
+ bp.hRoundTrip = cmsCreateTransformTHR(ContextID, hLab, TYPE_Lab_16,
+ hProfile, dwFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
+
+ cmsCloseProfile(hLab);
+ if (bp.hRoundTrip == NULL) return 0;
+
+ // For L* we only need black and white. For C* we need many points
+ GridPoints[0] = 6;
+ GridPoints[1] = 74;
+ GridPoints[2] = 74;
+
+
+ if (!cmsSliceSpace16(3, GridPoints, EstimateTAC, &bp)) {
+ bp.MaxTAC = 0;
+ }
+
+ cmsDeleteTransform(bp.hRoundTrip);
+
+ // Results in %
+ return bp.MaxTAC;
+}
+
+
+// Carefully, clamp on CIELab space.
+
+cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,
+ double amax, double amin,
+ double bmax, double bmin)
+{
+
+ // Whole Luma surface to zero
+
+ if (Lab -> L < 0) {
+
+ Lab-> L = Lab->a = Lab-> b = 0.0;
+ return FALSE;
+ }
+
+ // Clamp white, DISCARD HIGHLIGHTS. This is done
+ // in such way because icc spec doesn't allow the
+ // use of L>100 as a highlight means.
+
+ if (Lab->L > 100)
+ Lab -> L = 100;
+
+ // Check out gamut prism, on a, b faces
+
+ if (Lab -> a < amin || Lab->a > amax||
+ Lab -> b < bmin || Lab->b > bmax) {
+
+ cmsCIELCh LCh;
+ double h, slope;
+
+ // Falls outside a, b limits. Transports to LCh space,
+ // and then do the clipping
+
+
+ if (Lab -> a == 0.0) { // Is hue exactly 90?
+
+ // atan will not work, so clamp here
+ Lab -> b = Lab->b < 0 ? bmin : bmax;
+ return TRUE;
+ }
+
+ cmsLab2LCh(&LCh, Lab);
+
+ slope = Lab -> b / Lab -> a;
+ h = LCh.h;
+
+ // There are 4 zones
+
+ if ((h >= 0. && h < 45.) ||
+ (h >= 315 && h <= 360.)) {
+
+ // clip by amax
+ Lab -> a = amax;
+ Lab -> b = amax * slope;
+ }
+ else
+ if (h >= 45. && h < 135.)
+ {
+ // clip by bmax
+ Lab -> b = bmax;
+ Lab -> a = bmax / slope;
+ }
+ else
+ if (h >= 135. && h < 225.) {
+ // clip by amin
+ Lab -> a = amin;
+ Lab -> b = amin * slope;
+
+ }
+ else
+ if (h >= 225. && h < 315.) {
+ // clip by bmin
+ Lab -> b = bmin;
+ Lab -> a = bmin / slope;
+ }
+ else {
+ cmsSignalError(0, cmsERROR_RANGE, "Invalid angle");
+ return FALSE;
+ }
+
+ }
+
+ return TRUE;
+}
diff --git a/src/cmsintrp.c b/src/cmsintrp.c
index 01150d7..5d5f35d 100644
--- a/src/cmsintrp.c
+++ b/src/cmsintrp.c
@@ -33,32 +33,58 @@
static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
// This is the default factory
-static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
+_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL };
+
+// The interpolation plug-in memory chunk allocator/dup
+void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
+{
+ void* from;
+
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+ from = src ->chunks[InterpPlugin];
+ }
+ else {
+ static _cmsInterpPluginChunkType InterpPluginChunk = { NULL };
+
+ from = &InterpPluginChunk;
+ }
+
+ _cmsAssert(from != NULL);
+ ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType));
+}
// Main plug-in entry
-cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
+cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
+ _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
if (Data == NULL) {
- Interpolators = DefaultInterpolatorsFactory;
+ ptr ->Interpolators = NULL;
return TRUE;
}
// Set replacement functions
- Interpolators = Plugin ->InterpolatorsFactory;
+ ptr ->Interpolators = Plugin ->InterpolatorsFactory;
return TRUE;
}
// Set the interpolation method
-cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
-{
- // Invoke factory, possibly in the Plug-in
- p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
+cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p)
+{
+ _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
+
+ p ->Interpolation.Lerp16 = NULL;
+ // Invoke factory, possibly in the Plug-in
+ if (ptr ->Interpolators != NULL)
+ p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
+
// If unsupported by the plug-in, go for the LittleCMS default.
// If happens only if an extern plug-in is being used
if (p ->Interpolation.Lerp16 == NULL)
@@ -68,6 +94,7 @@ cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
if (p ->Interpolation.Lerp16 == NULL) {
return FALSE;
}
+
return TRUE;
}
@@ -112,7 +139,7 @@ cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
- if (!_cmsSetInterpolationRoutine(p)) {
+ if (!_cmsSetInterpolationRoutine(ContextID, p)) {
cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
_cmsFree(ContextID, p);
return NULL;
diff --git a/src/cmsio0.c b/src/cmsio0.c
index 2430e98..4e8cd93 100644
--- a/src/cmsio0.c
+++ b/src/cmsio0.c
@@ -471,6 +471,9 @@ cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
// Set creation date/time
memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created));
+ // Create a mutex if the user provided proper plugin. NULL otherwise
+ Icc ->UsrMutex = _cmsCreateMutex(ContextID);
+
// Return the handle
return (cmsHPROFILE) Icc;
}
@@ -549,9 +552,38 @@ int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks
return n;
}
+// Deletes a tag entry
+
+static
+void _cmsDeleteTagByPos(_cmsICCPROFILE* Icc, int i)
+{
+ _cmsAssert(Icc != NULL);
+ _cmsAssert(i >= 0);
+
+
+ if (Icc -> TagPtrs[i] != NULL) {
+
+ // Free previous version
+ if (Icc ->TagSaveAsRaw[i]) {
+ _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
+ }
+ else {
+ cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
+
+ if (TypeHandler != NULL) {
+
+ cmsTagTypeHandler LocalTypeHandler = *TypeHandler;
+ LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter
+ LocalTypeHandler.ICCVersion = Icc ->Version;
+ LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
+ }
+ }
+
+ }
+}
-// Create a new tag entry
+// Creates a new tag entry
static
cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos)
{
@@ -559,15 +591,15 @@ cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos)
// Search for the tag
i = _cmsSearchTag(Icc, sig, FALSE);
-
- // Now let's do it easy. If the tag has been already written, that's an error
if (i >= 0) {
- cmsSignalError(Icc ->ContextID, cmsERROR_ALREADY_DEFINED, "Tag '%x' already exists", sig);
- return FALSE;
+
+ // Already exists? delete it
+ _cmsDeleteTagByPos(Icc, i);
+ *NewPos = i;
}
else {
- // New one
+ // No, make a new one
if (Icc -> TagCount >= MAX_TABLE_TAG) {
cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG);
@@ -924,7 +956,7 @@ void CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Vers
// 4.2 -> 0x4200000
- Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0), 10, 16) << 16;
+ Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0 + 0.5), 10, 16) << 16;
}
cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile)
@@ -1147,7 +1179,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
else {
// Search for support on this tag
- TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]);
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, Icc -> TagNames[i]);
if (TagDescriptor == NULL) continue; // Unsupported, ignore it
if (TagDescriptor ->DecideType != NULL) {
@@ -1159,7 +1191,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
Type = TagDescriptor ->SupportedTypes[0];
}
- TypeHandler = _cmsGetTagTypeHandler(Type);
+ TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type);
if (TypeHandler == NULL) {
cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]);
@@ -1227,7 +1259,7 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
_cmsICCPROFILE Keep;
- cmsIOHANDLER* PrevIO;
+ cmsIOHANDLER* PrevIO = NULL;
cmsUInt32Number UsedSpace;
cmsContext ContextID;
@@ -1241,8 +1273,8 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
// Pass #1 does compute offsets
- if (!_cmsWriteHeader(Icc, 0)) return 0;
- if (!SaveTags(Icc, &Keep)) return 0;
+ if (!_cmsWriteHeader(Icc, 0)) goto Error;
+ if (!SaveTags(Icc, &Keep)) goto Error;
UsedSpace = PrevIO ->UsedSpace;
@@ -1251,9 +1283,9 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
if (io != NULL) {
Icc ->IOhandler = io;
- if (!SetLinks(Icc)) goto CleanUp;
- if (!_cmsWriteHeader(Icc, UsedSpace)) goto CleanUp;
- if (!SaveTags(Icc, &Keep)) goto CleanUp;
+ if (!SetLinks(Icc)) goto Error;
+ if (!_cmsWriteHeader(Icc, UsedSpace)) goto Error;
+ if (!SaveTags(Icc, &Keep)) goto Error;
}
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
@@ -1262,7 +1294,7 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
return UsedSpace;
-CleanUp:
+Error:
cmsCloseIOhandler(PrevIO);
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
return 0;
@@ -1310,11 +1342,13 @@ cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUIn
cmsIOHANDLER* io;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
+ _cmsAssert(BytesNeeded != NULL);
+
// Should we just calculate the needed space?
if (MemPtr == NULL) {
*BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL);
- return TRUE;
+ return (*BytesNeeded == 0) ? FALSE : TRUE;
}
// That is a real write operation
@@ -1367,6 +1401,8 @@ cmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
rc &= cmsCloseIOhandler(Icc->IOhandler);
}
+ _cmsDestroyMutex(Icc->ContextID, Icc->UsrMutex);
+
_cmsFree(Icc ->ContextID, Icc); // Free placeholder memory
return rc;
@@ -1407,14 +1443,18 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
cmsUInt32Number ElemCount;
int n;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL;
+
n = _cmsSearchTag(Icc, sig, TRUE);
- if (n < 0) return NULL; // Not found, return NULL
+ if (n < 0) goto Error; // Not found, return NULL
// If the element is already in memory, return the pointer
if (Icc -> TagPtrs[n]) {
- if (Icc ->TagSaveAsRaw[n]) return NULL; // We don't support read raw tags as cooked
+ if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked
+
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc -> TagPtrs[n];
}
@@ -1424,23 +1464,32 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
// Seek to its location
if (!io -> Seek(io, Offset))
- return NULL;
+ goto Error;
// Search for support on this tag
- TagDescriptor = _cmsGetTagDescriptor(sig);
- if (TagDescriptor == NULL) return NULL; // Unsupported.
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig);
+ if (TagDescriptor == NULL) {
+
+ char String[5];
+
+ _cmsTagSignature2String(String, sig);
+
+ // An unknown element was found.
+ cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown tag type '%s' found.", String);
+ goto Error; // Unsupported.
+ }
// if supported, get type and check if in list
BaseType = _cmsReadTypeBase(io);
- if (BaseType == 0) return NULL;
+ if (BaseType == 0) goto Error;
- if (!IsTypeSupported(TagDescriptor, BaseType)) return NULL;
+ if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error;
TagSize -= 8; // Alredy read by the type base logic
// Get type handler
- TypeHandler = _cmsGetTagTypeHandler(BaseType);
- if (TypeHandler == NULL) return NULL;
+ TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType);
+ if (TypeHandler == NULL) goto Error;
LocalTypeHandler = *TypeHandler;
@@ -1459,7 +1508,7 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
_cmsTagSignature2String(String, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String);
- return NULL;
+ goto Error;
}
// This is a weird error that may be a symptom of something more serious, the number of
@@ -1475,7 +1524,14 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
// Return the data
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc -> TagPtrs[n];
+
+
+ // Return error and unlock tha data
+Error:
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return NULL;
}
@@ -1509,49 +1565,26 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
cmsFloat64Number Version;
char TypeString[5], SigString[5];
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE;
+ // To delete tags.
if (data == NULL) {
+ // Delete the tag
i = _cmsSearchTag(Icc, sig, FALSE);
- if (i >= 0)
+ if (i >= 0) {
+
+ // Use zero as a mark of deleted
+ _cmsDeleteTagByPos(Icc, i);
Icc ->TagNames[i] = (cmsTagSignature) 0;
- // Unsupported by now, reserved for future ampliations (delete)
- return FALSE;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return TRUE;
+ }
+ // Didn't find the tag
+ goto Error;
}
- i = _cmsSearchTag(Icc, sig, FALSE);
- if (i >=0) {
-
- if (Icc -> TagPtrs[i] != NULL) {
-
- // Already exists. Free previous version
- if (Icc ->TagSaveAsRaw[i]) {
- _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
- }
- else {
- TypeHandler = Icc ->TagTypeHandlers[i];
-
- if (TypeHandler != NULL) {
-
- LocalTypeHandler = *TypeHandler;
- LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter
- LocalTypeHandler.ICCVersion = Icc ->Version;
- LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]);
- }
- }
- }
- }
- else {
- // New one
- i = Icc -> TagCount;
-
- if (i >= MAX_TABLE_TAG) {
- cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG);
- return FALSE;
- }
-
- Icc -> TagCount++;
- }
+ if (!_cmsNewTag(Icc, sig, &i)) goto Error;
// This is not raw
Icc ->TagSaveAsRaw[i] = FALSE;
@@ -1560,10 +1593,10 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
Icc ->TagLinked[i] = (cmsTagSignature) 0;
// Get information about the TAG.
- TagDescriptor = _cmsGetTagDescriptor(sig);
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig);
if (TagDescriptor == NULL){
cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig);
- return FALSE;
+ goto Error;
}
@@ -1581,7 +1614,6 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
}
else {
-
Type = TagDescriptor ->SupportedTypes[0];
}
@@ -1592,18 +1624,18 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
_cmsTagSignature2String(SigString, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString);
- return FALSE;
+ goto Error;
}
// Does we have a handler for this type?
- TypeHandler = _cmsGetTagTypeHandler(Type);
+ TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type);
if (TypeHandler == NULL) {
_cmsTagSignature2String(TypeString, (cmsTagSignature) Type);
_cmsTagSignature2String(SigString, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString);
- return FALSE; // Should never happen
+ goto Error; // Should never happen
}
@@ -1616,7 +1648,7 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
LocalTypeHandler = *TypeHandler;
LocalTypeHandler.ContextID = Icc ->ContextID;
LocalTypeHandler.ICCVersion = Icc ->Version;
- Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
+ Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount);
if (Icc ->TagPtrs[i] == NULL) {
@@ -1624,10 +1656,16 @@ cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const v
_cmsTagSignature2String(SigString, sig);
cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%s' for tag '%s'", TypeString, SigString);
- return FALSE;
+ goto Error;
}
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TRUE;
+
+Error:
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return FALSE;
+
}
// Read and write raw data. The only way those function would work and keep consistence with normal read and write
@@ -1648,9 +1686,11 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
cmsUInt32Number rc;
cmsUInt32Number Offset, TagSize;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
+
// Search for given tag in ICC profile directory
i = _cmsSearchTag(Icc, sig, TRUE);
- if (i < 0) return 0; // Not found, return 0
+ if (i < 0) goto Error; // Not found,
// It is already read?
if (Icc -> TagPtrs[i] == NULL) {
@@ -1665,12 +1705,13 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
if (BufferSize < TagSize)
TagSize = BufferSize;
- if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0;
- if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0;
+ if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) goto Error;
+ if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) goto Error;
return TagSize;
}
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc ->TagSizes[i];
}
@@ -1686,16 +1727,18 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
memmove(data, Icc ->TagPtrs[i], TagSize);
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TagSize;
}
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return Icc ->TagSizes[i];
}
// Already readed, or previously set by cmsWriteTag(). We need to serialize that
// data to raw in order to maintain consistency.
Object = cmsReadTag(hProfile, sig);
- if (Object == NULL) return 0;
+ if (Object == NULL) goto Error;
// Now we need to serialize to a memory block: just use a memory iohandler
@@ -1704,17 +1747,18 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
} else{
MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
}
- if (MemIO == NULL) return 0;
+ if (MemIO == NULL) goto Error;
// Obtain type handling for the tag
TypeHandler = Icc ->TagTypeHandlers[i];
- TagDescriptor = _cmsGetTagDescriptor(sig);
+ TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig);
if (TagDescriptor == NULL) {
cmsCloseIOhandler(MemIO);
- return 0;
+ goto Error;
}
+
+ if (TypeHandler == NULL) goto Error;
- // FIXME: No handling for TypeHandler == NULL here?
// Serialize
LocalTypeHandler = *TypeHandler;
LocalTypeHandler.ContextID = Icc ->ContextID;
@@ -1722,19 +1766,24 @@ cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig
if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
cmsCloseIOhandler(MemIO);
- return 0;
+ goto Error;
}
if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) {
cmsCloseIOhandler(MemIO);
- return 0;
+ goto Error;
}
// Get Size and close
rc = MemIO ->Tell(MemIO);
cmsCloseIOhandler(MemIO); // Ignore return code this time
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return rc;
+
+Error:
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return 0;
}
// Similar to the anterior. This function allows to write directly to the ICC profile any data, without
@@ -1746,7 +1795,12 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
int i;
- if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0;
+
+ if (!_cmsNewTag(Icc, sig, &i)) {
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return FALSE;
+ }
// Mark the tag as being written as RAW
Icc ->TagSaveAsRaw[i] = TRUE;
@@ -1757,6 +1811,7 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons
Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size);
Icc ->TagSizes[i] = Size;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TRUE;
}
@@ -1766,7 +1821,12 @@ cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSi
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
int i;
- if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
+ if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE;
+
+ if (!_cmsNewTag(Icc, sig, &i)) {
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
+ return FALSE;
+ }
// Keep necessary information
Icc ->TagSaveAsRaw[i] = FALSE;
@@ -1777,6 +1837,7 @@ cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSi
Icc ->TagSizes[i] = 0;
Icc ->TagOffsets[i] = 0;
+ _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
return TRUE;
}
diff --git a/src/cmsio1.c b/src/cmsio1.c
index 3262402..89856e5 100644
--- a/src/cmsio1.c
+++ b/src/cmsio1.c
@@ -528,7 +528,7 @@ void ChangeInterpolationToTrilinear(cmsPipeline* Lut)
_cmsStageCLutData* CLUT = (_cmsStageCLutData*) Stage ->Data;
CLUT ->Params->dwFlags |= CMS_LERP_FLAGS_TRILINEAR;
- _cmsSetInterpolationRoutine(CLUT ->Params);
+ _cmsSetInterpolationRoutine(Lut->ContextID, CLUT ->Params);
}
}
}
diff --git a/src/cmsopt.c b/src/cmsopt.c
index 4bdf0a7..bf95091 100644
--- a/src/cmsopt.c
+++ b/src/cmsopt.c
@@ -512,8 +512,14 @@ cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColor
for (i=0; i < nOuts; i++) {
cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]);
- WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]);
- cmsFreeToneCurve(InversePostLin);
+ if (InversePostLin == NULL) {
+ WhiteOut[i] = WhitePointOut[i];
+
+ } else {
+
+ WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]);
+ cmsFreeToneCurve(InversePostLin);
+ }
}
}
else {
@@ -1633,44 +1639,102 @@ static _cmsOptimizationCollection DefaultOptimization[] = {
};
// The linked list head
-static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization;
+_cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginOptimizationList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsOptimizationPluginChunkType newHead = { NULL };
+ _cmsOptimizationCollection* entry;
+ _cmsOptimizationCollection* Anterior = NULL;
+ _cmsOptimizationPluginChunkType* head = (_cmsOptimizationPluginChunkType*) src->chunks[OptimizationPlugin];
+
+ _cmsAssert(ctx != NULL);
+ _cmsAssert(head != NULL);
+
+ // Walk the list copying all nodes
+ for (entry = head->OptimizationCollection;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsOptimizationCollection *newEntry = ( _cmsOptimizationCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsOptimizationCollection));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.OptimizationCollection == NULL)
+ newHead.OptimizationCollection = newEntry;
+ }
+
+ ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsOptimizationPluginChunkType));
+}
+
+void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginOptimizationList(ctx, src);
+ }
+ else {
+ static _cmsOptimizationPluginChunkType OptimizationPluginChunkType = { NULL };
+ ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx ->MemPool, &OptimizationPluginChunkType, sizeof(_cmsOptimizationPluginChunkType));
+ }
+}
+
// Register new ways to optimize
-cmsBool _cmsRegisterOptimizationPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
+ _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
_cmsOptimizationCollection* fl;
if (Data == NULL) {
- OptimizationCollection = DefaultOptimization;
+ ctx->OptimizationCollection = NULL;
return TRUE;
}
// Optimizer callback is required
if (Plugin ->OptimizePtr == NULL) return FALSE;
- fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(id, sizeof(_cmsOptimizationCollection));
+ fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsOptimizationCollection));
if (fl == NULL) return FALSE;
// Copy the parameters
fl ->OptimizePtr = Plugin ->OptimizePtr;
// Keep linked list
- fl ->Next = OptimizationCollection;
- OptimizationCollection = fl;
+ fl ->Next = ctx->OptimizationCollection;
+
+ // Set the head
+ ctx ->OptimizationCollection = fl;
// All is ok
return TRUE;
}
// The entry point for LUT optimization
-cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut,
+cmsBool _cmsOptimizePipeline(cmsContext ContextID,
+ cmsPipeline** PtrLut,
int Intent,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags)
{
+ _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
_cmsOptimizationCollection* Opts;
cmsBool AnySuccess = FALSE;
@@ -1700,8 +1764,8 @@ cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut,
if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
return FALSE;
- // Try built-in optimizations and plug-in
- for (Opts = OptimizationCollection;
+ // Try plug-in optimizations
+ for (Opts = ctx->OptimizationCollection;
Opts != NULL;
Opts = Opts ->Next) {
@@ -1712,6 +1776,17 @@ cmsBool _cmsOptimizePipeline(cmsPipeline** PtrLut,
}
}
+ // Try built-in optimizations
+ for (Opts = DefaultOptimization;
+ Opts != NULL;
+ Opts = Opts ->Next) {
+
+ if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) {
+
+ return TRUE;
+ }
+ }
+
// Only simple optimizations succeeded
return AnySuccess;
}
diff --git a/src/cmspack.c b/src/cmspack.c
index 6509e89..c84fd82 100644
--- a/src/cmspack.c
+++ b/src/cmspack.c
@@ -2352,9 +2352,9 @@ cmsUInt8Number* PackXYZFloatFrom16(register _cmsTRANSFORM* Info,
cmsFloat32Number* Out = (cmsFloat32Number*) output;
cmsXYZEncoded2Float(&XYZ, wOut);
- Out[0] = XYZ.X;
- Out[Stride] = XYZ.Y;
- Out[Stride*2] = XYZ.Z;
+ Out[0] = (cmsFloat32Number) XYZ.X;
+ Out[Stride] = (cmsFloat32Number) XYZ.Y;
+ Out[Stride*2] = (cmsFloat32Number) XYZ.Z;
return output + sizeof(cmsFloat32Number);
@@ -2365,9 +2365,9 @@ cmsUInt8Number* PackXYZFloatFrom16(register _cmsTRANSFORM* Info,
cmsFloat32Number* Out = (cmsFloat32Number*) output;
cmsXYZEncoded2Float(&XYZ, wOut);
- Out[0] = XYZ.X;
- Out[1] = XYZ.Y;
- Out[2] = XYZ.Z;
+ Out[0] = (cmsFloat32Number) XYZ.X;
+ Out[1] = (cmsFloat32Number) XYZ.Y;
+ Out[2] = (cmsFloat32Number) XYZ.Z;
return output + (3 * sizeof(cmsFloat32Number) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
}
@@ -3224,40 +3224,98 @@ typedef struct _cms_formatters_factory_list {
} cmsFormattersFactoryList;
-static cmsFormattersFactoryList* FactoryList = NULL;
+_cmsFormattersPluginChunkType _cmsFormattersPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupFormatterFactoryList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsFormattersPluginChunkType newHead = { NULL };
+ cmsFormattersFactoryList* entry;
+ cmsFormattersFactoryList* Anterior = NULL;
+ _cmsFormattersPluginChunkType* head = (_cmsFormattersPluginChunkType*) src->chunks[FormattersPlugin];
+
+ _cmsAssert(head != NULL);
+
+ // Walk the list copying all nodes
+ for (entry = head->FactoryList;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ cmsFormattersFactoryList *newEntry = ( cmsFormattersFactoryList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(cmsFormattersFactoryList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.FactoryList == NULL)
+ newHead.FactoryList = newEntry;
+ }
+
+ ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsFormattersPluginChunkType));
+}
+
+// The interpolation plug-in memory chunk allocator/dup
+void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsAssert(ctx != NULL);
+
+ if (src != NULL) {
+
+ // Duplicate the LIST
+ DupFormatterFactoryList(ctx, src);
+ }
+ else {
+ static _cmsFormattersPluginChunkType FormattersPluginChunk = { NULL };
+ ctx ->chunks[FormattersPlugin] = _cmsSubAllocDup(ctx ->MemPool, &FormattersPluginChunk, sizeof(_cmsFormattersPluginChunkType));
+ }
+}
+
// Formatters management
-cmsBool _cmsRegisterFormattersPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterFormattersPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
+ _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
cmsFormattersFactoryList* fl ;
- // Reset
+ // Reset to built-in defaults
if (Data == NULL) {
- FactoryList = NULL;
+ ctx ->FactoryList = NULL;
return TRUE;
}
- fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(id, sizeof(cmsFormattersFactoryList));
+ fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(ContextID, sizeof(cmsFormattersFactoryList));
if (fl == NULL) return FALSE;
fl ->Factory = Plugin ->FormattersFactory;
- fl ->Next = FactoryList;
- FactoryList = fl;
+ fl ->Next = ctx -> FactoryList;
+ ctx ->FactoryList = fl;
return TRUE;
}
-cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
+cmsFormatter _cmsGetFormatter(cmsContext ContextID,
+ cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
cmsFormatterDirection Dir,
cmsUInt32Number dwFlags)
{
+ _cmsFormattersPluginChunkType* ctx = ( _cmsFormattersPluginChunkType*) _cmsContextGetClientChunk(ContextID, FormattersPlugin);
cmsFormattersFactoryList* f;
- for (f = FactoryList; f != NULL; f = f ->Next) {
+ for (f =ctx->FactoryList; f != NULL; f = f ->Next) {
cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);
if (fn.Fmt16 != NULL) return fn;
diff --git a/src/cmsplugin.c b/src/cmsplugin.c
index e334fac..7c58b60 100644
--- a/src/cmsplugin.c
+++ b/src/cmsplugin.c
@@ -515,15 +515,18 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
// Plugin memory management -------------------------------------------------------------------------------------------------
-static _cmsSubAllocator* PluginPool = NULL;
-
// Specialized malloc for plug-ins, that is freed upon exit.
-void* _cmsPluginMalloc(cmsContext id, cmsUInt32Number size)
+void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size)
{
- if (PluginPool == NULL)
- PluginPool = _cmsCreateSubAlloc(id, 4*1024);
+ struct _cmsContext_struct* ctx = _cmsGetContext(ContextID);
+
+ if (ctx ->MemPool == NULL) {
+
+ cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context");
+ return NULL;
+ }
- return _cmsSubAlloc(PluginPool, size);
+ return _cmsSubAlloc(ctx->MemPool, size);
}
@@ -542,12 +545,12 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
Plugin = Plugin -> Next) {
if (Plugin -> Magic != cmsPluginMagicNumber) {
- cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
+ cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
return FALSE;
}
if (Plugin ->ExpectedVersion > LCMS_VERSION) {
- cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
+ cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
Plugin ->ExpectedVersion, LCMS_VERSION);
return FALSE;
}
@@ -555,11 +558,11 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
switch (Plugin -> Type) {
case cmsPluginMemHandlerSig:
- if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginInterpolationSig:
- if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE;
+ if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE;
break;
case cmsPluginTagTypeSig:
@@ -594,8 +597,12 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
break;
+ case cmsPluginMutexSig:
+ if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE;
+ break;
+
default:
- cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
+ cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
return FALSE;
}
}
@@ -608,19 +615,322 @@ cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
// Revert all plug-ins to default
void CMSEXPORT cmsUnregisterPlugins(void)
{
- _cmsRegisterMemHandlerPlugin(NULL);
- _cmsRegisterInterpPlugin(NULL);
- _cmsRegisterTagTypePlugin(NULL, NULL);
- _cmsRegisterTagPlugin(NULL, NULL);
- _cmsRegisterFormattersPlugin(NULL, NULL);
- _cmsRegisterRenderingIntentPlugin(NULL, NULL);
- _cmsRegisterParametricCurvesPlugin(NULL, NULL);
- _cmsRegisterMultiProcessElementPlugin(NULL, NULL);
- _cmsRegisterOptimizationPlugin(NULL, NULL);
- _cmsRegisterTransformPlugin(NULL, NULL);
+ cmsUnregisterPluginsTHR(NULL);
+}
+
+
+// The Global storage for system context. This is the one and only global variable
+// pointers structure. All global vars are referenced here.
+static struct _cmsContext_struct globalContext = {
+
+ cmsContextMagicNumber,
+ NULL, // No suballocator
+ {
+ NULL, // UserPtr,
+ &_cmsLogErrorChunk, // Logger,
+ &_cmsAlarmCodesChunk, // AlarmCodes,
+ &_cmsAdaptationStateChunk, // AdaptationState,
+ &_cmsMemPluginChunk, // MemPlugin,
+ &_cmsInterpPluginChunk, // InterpPlugin,
+ &_cmsCurvesPluginChunk, // CurvesPlugin,
+ &_cmsFormattersPluginChunk, // FormattersPlugin,
+ &_cmsTagTypePluginChunk, // TagTypePlugin,
+ &_cmsTagPluginChunk, // TagPlugin,
+ &_cmsIntentsPluginChunk, // IntentPlugin,
+ &_cmsMPETypePluginChunk, // MPEPlugin,
+ &_cmsOptimizationPluginChunk, // OptimizationPlugin,
+ &_cmsTransformPluginChunk, // TransformPlugin,
+ &_cmsMutexPluginChunk // MutexPlugin
+ },
+
+ { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
+};
+
+
+// This is a replacement for (intptr_t), which despite C99, is not supported by some compilers.
+// Clever idea from Robin, to use pointer substraction.
+#define PTR_TO_INT(ptr) (((cmsUInt8Number*) (ptr)) - (cmsUInt8Number*) 0)
+
+// Internal, get associated pointer, with guessing. Never returns NULL.
+struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
+{
+#ifdef CMS_CONTEXT_IN_LEGACY_MODE
+
+ return &globalContext;
+ cmsUNUSED_PARAMETER(ContextID);
+#else
+ struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
+
+ // Check for low numbers. Yes, I know, it is a hack... but it works
+ if ((PTR_TO_INT(ContextID) < 0x1000) && (PTR_TO_INT(ContextID) > 0))
+ return &globalContext;
+
+ // On 0, use global settings
+ if (ctx == NULL)
+ return &globalContext;
+
+ // Validate across magic number
+ if (ctx ->Magic != cmsContextMagicNumber)
+ return &globalContext;
+
+ // New-style context,
+ return ctx;
+#endif
+}
+
+
+// Internal: get the memory area associanted with each context client
+// Returns the block assigned to the specific zone.
+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;
+ }
+
+ ctx = _cmsGetContext(ContextID);
+ ptr = ctx ->chunks[mc];
- if (PluginPool != NULL)
- _cmsSubAllocDestroy(PluginPool);
+ if (ptr != NULL)
+ return ptr;
- PluginPool = NULL;
+ // A null ptr means no special settings for that context, and this
+ // reverts to Context0 globals
+ return globalContext.chunks[mc];
}
+
+
+// This function returns the given context its default pristine state,
+// as no plug-ins were declared. There is no way to unregister a single
+// plug-in, as a single call to cmsPluginTHR() function may register
+// many different plug-ins simultaneously, then there is no way to
+// identify which plug-in to unregister.
+void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)
+{
+ _cmsRegisterMemHandlerPlugin(ContextID, NULL);
+ _cmsRegisterInterpPlugin(ContextID, NULL);
+ _cmsRegisterTagTypePlugin(ContextID, NULL);
+ _cmsRegisterTagPlugin(ContextID, NULL);
+ _cmsRegisterFormattersPlugin(ContextID, NULL);
+ _cmsRegisterRenderingIntentPlugin(ContextID, NULL);
+ _cmsRegisterParametricCurvesPlugin(ContextID, NULL);
+ _cmsRegisterMultiProcessElementPlugin(ContextID, NULL);
+ _cmsRegisterOptimizationPlugin(ContextID, NULL);
+ _cmsRegisterTransformPlugin(ContextID, NULL);
+ _cmsRegisterMutexPlugin(ContextID, NULL);
+}
+
+
+// Returns the memory manager plug-in, if any, from the Plug-in bundle
+static
+cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle)
+{
+ cmsPluginBase* Plugin;
+
+ for (Plugin = (cmsPluginBase*) PluginBundle;
+ Plugin != NULL;
+ Plugin = Plugin -> Next) {
+
+ if (Plugin -> Magic == cmsPluginMagicNumber &&
+ Plugin -> ExpectedVersion <= LCMS_VERSION &&
+ Plugin -> Type == cmsPluginMemHandlerSig) {
+
+ // Found!
+ return (cmsPluginMemHandler*) Plugin;
+ }
+ }
+
+ // Nope, revert to defaults
+ return NULL;
+}
+
+
+// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined
+// data that will be forwarded to plug-ins and logger.
+cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
+{
+#ifdef CMS_CONTEXT_IN_LEGACY_MODE
+ cmsSignalError(0, cmsERROR_NOT_SUITABLE, "Lcms is compiled as legacy context mode and you called an advanced context function");
+ return UserData;
+
+ cmsUNUSED_PARAMETER(Plugin);
+ cmsUNUSED_PARAMETER(UserData);
+#else
+
+
+ struct _cmsContext_struct* ctx;
+ struct _cmsContext_struct fakeContext;
+
+ _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
+
+ fakeContext.chunks[UserPtr] = UserData;
+ fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
+
+ // Create the context structure.
+ ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));
+ if (ctx == NULL)
+ return NULL; // Something very wrong happened!
+
+ // Init the structure and the memory manager
+ memset(ctx, 0, sizeof(struct _cmsContext_struct));
+
+ // Keep memory manager
+ memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));
+
+ // Identify it as a context
+ ctx ->Magic = cmsContextMagicNumber;
+
+ ctx ->chunks[UserPtr] = UserData;
+ ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
+
+ // Now we can allocate the pool by using default memory manager
+ ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers
+ if (ctx ->MemPool == NULL) {
+
+ cmsDeleteContext(ctx);
+ return NULL;
+ }
+
+ _cmsAllocLogErrorChunk(ctx, NULL);
+ _cmsAllocAlarmCodesChunk(ctx, NULL);
+ _cmsAllocAdaptationStateChunk(ctx, NULL);
+ _cmsAllocMemPluginChunk(ctx, NULL);
+ _cmsAllocInterpPluginChunk(ctx, NULL);
+ _cmsAllocCurvesPluginChunk(ctx, NULL);
+ _cmsAllocFormattersPluginChunk(ctx, NULL);
+ _cmsAllocTagTypePluginChunk(ctx, NULL);
+ _cmsAllocMPETypePluginChunk(ctx, NULL);
+ _cmsAllocTagPluginChunk(ctx, NULL);
+ _cmsAllocIntentsPluginChunk(ctx, NULL);
+ _cmsAllocOptimizationPluginChunk(ctx, NULL);
+ _cmsAllocTransformPluginChunk(ctx, NULL);
+ _cmsAllocMutexPluginChunk(ctx, NULL);
+
+ // Setup the plug-ins
+ if (!cmsPluginTHR(ctx, Plugin)) {
+
+ cmsDeleteContext(ctx);
+ return NULL;
+ }
+
+ return (cmsContext) ctx;
+#endif
+}
+
+// Duplicates a context with all associated plug-ins.
+// Caller may specify an optional pointer to user-defined
+// data that will be forwarded to plug-ins and logger.
+cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
+{
+#ifdef CMS_CONTEXT_IN_LEGACY_MODE
+ cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Lcms is compiled as legacy context mode and you called an advanced context function");
+ return ContextID;
+ cmsUNUSED_PARAMETER(NewUserData);
+
+#else
+ int i;
+ struct _cmsContext_struct* ctx;
+ const struct _cmsContext_struct* src = _cmsGetContext(ContextID);
+
+ void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr];
+
+
+ ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct));
+ if (ctx == NULL)
+ return NULL; // Something very wrong happened
+
+ // Setup default memory allocators
+ memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+
+ ctx ->Magic = cmsContextMagicNumber;
+
+ ctx ->chunks[UserPtr] = userData;
+ ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
+
+ ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));
+ if (ctx ->MemPool == NULL) {
+
+ cmsDeleteContext(ctx);
+ return NULL;
+ }
+
+ // Allocate all required chunks.
+ _cmsAllocLogErrorChunk(ctx, src);
+ _cmsAllocAlarmCodesChunk(ctx, src);
+ _cmsAllocAdaptationStateChunk(ctx, src);
+ _cmsAllocMemPluginChunk(ctx, src);
+ _cmsAllocInterpPluginChunk(ctx, src);
+ _cmsAllocCurvesPluginChunk(ctx, src);
+ _cmsAllocFormattersPluginChunk(ctx, src);
+ _cmsAllocTagTypePluginChunk(ctx, src);
+ _cmsAllocMPETypePluginChunk(ctx, src);
+ _cmsAllocTagPluginChunk(ctx, src);
+ _cmsAllocIntentsPluginChunk(ctx, src);
+ _cmsAllocOptimizationPluginChunk(ctx, src);
+ _cmsAllocTransformPluginChunk(ctx, src);
+ _cmsAllocMutexPluginChunk(ctx, src);
+
+ // Make sure no one failed
+ for (i=Logger; i < MemoryClientMax; i++) {
+
+ if (src ->chunks[i] == NULL) {
+ cmsDeleteContext((cmsContext) ctx);
+ return NULL;
+ }
+ }
+
+ return (cmsContext) ctx;
+#endif
+
+}
+
+// Frees any resources associated with the given context,
+// and destroys the context placeholder.
+// The ContextID can no longer be used in any THR operation.
+void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
+{
+#ifdef CMS_CONTEXT_IN_LEGACY_MODE
+ cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Lcms is compiled as legacy context mode and you called an advanced context function");
+ cmsUNUSED_PARAMETER(ContextID);
+#else
+
+ if (ContextID != NULL) {
+
+ struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
+ struct _cmsContext_struct fakeContext;
+
+ memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+
+ fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
+ fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
+
+
+ // Get rid of plugins
+ cmsUnregisterPluginsTHR(ContextID);
+
+ // Since all memory is allocated in the private pool, all what we need to do is destroy the pool
+ if (ctx -> MemPool != NULL)
+ _cmsSubAllocDestroy(ctx ->MemPool);
+ ctx -> MemPool = NULL;
+
+ // free the memory block itself
+ _cmsFree(&fakeContext, ctx);
+ }
+#endif
+}
+
+// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation
+void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID)
+{
+#ifdef CMS_CONTEXT_IN_LEGACY_MODE
+ cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Lcms is compiled as legacy context mode and you called an advanced context function");
+ return ContextID;
+#else
+ return _cmsContextGetClientChunk(ContextID, UserPtr);
+#endif
+}
+
+
diff --git a/src/cmsps2.c b/src/cmsps2.c
index fe91500..224b44b 100644
--- a/src/cmsps2.c
+++ b/src/cmsps2.c
@@ -913,7 +913,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Nu
if (DeviceLink == NULL) return 0;
dwFlags |= cmsFLAGS_FORCE_CLUT;
- _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
+ _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
cmsPipelineFree(DeviceLink);
@@ -1330,7 +1330,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32N
// We need a CLUT
dwFlags |= cmsFLAGS_FORCE_CLUT;
- _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
+ _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
_cmsIOPrintf(m, "<<\n");
_cmsIOPrintf(m, "/ColorRenderingType 1\n");
diff --git a/src/cmstypes.c b/src/cmstypes.c
index 9114a6e..a9e3fa0 100644
--- a/src/cmstypes.c
+++ b/src/cmstypes.c
@@ -60,54 +60,49 @@ typedef struct _cmsTagTypeLinkedList_st {
// Helper macro to define a MPE handler. Callbacks do have a fixed naming convention
#define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 }
-// Register a new type handler. This routine is shared between normal types and MPE
+// Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head
static
-cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
+cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos)
{
cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
- _cmsTagTypeLinkedList *pt, *Anterior = NULL;
+ _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos);
+ _cmsTagTypeLinkedList *pt;
// Calling the function with NULL as plug-in would unregister the plug in.
if (Data == NULL) {
- LinkedList[DefaultListCount-1].Next = NULL;
+ // There is no need to set free the memory, as pool is destroyed as a whole.
+ ctx ->TagTypes = NULL;
return TRUE;
}
- pt = Anterior = LinkedList;
- while (pt != NULL) {
-
- if (Plugin->Handler.Signature == pt -> Handler.Signature) {
- pt ->Handler = Plugin ->Handler; // Replace old behaviour.
- // Note that since no memory is allocated, unregister does not
- // reset this action.
- return TRUE;
- }
-
- Anterior = pt;
- pt = pt ->Next;
- }
-
- // Registering happens in plug-in memory pool
+ // Registering happens in plug-in memory pool.
pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
if (pt == NULL) return FALSE;
pt ->Handler = Plugin ->Handler;
- pt ->Next = NULL;
-
- if (Anterior)
- Anterior -> Next = pt;
+ pt ->Next = ctx ->TagTypes;
+ ctx ->TagTypes = pt;
+
return TRUE;
}
-// Return handler for a given type or NULL if not found. Shared between normal types and MPE
+// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons
+// made by plug-ins and then the built-in defaults.
static
-cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* LinkedList)
+cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList)
{
_cmsTagTypeLinkedList* pt;
- for (pt = LinkedList;
+ for (pt = PluginLinkedList;
+ pt != NULL;
+ pt = pt ->Next) {
+
+ if (sig == pt -> Handler.Signature) return &pt ->Handler;
+ }
+
+ for (pt = DefaultLinkedList;
pt != NULL;
pt = pt ->Next) {
@@ -134,6 +129,7 @@ cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t*
return TRUE;
}
+// Auxiliar to read an array of wchar_t
static
cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
{
@@ -748,6 +744,8 @@ cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
// Create memory
Text = (char*) _cmsMalloc(self ->ContextID, size);
+ if (Text == NULL) return FALSE;
+
cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);
// Write it, including separator
@@ -4355,7 +4353,7 @@ static _cmsTagTypeLinkedList SupportedMPEtypes[] = {
{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType, MPEclut), NULL },
};
-#define DEFAULT_MPE_TYPE_COUNT (sizeof(SupportedMPEtypes) / sizeof(_cmsTagTypeLinkedList))
+_cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL };
static
cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
@@ -4368,6 +4366,8 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
cmsTagTypeHandler* TypeHandler;
cmsUInt32Number nItems;
cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
+ _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
+
// Take signature and channels for each element.
if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE;
@@ -4376,7 +4376,7 @@ cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
if (!_cmsReadUInt32Number(io, NULL)) return FALSE;
// Read diverse MPE types
- TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes);
+ TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes);
if (TypeHandler == NULL) {
char String[5];
@@ -4453,6 +4453,7 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v
cmsPipeline* Lut = (cmsPipeline*) Ptr;
cmsStage* Elem = Lut ->Elements;
cmsTagTypeHandler* TypeHandler;
+ _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
@@ -4486,7 +4487,7 @@ cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, v
ElementSig = Elem ->Type;
- TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes);
+ TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes);
if (TypeHandler == NULL) {
char String[5];
@@ -5263,24 +5264,95 @@ static _cmsTagTypeLinkedList SupportedTagTypes[] = {
{TYPE_HANDLER(cmsSigVcgtType, vcgt), NULL }
};
-#define DEFAULT_TAG_TYPE_COUNT (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList))
+
+_cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL };
+
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupTagTypeList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src,
+ int loc)
+{
+ _cmsTagTypePluginChunkType newHead = { NULL };
+ _cmsTagTypeLinkedList* entry;
+ _cmsTagTypeLinkedList* Anterior = NULL;
+ _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc];
+
+ // Walk the list copying all nodes
+ for (entry = head->TagTypes;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.TagTypes == NULL)
+ newHead.TagTypes = newEntry;
+ }
+
+ ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType));
+}
+
+
+void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Duplicate the LIST
+ DupTagTypeList(ctx, src, TagTypePlugin);
+ }
+ else {
+ static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
+ ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
+ }
+}
+
+void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Duplicate the LIST
+ DupTagTypeList(ctx, src, MPEPlugin);
+ }
+ else {
+ static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
+ ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
+ }
+
+}
+
// Both kind of plug-ins share same structure
cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data)
{
- return RegisterTypesPlugin(id, Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
+ return RegisterTypesPlugin(id, Data, TagTypePlugin);
}
cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data)
{
- return RegisterTypesPlugin(id, Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
+ return RegisterTypesPlugin(id, Data,MPEPlugin);
}
// Wrapper for tag types
-cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig)
+cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig)
{
- return GetHandler(sig, SupportedTagTypes);
+ _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin);
+
+ return GetHandler(sig, ctx->TagTypes, SupportedTagTypes);
}
// ********************************************************************************
@@ -5395,30 +5467,68 @@ static _cmsTagLinkedList SupportedTags[] = {
cmsSigDeviceSettingsTag ==> Deprecated, useless
*/
-#define DEFAULT_TAG_COUNT (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList))
-cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
+_cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupTagList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
{
- cmsPluginTag* Plugin = (cmsPluginTag*) Data;
- _cmsTagLinkedList *pt, *Anterior;
+ _cmsTagPluginChunkType newHead = { NULL };
+ _cmsTagLinkedList* entry;
+ _cmsTagLinkedList* Anterior = NULL;
+ _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin];
+ // Walk the list copying all nodes
+ for (entry = head->Tag;
+ entry != NULL;
+ entry = entry ->Next) {
- if (Data == NULL) {
+ _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList));
- SupportedTags[DEFAULT_TAG_COUNT-1].Next = NULL;
- return TRUE;
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.Tag == NULL)
+ newHead.Tag = newEntry;
+ }
+
+ ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType));
+}
+
+void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ DupTagList(ctx, src);
+ }
+ else {
+ static _cmsTagPluginChunkType TagPluginChunk = { NULL };
+ ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagPluginChunk, sizeof(_cmsTagPluginChunkType));
}
- pt = Anterior = SupportedTags;
- while (pt != NULL) {
+}
- if (Plugin->Signature == pt -> Signature) {
- pt ->Descriptor = Plugin ->Descriptor; // Replace old behaviour
- return TRUE;
- }
+cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
+{
+ cmsPluginTag* Plugin = (cmsPluginTag*) Data;
+ _cmsTagLinkedList *pt;
+ _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(id, TagPlugin);
+
+ if (Data == NULL) {
- Anterior = pt;
- pt = pt ->Next;
+ TagPluginChunk->Tag = NULL;
+ return TRUE;
}
pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList));
@@ -5426,17 +5536,25 @@ cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
pt ->Signature = Plugin ->Signature;
pt ->Descriptor = Plugin ->Descriptor;
- pt ->Next = NULL;
-
- if (Anterior != NULL) Anterior -> Next = pt;
+ pt ->Next = TagPluginChunk ->Tag;
+ TagPluginChunk ->Tag = pt;
+
return TRUE;
}
// Return a descriptor for a given tag or NULL
-cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig)
+cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig)
{
_cmsTagLinkedList* pt;
+ _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(ContextID, TagPlugin);
+
+ for (pt = TagPluginChunk->Tag;
+ pt != NULL;
+ pt = pt ->Next) {
+
+ if (sig == pt -> Signature) return &pt ->Descriptor;
+ }
for (pt = SupportedTags;
pt != NULL;
diff --git a/src/cmsvirt.c b/src/cmsvirt.c
index 953377a..deeb7a6 100644
--- a/src/cmsvirt.c
+++ b/src/cmsvirt.c
@@ -990,7 +990,7 @@ typedef struct {
static const cmsAllowedLUT AllowedLUTTypes[] = {
- { FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
+ { 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 }},
@@ -1121,7 +1121,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
if (AllowedLUT == NULL) {
// Try to optimize
- _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
+ _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
AllowedLUT = FindCombination(LUT, Version >= 4.0, DestinationTag);
}
@@ -1130,7 +1130,7 @@ cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat
if (AllowedLUT == NULL) {
dwFlags |= cmsFLAGS_FORCE_CLUT;
- _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
+ _cmsOptimizePipeline(ContextID, &LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
// Put identity curves if needed
if (cmsPipelineGetPtrToFirstStage(LUT) ->Type != cmsSigCurveSetElemType)
diff --git a/src/cmsxform.c b/src/cmsxform.c
index b39c116..b2705cb 100644
--- a/src/cmsxform.c
+++ b/src/cmsxform.c
@@ -29,44 +29,120 @@
// Transformations stuff
// -----------------------------------------------------------------------
-// Alarm codes for 16-bit transformations, because the fixed range of containers there are
-// no values left to mark out of gamut. volatile is C99 per 6.2.5
-static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS] = { 0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static volatile cmsFloat64Number GlobalAdaptationState = 1;
+#define DEFAULT_OBSERVER_ADAPTATION_STATE 1.0
+
+// The Context0 observer adaptation state.
+_cmsAdaptationStateChunkType _cmsAdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
+
+// Init and duplicate observer adaptation state
+void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsAdaptationStateChunkType AdaptationStateChunk = { DEFAULT_OBSERVER_ADAPTATION_STATE };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[AdaptationStateContext];
+ }
+ else {
+ from = &AdaptationStateChunk;
+ }
+
+ ctx ->chunks[AdaptationStateContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAdaptationStateChunkType));
+}
+
+
+// Sets adaptation state for absolute colorimetric intent in the given context. Adaptation state applies on all
+// but cmsCreateExtendedTransformTHR(). Little CMS can handle incomplete adaptation states.
+cmsFloat64Number CMSEXPORT cmsSetAdaptationStateTHR(cmsContext ContextID, cmsFloat64Number d)
+{
+ cmsFloat64Number prev;
+ _cmsAdaptationStateChunkType* ptr = (_cmsAdaptationStateChunkType*) _cmsContextGetClientChunk(ContextID, AdaptationStateContext);
+
+ // Get previous value for return
+ prev = ptr ->AdaptationState;
+
+ // Set the value if d is positive or zero
+ if (d >= 0.0) {
+
+ ptr ->AdaptationState = d;
+ }
+
+ // Always return previous value
+ return prev;
+}
+
// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d)
-{
- cmsFloat64Number OldVal = GlobalAdaptationState;
+{
+ return cmsSetAdaptationStateTHR(NULL, d);
+}
+
+// -----------------------------------------------------------------------
+
+// Alarm codes for 16-bit transformations, because the fixed range of containers there are
+// no values left to mark out of gamut.
- if (d >= 0)
- GlobalAdaptationState = d;
+#define DEFAULT_ALARM_CODES_VALUE {0x7F00, 0x7F00, 0x7F00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
- return OldVal;
+_cmsAlarmCodesChunkType _cmsAlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
+
+// Sets the codes used to mark out-out-gamut on Proofing transforms for a given context. Values are meant to be
+// encoded in 16 bits.
+void CMSEXPORT cmsSetAlarmCodesTHR(cmsContext ContextID, const cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
+{
+ _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
+
+ _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
+
+ memcpy(ContextAlarmCodes->AlarmCodes, AlarmCodesP, sizeof(ContextAlarmCodes->AlarmCodes));
}
-// Alarm codes are always global
-void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS])
+// Gets the current codes used to mark out-out-gamut on Proofing transforms for the given context.
+// Values are meant to be encoded in 16 bits.
+void CMSEXPORT cmsGetAlarmCodesTHR(cmsContext ContextID, cmsUInt16Number AlarmCodesP[cmsMAXCHANNELS])
{
- int i;
+ _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(ContextID, AlarmCodesContext);
- _cmsAssert(NewAlarm != NULL);
+ _cmsAssert(ContextAlarmCodes != NULL); // Can't happen
- for (i=0; i < cmsMAXCHANNELS; i++)
- Alarm[i] = NewAlarm[i];
+ memcpy(AlarmCodesP, ContextAlarmCodes->AlarmCodes, sizeof(ContextAlarmCodes->AlarmCodes));
}
-// You can get the codes cas well
-void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS])
+void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS])
{
- int i;
+ _cmsAssert(NewAlarm != NULL);
+ cmsSetAlarmCodesTHR(NULL, NewAlarm);
+}
+
+void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS])
+{
_cmsAssert(OldAlarm != NULL);
+ cmsGetAlarmCodesTHR(NULL, OldAlarm);
+}
- for (i=0; i < cmsMAXCHANNELS; i++)
- OldAlarm[i] = Alarm[i];
+
+// Init and duplicate alarm codes
+void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ static _cmsAlarmCodesChunkType AlarmCodesChunk = { DEFAULT_ALARM_CODES_VALUE };
+ void* from;
+
+ if (src != NULL) {
+ from = src ->chunks[AlarmCodesContext];
+ }
+ else {
+ from = &AlarmCodesChunk;
+ }
+
+ ctx ->chunks[AlarmCodesContext] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsAlarmCodesChunkType));
}
+// -----------------------------------------------------------------------
+
// Get rid of transform resources
void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
{
@@ -173,6 +249,30 @@ void FloatXFORM(_cmsTRANSFORM* p,
}
}
+
+static
+void NullFloatXFORM(_cmsTRANSFORM* p,
+ const void* in,
+ void* out,
+ cmsUInt32Number Size,
+ cmsUInt32Number Stride)
+{
+ cmsUInt8Number* accum;
+ cmsUInt8Number* output;
+ cmsFloat32Number fIn[cmsMAXCHANNELS];
+ cmsUInt32Number i, n;
+
+ accum = (cmsUInt8Number*) in;
+ output = (cmsUInt8Number*) out;
+ n = Size;
+
+ for (i=0; i < n; i++) {
+
+ accum = p -> FromInputFloat(p, fIn, accum, Stride);
+ output = p -> ToOutputFloat(p, fIn, output, Stride);
+ }
+}
+
// 16 bit precision -----------------------------------------------------------------------------------------------------------
// Null transformation, only applies formatters. No caché
@@ -223,7 +323,7 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p,
}
-// Auxiliar: Handle precalculated gamut check
+// Auxiliar: Handle precalculated gamut check. The retrieval of context may be alittle bit slow, but this function is not critical.
static
void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
const cmsUInt16Number wIn[],
@@ -235,9 +335,12 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
if (wOutOfGamut >= 1) {
cmsUInt16Number i;
+ _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
+
+ for (i=0; i < p ->Lut->OutputChannels; i++) {
- for (i=0; i < p ->Lut->OutputChannels; i++)
- wOut[i] = Alarm[i];
+ wOut[i] = ContextAlarmCodes ->AlarmCodes[i];
+ }
}
else
p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
@@ -364,34 +467,86 @@ typedef struct _cmsTransformCollection_st {
} _cmsTransformCollection;
// The linked list head
-static _cmsTransformCollection* TransformCollection = NULL;
+_cmsTransformPluginChunkType _cmsTransformPluginChunk = { NULL };
+
+
+// Duplicates the zone of memory used by the plug-in in the new context
+static
+void DupPluginTransformList(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ _cmsTransformPluginChunkType newHead = { NULL };
+ _cmsTransformCollection* entry;
+ _cmsTransformCollection* Anterior = NULL;
+ _cmsTransformPluginChunkType* head = (_cmsTransformPluginChunkType*) src->chunks[TransformPlugin];
+
+ // Walk the list copying all nodes
+ for (entry = head->TransformCollection;
+ entry != NULL;
+ entry = entry ->Next) {
+
+ _cmsTransformCollection *newEntry = ( _cmsTransformCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTransformCollection));
+
+ if (newEntry == NULL)
+ return;
+
+ // We want to keep the linked list order, so this is a little bit tricky
+ newEntry -> Next = NULL;
+ if (Anterior)
+ Anterior -> Next = newEntry;
+
+ Anterior = newEntry;
+
+ if (newHead.TransformCollection == NULL)
+ newHead.TransformCollection = newEntry;
+ }
+
+ ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
+}
+
+void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src)
+{
+ if (src != NULL) {
+
+ // Copy all linked list
+ DupPluginTransformList(ctx, src);
+ }
+ else {
+ static _cmsTransformPluginChunkType TransformPluginChunkType = { NULL };
+ ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TransformPluginChunkType, sizeof(_cmsTransformPluginChunkType));
+ }
+}
+
+
// Register new ways to transform
-cmsBool _cmsRegisterTransformPlugin(cmsContext id, cmsPluginBase* Data)
+cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
cmsPluginTransform* Plugin = (cmsPluginTransform*) Data;
_cmsTransformCollection* fl;
+ _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID,TransformPlugin);
- if (Data == NULL) {
+ if (Data == NULL) {
// Free the chain. Memory is safely freed at exit
- TransformCollection = NULL;
+ ctx->TransformCollection = NULL;
return TRUE;
}
// Factory callback is required
- if (Plugin ->Factory == NULL) return FALSE;
+ if (Plugin ->Factory == NULL) return FALSE;
- fl = (_cmsTransformCollection*) _cmsPluginMalloc(id, sizeof(_cmsTransformCollection));
+ fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
if (fl == NULL) return FALSE;
- // Copy the parameters
+ // Copy the parameters
fl ->Factory = Plugin ->Factory;
// Keep linked list
- fl ->Next = TransformCollection;
- TransformCollection = fl;
+ fl ->Next = ctx->TransformCollection;
+ ctx->TransformCollection = fl;
// All is ok
return TRUE;
@@ -434,6 +589,7 @@ static
_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
+ _cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
_cmsTransformCollection* Plugin;
// Allocate needed memory
@@ -444,7 +600,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
p ->Lut = lut;
// Let's see if any plug-in want to do the transform by itself
- for (Plugin = TransformCollection;
+ for (Plugin = ctx ->TransformCollection;
Plugin != NULL;
Plugin = Plugin ->Next) {
@@ -464,10 +620,10 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
// 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(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
- p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
- p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
- p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ 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;
}
@@ -475,14 +631,14 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
// Not suitable for the transform plug-in, let's check the pipeline plug-in
if (p ->Lut != NULL)
- _cmsOptimizePipeline(&p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
+ _cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
// Check whatever this is a true floating point transform
if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
// Get formatter function always return a valid union, but the contents of this union may be NULL.
- p ->FromInputFloat = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
- p ->ToOutputFloat = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
+ p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
*dwFlags |= cmsFLAGS_CAN_CHANGE_FORMATTER;
if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
@@ -492,8 +648,15 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
return NULL;
}
- // Float transforms don't use caché, always are non-NULL
- p ->xform = FloatXFORM;
+ if (*dwFlags & cmsFLAGS_NULLTRANSFORM) {
+
+ p ->xform = NullFloatXFORM;
+ }
+ else {
+ // Float transforms don't use caché, always are non-NULL
+ p ->xform = FloatXFORM;
+ }
+
}
else {
@@ -505,8 +668,8 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
int BytesPerPixelInput;
- p ->FromInput = _cmsGetFormatter(*InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
- p ->ToOutput = _cmsGetFormatter(*OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
if (p ->FromInput == NULL || p ->ToOutput == NULL) {
@@ -801,7 +964,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID,
for (i=0; i < nProfiles; i++) {
BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE;
Intents[i] = Intent;
- AdaptationStates[i] = GlobalAdaptationState;
+ AdaptationStates[i] = cmsSetAdaptationStateTHR(ContextID, -1);
}
@@ -881,7 +1044,7 @@ cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID,
Intents[0] = nIntent; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = ProofingIntent;
BPC[0] = DoBPC; BPC[1] = DoBPC; BPC[2] = 0; BPC[3] = 0;
- Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = GlobalAdaptationState;
+ Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = cmsSetAdaptationStateTHR(ContextID, -1);
if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK)))
return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags);
@@ -956,8 +1119,8 @@ cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
return FALSE;
}
- FromInput = _cmsGetFormatter(InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
- ToOutput = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ FromInput = _cmsGetFormatter(xform->ContextID, InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
+ ToOutput = _cmsGetFormatter(xform->ContextID, OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
if (FromInput == NULL || ToOutput == NULL) {
diff --git a/src/lcms2.def b/src/lcms2.def
index def9680..a1f69c4 100644
--- a/src/lcms2.def
+++ b/src/lcms2.def
@@ -1,325 +1,341 @@
-LIBRARY LCMS2.DLL
-
-EXPORTS
-
-_cms15Fixed16toDouble = _cms15Fixed16toDouble
-_cms8Fixed8toDouble = _cms8Fixed8toDouble
-cmsAdaptToIlluminant = cmsAdaptToIlluminant
-_cmsAdjustEndianess16 = _cmsAdjustEndianess16
-_cmsAdjustEndianess32 = _cmsAdjustEndianess32
-_cmsAdjustEndianess64 = _cmsAdjustEndianess64
-cmsAllocNamedColorList = cmsAllocNamedColorList
-cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription
-cmsAppendNamedColor = cmsAppendNamedColor
-cmsBFDdeltaE = cmsBFDdeltaE
-cmsBuildGamma = cmsBuildGamma
-cmsBuildParametricToneCurve = cmsBuildParametricToneCurve
-cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve
-cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16
-cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat
-_cmsCalloc = _cmsCalloc
-cmsChannelsOf = cmsChannelsOf
-cmsCIE2000DeltaE = cmsCIE2000DeltaE
-cmsCIE94DeltaE = cmsCIE94DeltaE
-cmsCIECAM02Done = cmsCIECAM02Done
-cmsCIECAM02Forward = cmsCIECAM02Forward
-cmsCIECAM02Init = cmsCIECAM02Init
-cmsCIECAM02Reverse = cmsCIECAM02Reverse
-cmsCloseIOhandler = cmsCloseIOhandler
-cmsCloseProfile = cmsCloseProfile
-cmsCMCdeltaE = cmsCMCdeltaE
-cmsCreate_sRGBProfile = cmsCreate_sRGBProfile
-cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR
-cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile
-cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR
-cmsCreateExtendedTransform = cmsCreateExtendedTransform
-cmsCreateGrayProfile = cmsCreateGrayProfile
-cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR
-cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink
-cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR
-cmsCreateLab2Profile = cmsCreateLab2Profile
-cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR
-cmsCreateLab4Profile = cmsCreateLab4Profile
-cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR
-cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink
-cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR
-cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform
-cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR
-cmsCreateNULLProfile = cmsCreateNULLProfile
-cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR
-cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder
-cmsCreateProofingTransform = cmsCreateProofingTransform
-cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR
-cmsCreateRGBProfile = cmsCreateRGBProfile
-cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR
-cmsCreateTransform = cmsCreateTransform
-cmsCreateTransformTHR = cmsCreateTransformTHR
-cmsCreateXYZProfile = cmsCreateXYZProfile
-cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR
-cmsD50_xyY = cmsD50_xyY
-cmsD50_XYZ = cmsD50_XYZ
-_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber
-_cmsDefaultICCintents = _cmsDefaultICCintents
-cmsDeleteTransform = cmsDeleteTransform
-cmsDeltaE = cmsDeltaE
-cmsDetectBlackPoint = cmsDetectBlackPoint
-cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint
-cmsDetectTAC = cmsDetectTAC
-cmsDesaturateLab = cmsDesaturateLab
-cmsDoTransform = cmsDoTransform
-cmsDoTransformStride = cmsDoTransformStride
-_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16
-_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8
-_cmsDupMem = _cmsDupMem
-cmsDupNamedColorList = cmsDupNamedColorList
-cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription
-cmsDupToneCurve = cmsDupToneCurve
-_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber
-cmsEstimateGamma = cmsEstimateGamma
-cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries
-cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable
-cmsEvalToneCurve16 = cmsEvalToneCurve16
-cmsEvalToneCurveFloat = cmsEvalToneCurveFloat
-cmsfilelength = cmsfilelength
-cmsFloat2LabEncoded = cmsFloat2LabEncoded
-cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2
-cmsFloat2XYZEncoded = cmsFloat2XYZEncoded
-cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile
-cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile
-_cmsFree = _cmsFree
-cmsFreeNamedColorList = cmsFreeNamedColorList
-cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription
-cmsFreeToneCurve = cmsFreeToneCurve
-cmsFreeToneCurveTriple = cmsFreeToneCurveTriple
-cmsGBDAlloc = cmsGBDAlloc
-cmsGBDFree = cmsGBDFree
-cmsGDBAddPoint = cmsGDBAddPoint
-cmsGDBCheckPoint = cmsGDBCheckPoint
-cmsGDBCompute = cmsGDBCompute
-cmsGetAlarmCodes = cmsGetAlarmCodes
-cmsGetColorSpace = cmsGetColorSpace
-cmsGetDeviceClass = cmsGetDeviceClass
-cmsGetEncodedICCversion = cmsGetEncodedICCversion
-cmsGetHeaderAttributes = cmsGetHeaderAttributes
-cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime
-cmsGetHeaderFlags = cmsGetHeaderFlags
-cmsGetHeaderManufacturer = cmsGetHeaderManufacturer
-cmsGetHeaderModel = cmsGetHeaderModel
-cmsGetHeaderProfileID = cmsGetHeaderProfileID
-cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent
-cmsGetNamedColorList = cmsGetNamedColorList
-cmsGetPCS = cmsGetPCS
-cmsGetPostScriptColorResource = cmsGetPostScriptColorResource
-cmsGetPostScriptCRD = cmsGetPostScriptCRD
-cmsGetPostScriptCSA = cmsGetPostScriptCSA
-cmsGetProfileInfo = cmsGetProfileInfo
-cmsGetProfileInfoASCII = cmsGetProfileInfoASCII
-cmsGetProfileContextID = cmsGetProfileContextID
-cmsGetProfileVersion = cmsGetProfileVersion
-cmsGetSupportedIntents = cmsGetSupportedIntents
-cmsGetTagCount = cmsGetTagCount
-cmsGetTagSignature = cmsGetTagSignature
-cmsGetTransformContextID = cmsGetTransformContextID
-_cmsICCcolorSpace = _cmsICCcolorSpace
-_cmsIOPrintf = _cmsIOPrintf
-cmsIsCLUT = cmsIsCLUT
-cmsIsIntentSupported = cmsIsIntentSupported
-cmsIsMatrixShaper = cmsIsMatrixShaper
-cmsIsTag = cmsIsTag
-cmsIsToneCurveDescending = cmsIsToneCurveDescending
-cmsIsToneCurveLinear = cmsIsToneCurveLinear
-cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic
-cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment
-cmsGetToneCurveParametricType = cmsGetToneCurveParametricType
-cmsIT8Alloc = cmsIT8Alloc
-cmsIT8DefineDblFormat = cmsIT8DefineDblFormat
-cmsIT8EnumDataFormat = cmsIT8EnumDataFormat
-cmsIT8EnumProperties = cmsIT8EnumProperties
-cmsIT8EnumPropertyMulti = cmsIT8EnumPropertyMulti
-cmsIT8Free = cmsIT8Free
-cmsIT8GetData = cmsIT8GetData
-cmsIT8GetDataDbl = cmsIT8GetDataDbl
-cmsIT8FindDataFormat = cmsIT8FindDataFormat
-cmsIT8GetDataRowCol = cmsIT8GetDataRowCol
-cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl
-cmsIT8GetPatchName = cmsIT8GetPatchName
-cmsIT8GetPatchByName = cmsIT8GetPatchByName
-cmsIT8GetProperty = cmsIT8GetProperty
-cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl
-cmsIT8GetPropertyMulti = cmsIT8GetPropertyMulti
-cmsIT8GetSheetType = cmsIT8GetSheetType
-cmsIT8LoadFromFile = cmsIT8LoadFromFile
-cmsIT8LoadFromMem = cmsIT8LoadFromMem
-cmsIT8SaveToFile = cmsIT8SaveToFile
-cmsIT8SaveToMem = cmsIT8SaveToMem
-cmsIT8SetComment = cmsIT8SetComment
-cmsIT8SetData = cmsIT8SetData
-cmsIT8SetDataDbl = cmsIT8SetDataDbl
-cmsIT8SetDataFormat = cmsIT8SetDataFormat
-cmsIT8SetDataRowCol = cmsIT8SetDataRowCol
-cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl
-cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl
-cmsIT8SetPropertyHex = cmsIT8SetPropertyHex
-cmsIT8SetPropertyStr = cmsIT8SetPropertyStr
-cmsIT8SetPropertyMulti = cmsIT8SetPropertyMulti
-cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked
-cmsIT8SetSheetType = cmsIT8SetSheetType
-cmsIT8SetTable = cmsIT8SetTable
-cmsIT8SetTableByLabel = cmsIT8SetTableByLabel
-cmsIT8SetIndexColumn = cmsIT8SetIndexColumn
-cmsIT8TableCount = cmsIT8TableCount
-cmsJoinToneCurve = cmsJoinToneCurve
-cmsLab2LCh = cmsLab2LCh
-cmsLab2XYZ = cmsLab2XYZ
-cmsLabEncoded2Float = cmsLabEncoded2Float
-cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2
-cmsLCh2Lab = cmsLCh2Lab
-_cmsLCMScolorSpace = _cmsLCMScolorSpace
-cmsLinkTag = cmsLinkTag
-cmsTagLinkedTo = cmsTagLinkedTo
-cmsPipelineAlloc = cmsPipelineAlloc
-cmsPipelineCat = cmsPipelineCat
-cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages
-cmsPipelineDup = cmsPipelineDup
-cmsPipelineStageCount = cmsPipelineStageCount
-cmsPipelineEval16 = cmsPipelineEval16
-cmsPipelineEvalFloat = cmsPipelineEvalFloat
-cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat
-cmsPipelineFree = cmsPipelineFree
-cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage
-cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage
-cmsPipelineInputChannels = cmsPipelineInputChannels
-cmsPipelineInsertStage = cmsPipelineInsertStage
-cmsPipelineOutputChannels = cmsPipelineOutputChannels
-cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag
-_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters
-cmsPipelineUnlinkStage = cmsPipelineUnlinkStage
-_cmsMalloc = _cmsMalloc
-_cmsMallocZero = _cmsMallocZero
-_cmsMAT3eval = _cmsMAT3eval
-_cmsMAT3identity = _cmsMAT3identity
-_cmsMAT3inverse = _cmsMAT3inverse
-_cmsMAT3isIdentity = _cmsMAT3isIdentity
-_cmsMAT3per = _cmsMAT3per
-_cmsMAT3solve = _cmsMAT3solve
-cmsMD5computeID = cmsMD5computeID
-cmsMLUalloc = cmsMLUalloc
-cmsMLUdup = cmsMLUdup
-cmsMLUfree = cmsMLUfree
-cmsMLUgetASCII = cmsMLUgetASCII
-cmsMLUgetTranslation = cmsMLUgetTranslation
-cmsMLUgetWide = cmsMLUgetWide
-cmsMLUsetASCII = cmsMLUsetASCII
-cmsMLUsetWide = cmsMLUsetWide
-cmsStageAllocCLut16bit = cmsStageAllocCLut16bit
-cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular
-cmsStageAllocCLutFloat = cmsStageAllocCLutFloat
-cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular
-cmsStageAllocToneCurves = cmsStageAllocToneCurves
-cmsStageAllocIdentity = cmsStageAllocIdentity
-cmsStageAllocMatrix = cmsStageAllocMatrix
-_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder
-cmsStageDup = cmsStageDup
-cmsStageFree = cmsStageFree
-cmsStageNext = cmsStageNext
-cmsStageInputChannels = cmsStageInputChannels
-cmsStageOutputChannels = cmsStageOutputChannels
-cmsStageSampleCLut16bit = cmsStageSampleCLut16bit
-cmsStageSampleCLutFloat = cmsStageSampleCLutFloat
-cmsStageType = cmsStageType
-cmsStageData = cmsStageData
-cmsNamedColorCount = cmsNamedColorCount
-cmsNamedColorIndex = cmsNamedColorIndex
-cmsNamedColorInfo = cmsNamedColorInfo
-cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile
-cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem
-cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL
-cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream
-cmsOpenProfileFromFile = cmsOpenProfileFromFile
-cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR
-cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR
-cmsOpenProfileFromMem = cmsOpenProfileFromMem
-cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR
-cmsOpenProfileFromStream = cmsOpenProfileFromStream
-cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR
-cmsPlugin = cmsPlugin
-_cmsRead15Fixed16Number = _cmsRead15Fixed16Number
-_cmsReadAlignment = _cmsReadAlignment
-_cmsReadFloat32Number = _cmsReadFloat32Number
-cmsReadRawTag = cmsReadRawTag
-cmsReadTag = cmsReadTag
-_cmsReadTypeBase = _cmsReadTypeBase
-_cmsReadUInt16Array = _cmsReadUInt16Array
-_cmsReadUInt16Number = _cmsReadUInt16Number
-_cmsReadUInt32Number = _cmsReadUInt32Number
-_cmsReadUInt64Number = _cmsReadUInt64Number
-_cmsReadUInt8Number = _cmsReadUInt8Number
-_cmsReadXYZNumber = _cmsReadXYZNumber
-_cmsRealloc = _cmsRealloc
-cmsReverseToneCurve = cmsReverseToneCurve
-cmsReverseToneCurveEx = cmsReverseToneCurveEx
-cmsSaveProfileToFile = cmsSaveProfileToFile
-cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler
-cmsSaveProfileToMem = cmsSaveProfileToMem
-cmsSaveProfileToStream = cmsSaveProfileToStream
-cmsSetAdaptationState = cmsSetAdaptationState
-cmsSetAlarmCodes = cmsSetAlarmCodes
-cmsSetColorSpace = cmsSetColorSpace
-cmsSetDeviceClass = cmsSetDeviceClass
-cmsSetEncodedICCversion = cmsSetEncodedICCversion
-cmsSetHeaderAttributes = cmsSetHeaderAttributes
-cmsSetHeaderFlags = cmsSetHeaderFlags
-cmsSetHeaderManufacturer = cmsSetHeaderManufacturer
-cmsSetHeaderModel = cmsSetHeaderModel
-cmsSetHeaderProfileID = cmsSetHeaderProfileID
-cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent
-cmsSetLogErrorHandler = cmsSetLogErrorHandler
-cmsSetPCS = cmsSetPCS
-cmsSetProfileVersion = cmsSetProfileVersion
-cmsSignalError = cmsSignalError
-cmsSmoothToneCurve = cmsSmoothToneCurve
-cmsstrcasecmp = cmsstrcasecmp
-cmsTempFromWhitePoint = cmsTempFromWhitePoint
-cmsTransform2DeviceLink = cmsTransform2DeviceLink
-cmsUnregisterPlugins = cmsUnregisterPlugins
-_cmsVEC3cross = _cmsVEC3cross
-_cmsVEC3distance = _cmsVEC3distance
-_cmsVEC3dot = _cmsVEC3dot
-_cmsVEC3init = _cmsVEC3init
-_cmsVEC3length = _cmsVEC3length
-_cmsVEC3minus = _cmsVEC3minus
-cmsWhitePointFromTemp = cmsWhitePointFromTemp
-_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number
-_cmsWriteAlignment = _cmsWriteAlignment
-_cmsWriteFloat32Number = _cmsWriteFloat32Number
-cmsWriteRawTag = cmsWriteRawTag
-cmsWriteTag = cmsWriteTag
-_cmsWriteTypeBase = _cmsWriteTypeBase
-_cmsWriteUInt16Array = _cmsWriteUInt16Array
-_cmsWriteUInt16Number = _cmsWriteUInt16Number
-_cmsWriteUInt32Number = _cmsWriteUInt32Number
-_cmsWriteUInt64Number = _cmsWriteUInt64Number
-_cmsWriteUInt8Number = _cmsWriteUInt8Number
-_cmsWriteXYZNumber = _cmsWriteXYZNumber
-cmsxyY2XYZ = cmsxyY2XYZ
-cmsXYZ2Lab = cmsXYZ2Lab
-cmsXYZ2xyY = cmsXYZ2xyY
-cmsXYZEncoded2Float = cmsXYZEncoded2Float
-cmsSliceSpace16 = cmsSliceSpace16
-cmsSliceSpaceFloat = cmsSliceSpaceFloat
-cmsChangeBuffersFormat = cmsChangeBuffersFormat
-cmsDictAlloc = cmsDictAlloc
-cmsDictFree = cmsDictFree
-cmsDictDup = cmsDictDup
-cmsDictAddEntry = cmsDictAddEntry
-cmsDictGetEntryList = cmsDictGetEntryList
-cmsDictNextEntry = cmsDictNextEntry
-_cmsGetTransformUserData = _cmsGetTransformUserData
-_cmsSetTransformUserData = _cmsSetTransformUserData
-_cmsGetTransformFormatters16 = _cmsGetTransformFormatters16
-_cmsGetTransformFormattersFloat = _cmsGetTransformFormattersFloat
-cmsGetHeaderCreator = cmsGetHeaderCreator
-cmsPluginTHR = cmsPluginTHR
-cmsGetPipelineContextID = cmsGetPipelineContextID
-cmsGetTransformInputFormat = cmsGetTransformInputFormat
-cmsGetTransformOutputFormat = cmsGetTransformOutputFormat
+LIBRARY LCMS2.DLL
+
+EXPORTS
+
+_cms15Fixed16toDouble = _cms15Fixed16toDouble
+_cms8Fixed8toDouble = _cms8Fixed8toDouble
+cmsAdaptToIlluminant = cmsAdaptToIlluminant
+_cmsAdjustEndianess16 = _cmsAdjustEndianess16
+_cmsAdjustEndianess32 = _cmsAdjustEndianess32
+_cmsAdjustEndianess64 = _cmsAdjustEndianess64
+cmsAllocNamedColorList = cmsAllocNamedColorList
+cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription
+cmsAppendNamedColor = cmsAppendNamedColor
+cmsBFDdeltaE = cmsBFDdeltaE
+cmsBuildGamma = cmsBuildGamma
+cmsBuildParametricToneCurve = cmsBuildParametricToneCurve
+cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve
+cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16
+cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat
+_cmsCalloc = _cmsCalloc
+cmsChannelsOf = cmsChannelsOf
+cmsCIE2000DeltaE = cmsCIE2000DeltaE
+cmsCIE94DeltaE = cmsCIE94DeltaE
+cmsCIECAM02Done = cmsCIECAM02Done
+cmsCIECAM02Forward = cmsCIECAM02Forward
+cmsCIECAM02Init = cmsCIECAM02Init
+cmsCIECAM02Reverse = cmsCIECAM02Reverse
+cmsCloseIOhandler = cmsCloseIOhandler
+cmsCloseProfile = cmsCloseProfile
+cmsCMCdeltaE = cmsCMCdeltaE
+cmsCreate_sRGBProfile = cmsCreate_sRGBProfile
+cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR
+cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile
+cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR
+cmsCreateExtendedTransform = cmsCreateExtendedTransform
+cmsCreateGrayProfile = cmsCreateGrayProfile
+cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR
+cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink
+cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR
+cmsCreateLab2Profile = cmsCreateLab2Profile
+cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR
+cmsCreateLab4Profile = cmsCreateLab4Profile
+cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR
+cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink
+cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR
+cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform
+cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR
+cmsCreateNULLProfile = cmsCreateNULLProfile
+cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR
+cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder
+cmsCreateProofingTransform = cmsCreateProofingTransform
+cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR
+cmsCreateRGBProfile = cmsCreateRGBProfile
+cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR
+cmsCreateTransform = cmsCreateTransform
+cmsCreateTransformTHR = cmsCreateTransformTHR
+cmsCreateXYZProfile = cmsCreateXYZProfile
+cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR
+cmsD50_xyY = cmsD50_xyY
+cmsD50_XYZ = cmsD50_XYZ
+_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber
+_cmsDefaultICCintents = _cmsDefaultICCintents
+cmsDeleteTransform = cmsDeleteTransform
+cmsDeltaE = cmsDeltaE
+cmsDetectBlackPoint = cmsDetectBlackPoint
+cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint
+cmsDetectTAC = cmsDetectTAC
+cmsDesaturateLab = cmsDesaturateLab
+cmsDoTransform = cmsDoTransform
+cmsDoTransformStride = cmsDoTransformStride
+_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16
+_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8
+_cmsDupMem = _cmsDupMem
+cmsDupNamedColorList = cmsDupNamedColorList
+cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription
+cmsDupToneCurve = cmsDupToneCurve
+_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber
+cmsEstimateGamma = cmsEstimateGamma
+cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries
+cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable
+cmsEvalToneCurve16 = cmsEvalToneCurve16
+cmsEvalToneCurveFloat = cmsEvalToneCurveFloat
+cmsfilelength = cmsfilelength
+cmsFloat2LabEncoded = cmsFloat2LabEncoded
+cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2
+cmsFloat2XYZEncoded = cmsFloat2XYZEncoded
+cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile
+cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile
+_cmsFree = _cmsFree
+cmsFreeNamedColorList = cmsFreeNamedColorList
+cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription
+cmsFreeToneCurve = cmsFreeToneCurve
+cmsFreeToneCurveTriple = cmsFreeToneCurveTriple
+cmsGBDAlloc = cmsGBDAlloc
+cmsGBDFree = cmsGBDFree
+cmsGDBAddPoint = cmsGDBAddPoint
+cmsGDBCheckPoint = cmsGDBCheckPoint
+cmsGDBCompute = cmsGDBCompute
+cmsGetAlarmCodes = cmsGetAlarmCodes
+cmsGetColorSpace = cmsGetColorSpace
+cmsGetDeviceClass = cmsGetDeviceClass
+cmsGetEncodedICCversion = cmsGetEncodedICCversion
+cmsGetHeaderAttributes = cmsGetHeaderAttributes
+cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime
+cmsGetHeaderFlags = cmsGetHeaderFlags
+cmsGetHeaderManufacturer = cmsGetHeaderManufacturer
+cmsGetHeaderModel = cmsGetHeaderModel
+cmsGetHeaderProfileID = cmsGetHeaderProfileID
+cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent
+cmsGetNamedColorList = cmsGetNamedColorList
+cmsGetPCS = cmsGetPCS
+cmsGetPostScriptColorResource = cmsGetPostScriptColorResource
+cmsGetPostScriptCRD = cmsGetPostScriptCRD
+cmsGetPostScriptCSA = cmsGetPostScriptCSA
+cmsGetProfileInfo = cmsGetProfileInfo
+cmsGetProfileInfoASCII = cmsGetProfileInfoASCII
+cmsGetProfileContextID = cmsGetProfileContextID
+cmsGetProfileVersion = cmsGetProfileVersion
+cmsGetSupportedIntents = cmsGetSupportedIntents
+cmsGetTagCount = cmsGetTagCount
+cmsGetTagSignature = cmsGetTagSignature
+cmsGetTransformContextID = cmsGetTransformContextID
+_cmsICCcolorSpace = _cmsICCcolorSpace
+_cmsIOPrintf = _cmsIOPrintf
+cmsIsCLUT = cmsIsCLUT
+cmsIsIntentSupported = cmsIsIntentSupported
+cmsIsMatrixShaper = cmsIsMatrixShaper
+cmsIsTag = cmsIsTag
+cmsIsToneCurveDescending = cmsIsToneCurveDescending
+cmsIsToneCurveLinear = cmsIsToneCurveLinear
+cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic
+cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment
+cmsGetToneCurveParametricType = cmsGetToneCurveParametricType
+cmsIT8Alloc = cmsIT8Alloc
+cmsIT8DefineDblFormat = cmsIT8DefineDblFormat
+cmsIT8EnumDataFormat = cmsIT8EnumDataFormat
+cmsIT8EnumProperties = cmsIT8EnumProperties
+cmsIT8EnumPropertyMulti = cmsIT8EnumPropertyMulti
+cmsIT8Free = cmsIT8Free
+cmsIT8GetData = cmsIT8GetData
+cmsIT8GetDataDbl = cmsIT8GetDataDbl
+cmsIT8FindDataFormat = cmsIT8FindDataFormat
+cmsIT8GetDataRowCol = cmsIT8GetDataRowCol
+cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl
+cmsIT8GetPatchName = cmsIT8GetPatchName
+cmsIT8GetPatchByName = cmsIT8GetPatchByName
+cmsIT8GetProperty = cmsIT8GetProperty
+cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl
+cmsIT8GetPropertyMulti = cmsIT8GetPropertyMulti
+cmsIT8GetSheetType = cmsIT8GetSheetType
+cmsIT8LoadFromFile = cmsIT8LoadFromFile
+cmsIT8LoadFromMem = cmsIT8LoadFromMem
+cmsIT8SaveToFile = cmsIT8SaveToFile
+cmsIT8SaveToMem = cmsIT8SaveToMem
+cmsIT8SetComment = cmsIT8SetComment
+cmsIT8SetData = cmsIT8SetData
+cmsIT8SetDataDbl = cmsIT8SetDataDbl
+cmsIT8SetDataFormat = cmsIT8SetDataFormat
+cmsIT8SetDataRowCol = cmsIT8SetDataRowCol
+cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl
+cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl
+cmsIT8SetPropertyHex = cmsIT8SetPropertyHex
+cmsIT8SetPropertyStr = cmsIT8SetPropertyStr
+cmsIT8SetPropertyMulti = cmsIT8SetPropertyMulti
+cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked
+cmsIT8SetSheetType = cmsIT8SetSheetType
+cmsIT8SetTable = cmsIT8SetTable
+cmsIT8SetTableByLabel = cmsIT8SetTableByLabel
+cmsIT8SetIndexColumn = cmsIT8SetIndexColumn
+cmsIT8TableCount = cmsIT8TableCount
+cmsJoinToneCurve = cmsJoinToneCurve
+cmsLab2LCh = cmsLab2LCh
+cmsLab2XYZ = cmsLab2XYZ
+cmsLabEncoded2Float = cmsLabEncoded2Float
+cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2
+cmsLCh2Lab = cmsLCh2Lab
+_cmsLCMScolorSpace = _cmsLCMScolorSpace
+cmsLinkTag = cmsLinkTag
+cmsTagLinkedTo = cmsTagLinkedTo
+cmsPipelineAlloc = cmsPipelineAlloc
+cmsPipelineCat = cmsPipelineCat
+cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages
+cmsPipelineDup = cmsPipelineDup
+cmsPipelineStageCount = cmsPipelineStageCount
+cmsPipelineEval16 = cmsPipelineEval16
+cmsPipelineEvalFloat = cmsPipelineEvalFloat
+cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat
+cmsPipelineFree = cmsPipelineFree
+cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage
+cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage
+cmsPipelineInputChannels = cmsPipelineInputChannels
+cmsPipelineInsertStage = cmsPipelineInsertStage
+cmsPipelineOutputChannels = cmsPipelineOutputChannels
+cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag
+_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters
+cmsPipelineUnlinkStage = cmsPipelineUnlinkStage
+_cmsMalloc = _cmsMalloc
+_cmsMallocZero = _cmsMallocZero
+_cmsMAT3eval = _cmsMAT3eval
+_cmsMAT3identity = _cmsMAT3identity
+_cmsMAT3inverse = _cmsMAT3inverse
+_cmsMAT3isIdentity = _cmsMAT3isIdentity
+_cmsMAT3per = _cmsMAT3per
+_cmsMAT3solve = _cmsMAT3solve
+cmsMD5computeID = cmsMD5computeID
+cmsMLUalloc = cmsMLUalloc
+cmsMLUdup = cmsMLUdup
+cmsMLUfree = cmsMLUfree
+cmsMLUgetASCII = cmsMLUgetASCII
+cmsMLUgetTranslation = cmsMLUgetTranslation
+cmsMLUgetWide = cmsMLUgetWide
+cmsMLUsetASCII = cmsMLUsetASCII
+cmsMLUsetWide = cmsMLUsetWide
+cmsStageAllocCLut16bit = cmsStageAllocCLut16bit
+cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular
+cmsStageAllocCLutFloat = cmsStageAllocCLutFloat
+cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular
+cmsStageAllocToneCurves = cmsStageAllocToneCurves
+cmsStageAllocIdentity = cmsStageAllocIdentity
+cmsStageAllocMatrix = cmsStageAllocMatrix
+_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder
+cmsStageDup = cmsStageDup
+cmsStageFree = cmsStageFree
+cmsStageNext = cmsStageNext
+cmsStageInputChannels = cmsStageInputChannels
+cmsStageOutputChannels = cmsStageOutputChannels
+cmsStageSampleCLut16bit = cmsStageSampleCLut16bit
+cmsStageSampleCLutFloat = cmsStageSampleCLutFloat
+cmsStageType = cmsStageType
+cmsStageData = cmsStageData
+cmsNamedColorCount = cmsNamedColorCount
+cmsNamedColorIndex = cmsNamedColorIndex
+cmsNamedColorInfo = cmsNamedColorInfo
+cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile
+cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem
+cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL
+cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream
+cmsOpenProfileFromFile = cmsOpenProfileFromFile
+cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR
+cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR
+cmsOpenProfileFromMem = cmsOpenProfileFromMem
+cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR
+cmsOpenProfileFromStream = cmsOpenProfileFromStream
+cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR
+cmsPlugin = cmsPlugin
+_cmsRead15Fixed16Number = _cmsRead15Fixed16Number
+_cmsReadAlignment = _cmsReadAlignment
+_cmsReadFloat32Number = _cmsReadFloat32Number
+cmsReadRawTag = cmsReadRawTag
+cmsReadTag = cmsReadTag
+_cmsReadTypeBase = _cmsReadTypeBase
+_cmsReadUInt16Array = _cmsReadUInt16Array
+_cmsReadUInt16Number = _cmsReadUInt16Number
+_cmsReadUInt32Number = _cmsReadUInt32Number
+_cmsReadUInt64Number = _cmsReadUInt64Number
+_cmsReadUInt8Number = _cmsReadUInt8Number
+_cmsReadXYZNumber = _cmsReadXYZNumber
+_cmsRealloc = _cmsRealloc
+cmsReverseToneCurve = cmsReverseToneCurve
+cmsReverseToneCurveEx = cmsReverseToneCurveEx
+cmsSaveProfileToFile = cmsSaveProfileToFile
+cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler
+cmsSaveProfileToMem = cmsSaveProfileToMem
+cmsSaveProfileToStream = cmsSaveProfileToStream
+cmsSetAdaptationState = cmsSetAdaptationState
+cmsSetAlarmCodes = cmsSetAlarmCodes
+cmsSetColorSpace = cmsSetColorSpace
+cmsSetDeviceClass = cmsSetDeviceClass
+cmsSetEncodedICCversion = cmsSetEncodedICCversion
+cmsSetHeaderAttributes = cmsSetHeaderAttributes
+cmsSetHeaderFlags = cmsSetHeaderFlags
+cmsSetHeaderManufacturer = cmsSetHeaderManufacturer
+cmsSetHeaderModel = cmsSetHeaderModel
+cmsSetHeaderProfileID = cmsSetHeaderProfileID
+cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent
+cmsSetLogErrorHandler = cmsSetLogErrorHandler
+cmsSetPCS = cmsSetPCS
+cmsSetProfileVersion = cmsSetProfileVersion
+cmsSignalError = cmsSignalError
+cmsSmoothToneCurve = cmsSmoothToneCurve
+cmsstrcasecmp = cmsstrcasecmp
+cmsTempFromWhitePoint = cmsTempFromWhitePoint
+cmsTransform2DeviceLink = cmsTransform2DeviceLink
+cmsUnregisterPlugins = cmsUnregisterPlugins
+_cmsVEC3cross = _cmsVEC3cross
+_cmsVEC3distance = _cmsVEC3distance
+_cmsVEC3dot = _cmsVEC3dot
+_cmsVEC3init = _cmsVEC3init
+_cmsVEC3length = _cmsVEC3length
+_cmsVEC3minus = _cmsVEC3minus
+cmsWhitePointFromTemp = cmsWhitePointFromTemp
+_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number
+_cmsWriteAlignment = _cmsWriteAlignment
+_cmsWriteFloat32Number = _cmsWriteFloat32Number
+cmsWriteRawTag = cmsWriteRawTag
+cmsWriteTag = cmsWriteTag
+_cmsWriteTypeBase = _cmsWriteTypeBase
+_cmsWriteUInt16Array = _cmsWriteUInt16Array
+_cmsWriteUInt16Number = _cmsWriteUInt16Number
+_cmsWriteUInt32Number = _cmsWriteUInt32Number
+_cmsWriteUInt64Number = _cmsWriteUInt64Number
+_cmsWriteUInt8Number = _cmsWriteUInt8Number
+_cmsWriteXYZNumber = _cmsWriteXYZNumber
+cmsxyY2XYZ = cmsxyY2XYZ
+cmsXYZ2Lab = cmsXYZ2Lab
+cmsXYZ2xyY = cmsXYZ2xyY
+cmsXYZEncoded2Float = cmsXYZEncoded2Float
+cmsSliceSpace16 = cmsSliceSpace16
+cmsSliceSpaceFloat = cmsSliceSpaceFloat
+cmsChangeBuffersFormat = cmsChangeBuffersFormat
+cmsDictAlloc = cmsDictAlloc
+cmsDictFree = cmsDictFree
+cmsDictDup = cmsDictDup
+cmsDictAddEntry = cmsDictAddEntry
+cmsDictGetEntryList = cmsDictGetEntryList
+cmsDictNextEntry = cmsDictNextEntry
+_cmsGetTransformUserData = _cmsGetTransformUserData
+_cmsSetTransformUserData = _cmsSetTransformUserData
+_cmsGetTransformFormatters16 = _cmsGetTransformFormatters16
+_cmsGetTransformFormattersFloat = _cmsGetTransformFormattersFloat
+cmsGetHeaderCreator = cmsGetHeaderCreator
+cmsPluginTHR = cmsPluginTHR
+cmsGetPipelineContextID = cmsGetPipelineContextID
+cmsGetTransformInputFormat = cmsGetTransformInputFormat
+cmsGetTransformOutputFormat = cmsGetTransformOutputFormat
+cmsCreateContext = cmsCreateContext
+cmsDupContext = cmsDupContext
+cmsDeleteContext = cmsDeleteContext
+cmsGetContextUserData = cmsGetContextUserData
+cmsUnregisterPluginsTHR = cmsUnregisterPluginsTHR
+cmsSetAlarmCodesTHR = cmsSetAlarmCodesTHR
+cmsGetAlarmCodesTHR = cmsGetAlarmCodesTHR
+cmsSetAdaptationStateTHR = cmsSetAdaptationStateTHR
+cmsSetLogErrorHandlerTHR = cmsSetLogErrorHandlerTHR
+cmsGetSupportedIntentsTHR = cmsGetSupportedIntentsTHR
+cmsMLUtranslationsCount = cmsMLUtranslationsCount
+cmsMLUtranslationsCodes = cmsMLUtranslationsCodes
+_cmsCreateMutex = _cmsCreateMutex
+_cmsDestroyMutex = _cmsDestroyMutex
+_cmsLockMutex = _cmsLockMutex
+_cmsUnlockMutex = _cmsUnlockMutex \ No newline at end of file
diff --git a/src/lcms2_internal.h b/src/lcms2_internal.h
index d6300df..61ceb00 100644
--- a/src/lcms2_internal.h
+++ b/src/lcms2_internal.h
@@ -164,16 +164,16 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d)
return _cmsQuickFloorWord(d);
}
-// Plug-In registering ---------------------------------------------------------------
+// Plug-In registration ---------------------------------------------------------------
// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size);
// Memory management
-cmsBool _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterMemHandlerPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Interpolation
-cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Plugin);
+cmsBool _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
// Parametric curves
cmsBool _cmsRegisterParametricCurvesPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
@@ -199,6 +199,9 @@ cmsBool _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Plu
// Transform
cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
+// Mutex
+cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
+
// ---------------------------------------------------------------------------------------------------------
// Suballocators. Those are blocks of memory that is freed at the end on whole block.
@@ -224,9 +227,266 @@ typedef struct {
_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial);
void _cmsSubAllocDestroy(_cmsSubAllocator* s);
void* _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size);
+void* _cmsSubAllocDup(_cmsSubAllocator* s, const void *ptr, cmsUInt32Number size);
// ----------------------------------------------------------------------------------
+// The context clients.
+typedef enum {
+
+ UserPtr, // User-defined pointer
+ Logger,
+ AlarmCodesContext,
+ AdaptationStateContext,
+ MemPlugin,
+ InterpPlugin,
+ CurvesPlugin,
+ FormattersPlugin,
+ TagTypePlugin,
+ TagPlugin,
+ IntentPlugin,
+ MPEPlugin,
+ OptimizationPlugin,
+ TransformPlugin,
+ MutexPlugin,
+
+ // Last in list
+ MemoryClientMax
+
+} _cmsMemoryClient;
+
+// Magic number for identifying a valid context
+#define cmsContextMagicNumber 0x63747832 // 'ctx2'
+
+// Container for memory management plug-in.
+typedef struct {
+
+ _cmsMallocFnPtrType MallocPtr;
+ _cmsMalloZerocFnPtrType MallocZeroPtr;
+ _cmsFreeFnPtrType FreePtr;
+ _cmsReallocFnPtrType ReallocPtr;
+ _cmsCallocFnPtrType CallocPtr;
+ _cmsDupFnPtrType DupPtr;
+
+} _cmsMemPluginChunkType;
+
+// Copy memory management function pointers from plug-in to chunk, taking care of missing routines
+void _cmsInstallAllocFunctions(cmsPluginMemHandler* Plugin, _cmsMemPluginChunkType* ptr);
+
+// Internal structure for context
+struct _cmsContext_struct {
+
+ cmsUInt32Number Magic; // Magic number that identifies a valid context id in the new style
+ _cmsSubAllocator* MemPool; // The memory pool that stores context data
+
+ void* chunks[MemoryClientMax]; // array of pointers to client chunks. Memory itself is hold in the suballocator.
+ // If NULL, then it reverts to global Context0
+
+ _cmsMemPluginChunkType DefaultMemoryManager; // The allocators used for creating the context itself. Cannot be overriden
+};
+
+// Returns a pointer to a valid context structure, including the global one if id is zero.
+// Verifies the magic number.
+struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID);
+
+// Returns the block assigned to the specific zone.
+void* _cmsContextGetClientChunk(cmsContext id, _cmsMemoryClient mc);
+
+
+// Chunks of context memory by plug-in client -------------------------------------------------------
+
+// Those structures encapsulates all variables needed by the several context clients (mostly plug-ins)
+
+// Container for error logger -- not a plug-in
+typedef struct {
+
+ cmsLogErrorHandlerFunction LogErrorHandler; // Set to NULL for Context0 fallback
+
+} _cmsLogErrorChunkType;
+
+// The global Context0 storage for error logger
+extern _cmsLogErrorChunkType _cmsLogErrorChunk;
+
+// Allocate and init error logger container.
+void _cmsAllocLogErrorChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for alarm codes -- not a plug-in
+typedef struct {
+
+ cmsUInt16Number AlarmCodes[cmsMAXCHANNELS];
+
+} _cmsAlarmCodesChunkType;
+
+// The global Context0 storage for alarm codes
+extern _cmsAlarmCodesChunkType _cmsAlarmCodesChunk;
+
+// Allocate and init alarm codes container.
+void _cmsAllocAlarmCodesChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for adaptation state -- not a plug-in
+typedef struct {
+
+ cmsFloat64Number AdaptationState;
+
+} _cmsAdaptationStateChunkType;
+
+// The global Context0 storage for adaptation state
+extern _cmsAdaptationStateChunkType _cmsAdaptationStateChunk;
+
+// Allocate and init adaptation state container.
+void _cmsAllocAdaptationStateChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+
+// The global Context0 storage for memory management
+extern _cmsMemPluginChunkType _cmsMemPluginChunk;
+
+// Allocate and init memory management container.
+void _cmsAllocMemPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for interpolation plug-in
+typedef struct {
+
+ cmsInterpFnFactory Interpolators;
+
+} _cmsInterpPluginChunkType;
+
+// The global Context0 storage for interpolation plug-in
+extern _cmsInterpPluginChunkType _cmsInterpPluginChunk;
+
+// Allocate and init interpolation container.
+void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for parametric curves plug-in
+typedef struct {
+
+ struct _cmsParametricCurvesCollection_st* ParametricCurves;
+
+} _cmsCurvesPluginChunkType;
+
+// The global Context0 storage for tone curves plug-in
+extern _cmsCurvesPluginChunkType _cmsCurvesPluginChunk;
+
+// Allocate and init parametric curves container.
+void _cmsAllocCurvesPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for formatters plug-in
+typedef struct {
+
+ struct _cms_formatters_factory_list* FactoryList;
+
+} _cmsFormattersPluginChunkType;
+
+// The global Context0 storage for formatters plug-in
+extern _cmsFormattersPluginChunkType _cmsFormattersPluginChunk;
+
+// Allocate and init formatters container.
+void _cmsAllocFormattersPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// This chunk type is shared by TagType plug-in and MPE Plug-in
+typedef struct {
+
+ struct _cmsTagTypeLinkedList_st* TagTypes;
+
+} _cmsTagTypePluginChunkType;
+
+
+// The global Context0 storage for tag types plug-in
+extern _cmsTagTypePluginChunkType _cmsTagTypePluginChunk;
+
+
+// The global Context0 storage for mult process elements plug-in
+extern _cmsTagTypePluginChunkType _cmsMPETypePluginChunk;
+
+// Allocate and init Tag types container.
+void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+// Allocate and init MPE container.
+void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+// Container for tag plug-in
+typedef struct {
+
+ struct _cmsTagLinkedList_st* Tag;
+
+} _cmsTagPluginChunkType;
+
+
+// The global Context0 storage for tag plug-in
+extern _cmsTagPluginChunkType _cmsTagPluginChunk;
+
+// Allocate and init Tag container.
+void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for intents plug-in
+typedef struct {
+
+ struct _cms_intents_list* Intents;
+
+} _cmsIntentsPluginChunkType;
+
+
+// The global Context0 storage for intents plug-in
+extern _cmsIntentsPluginChunkType _cmsIntentsPluginChunk;
+
+// Allocate and init intents container.
+void _cmsAllocIntentsPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for optimization plug-in
+typedef struct {
+
+ struct _cmsOptimizationCollection_st* OptimizationCollection;
+
+} _cmsOptimizationPluginChunkType;
+
+
+// The global Context0 storage for optimizers plug-in
+extern _cmsOptimizationPluginChunkType _cmsOptimizationPluginChunk;
+
+// Allocate and init optimizers container.
+void _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for transform plug-in
+typedef struct {
+
+ struct _cmsTransformCollection_st* TransformCollection;
+
+} _cmsTransformPluginChunkType;
+
+// The global Context0 storage for full-transform replacement plug-in
+extern _cmsTransformPluginChunkType _cmsTransformPluginChunk;
+
+// Allocate and init transform container.
+void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// Container for mutex plug-in
+typedef struct {
+
+ _cmsCreateMutexFnPtrType CreateMutexPtr;
+ _cmsDestroyMutexFnPtrType DestroyMutexPtr;
+ _cmsLockMutexFnPtrType LockMutexPtr;
+ _cmsUnlockMutexFnPtrType UnlockMutexPtr;
+
+} _cmsMutexPluginChunkType;
+
+// The global Context0 storage for mutex plug-in
+extern _cmsMutexPluginChunkType _cmsMutexPluginChunk;
+
+// Allocate and init mutex container.
+void _cmsAllocMutexPluginChunk(struct _cmsContext_struct* ctx,
+ const struct _cmsContext_struct* src);
+
+// ----------------------------------------------------------------------------------
// MLU internal representation
typedef struct {
@@ -318,10 +578,14 @@ typedef struct _cms_iccprofile_struct {
cmsBool TagSaveAsRaw[MAX_TABLE_TAG]; // True to write uncooked
void * TagPtrs[MAX_TABLE_TAG];
cmsTagTypeHandler* TagTypeHandlers[MAX_TABLE_TAG]; // Same structure may be serialized on different types
- // depending on profile version, so we keep track of the // type handler for each tag in the list.
+ // depending on profile version, so we keep track of the
+ // type handler for each tag in the list.
// Special
cmsBool IsWrite;
+ // Keep a mutex for cmsReadTag -- Note that this only works if the user includes a mutex plugin
+ void * UsrMutex;
+
} _cmsICCPROFILE;
// IO helpers for profiles
@@ -330,9 +594,9 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSp
int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks);
// Tag types
-cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig);
+cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig);
cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig);
-cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig);
+cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig);
// Error logging ---------------------------------------------------------------------------------------------------------
@@ -343,7 +607,7 @@ void _cmsTagSignature2String(char String[5], cmsTagSignature sig
cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
void _cmsFreeInterpParams(cmsInterpParams* p);
-cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p);
+cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p);
// Curves ----------------------------------------------------------------------------------------------------------------
@@ -474,7 +738,8 @@ cmsBool _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
cmsUInt16Number **Black,
cmsUInt32Number *nOutputs);
-cmsBool _cmsOptimizePipeline(cmsPipeline** Lut,
+cmsBool _cmsOptimizePipeline(cmsContext ContextID,
+ cmsPipeline** Lut,
int Intent,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
@@ -499,7 +764,8 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
cmsBool _cmsFormatterIsFloat(cmsUInt32Number Type);
cmsBool _cmsFormatterIs8bit(cmsUInt32Number Type);
-cmsFormatter _cmsGetFormatter(cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
+cmsFormatter _cmsGetFormatter(cmsContext ContextID,
+ cmsUInt32Number Type, // Specific type, i.e. TYPE_RGB_8
cmsFormatterDirection Dir,
cmsUInt32Number dwFlags);
diff --git a/testbed/Makefile.am b/testbed/Makefile.am
index 7961a42..371ded2 100644
--- a/testbed/Makefile.am
+++ b/testbed/Makefile.am
@@ -13,11 +13,11 @@ check_PROGRAMS = testcms
testcms_LDADD = $(top_builddir)/src/liblcms2.la
testcms_LDFLAGS = @LDFLAGS@
-testcms_SOURCES = testcms2.c
+testcms_SOURCES = testcms2.c testplugin.c zoo_icc.c testcms2.h
EXTRA_DIST = test1.icc bad.icc toosmall.icc test2.icc \
test3.icc test4.icc \
- test5.icc
+ test5.icc ibm-t61.icc new.icc
check:
if [ $(top_srcdir) != $(top_builddir) ]; then \
diff --git a/testbed/Makefile.in b/testbed/Makefile.in
index 11723ec..8c0f64c 100644
--- a/testbed/Makefile.in
+++ b/testbed/Makefile.in
@@ -64,7 +64,8 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
-am_testcms_OBJECTS = testcms2.$(OBJEXT)
+am_testcms_OBJECTS = testcms2.$(OBJEXT) testplugin.$(OBJEXT) \
+ zoo_icc.$(OBJEXT)
testcms_OBJECTS = $(am_testcms_OBJECTS)
testcms_DEPENDENCIES = $(top_builddir)/src/liblcms2.la
testcms_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -233,10 +234,10 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(top_srcdir)/src
# CFLAGS = --pedantic -Wall -std=c99 -O2
testcms_LDADD = $(top_builddir)/src/liblcms2.la
testcms_LDFLAGS = @LDFLAGS@
-testcms_SOURCES = testcms2.c
+testcms_SOURCES = testcms2.c testplugin.c zoo_icc.c testcms2.h
EXTRA_DIST = test1.icc bad.icc toosmall.icc test2.icc \
test3.icc test4.icc \
- test5.icc
+ test5.icc ibm-t61.icc new.icc
all: all-am
@@ -292,6 +293,8 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcms2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testplugin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoo_icc.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/testbed/ibm-t61.icc b/testbed/ibm-t61.icc
new file mode 100755
index 0000000..497f2d8
--- /dev/null
+++ b/testbed/ibm-t61.icc
Binary files differ
diff --git a/testbed/new.icc b/testbed/new.icc
new file mode 100644
index 0000000..dd2f757
--- /dev/null
+++ b/testbed/new.icc
Binary files differ
diff --git a/testbed/testcms2.c b/testbed/testcms2.c
index 01deae2..f4e70bb 100644
--- a/testbed/testcms2.c
+++ b/testbed/testcms2.c
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2010 Marti Maria Saguer
+// Copyright (c) 1998-2014 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"),
@@ -24,11 +24,8 @@
//---------------------------------------------------------------------------------
//
-#ifdef _MSC_VER
-# define _CRT_SECURE_NO_WARNINGS 1
-#endif
-#include "lcms2_internal.h"
+#include "testcms2.h"
// On Visual Studio, use debug CRT
#ifdef _MSC_VER
@@ -55,7 +52,6 @@ static cmsInt32Number SimultaneousErrors;
#define cmsmin(a, b) (((a) < (b)) ? (a) : (b))
// Die, a fatal unexpected error is detected!
-static
void Die(const char* Reason)
{
printf("\n\nArrrgggg!!: %s!\n\n", Reason);
@@ -75,6 +71,7 @@ static cmsUInt32Number SingleHit, MaxAllocated=0, TotalMemory=0;
typedef struct {
cmsUInt32Number KeepSize;
cmsContext WhoAllocated;
+ cmsUInt32Number DontCheck;
union {
cmsUInt64Number HiSparc;
@@ -100,7 +97,7 @@ cmsContext DbgThread(void)
{
static cmsUInt32Number n = 1;
- return (cmsContext) n++;
+ return (cmsContext) (n++ % 0xff0);
}
// The allocate routine
@@ -126,10 +123,12 @@ void* DebugMalloc(cmsContext ContextID, cmsUInt32Number size)
blk ->KeepSize = size;
blk ->WhoAllocated = ContextID;
+ blk ->DontCheck = 0;
return (void*) ((cmsUInt8Number*) blk + SIZE_OF_MEM_HEADER);
}
+
// The free routine
static
void DebugFree(cmsContext ContextID, void *Ptr)
@@ -143,13 +142,14 @@ void DebugFree(cmsContext ContextID, void *Ptr)
blk = (_cmsMemoryBlock*) (((cmsUInt8Number*) Ptr) - SIZE_OF_MEM_HEADER);
TotalMemory -= blk ->KeepSize;
- if (blk ->WhoAllocated != ContextID) {
+ if (blk ->WhoAllocated != ContextID && !blk->DontCheck) {
Die("Trying to free memory allocated by a different thread");
}
free(blk);
}
+
// Reallocate, just a malloc, a copy and a free in this case.
static
void * DebugRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize)
@@ -177,11 +177,68 @@ void DebugMemPrintTotals(void)
printf("Allocated = %u MaxAlloc = %u Single block hit = %u\n", TotalMemory, MaxAllocated, SingleHit);
}
+
+void DebugMemDontCheckThis(void *Ptr)
+{
+ _cmsMemoryBlock* blk = (_cmsMemoryBlock*) (((cmsUInt8Number*) Ptr) - SIZE_OF_MEM_HEADER);
+
+ blk ->DontCheck = 1;
+}
+
+
+// Memory string
+static
+const char* MemStr(cmsUInt32Number size)
+{
+ static char Buffer[1024];
+
+ if (size > 1024*1024) {
+ sprintf(Buffer, "%g Mb", (cmsFloat64Number) size / (1024.0*1024.0));
+ }
+ else
+ if (size > 1024) {
+ sprintf(Buffer, "%g Kb", (cmsFloat64Number) size / 1024.0);
+ }
+ else
+ sprintf(Buffer, "%g bytes", (cmsFloat64Number) size);
+
+ return Buffer;
+}
+
+
+void TestMemoryLeaks(cmsBool ok)
+{
+ if (TotalMemory > 0)
+ printf("Ok, but %s are left!\n", MemStr(TotalMemory));
+ else {
+ if (ok) printf("Ok.\n");
+ }
+}
+
// Here we go with the plug-in declaration
-static cmsPluginMemHandler DebugMemHandler = {{ cmsPluginMagicNumber, 2000, cmsPluginMemHandlerSig, NULL },
+static cmsPluginMemHandler DebugMemHandler = {{ cmsPluginMagicNumber, 2060, cmsPluginMemHandlerSig, NULL },
DebugMalloc, DebugFree, DebugRealloc, NULL, NULL, NULL };
-// Utils -------------------------------------------------------------------------------------
+// Returnds a pointer to the memhandler plugin
+void* PluginMemHandler(void)
+{
+ return (void*) &DebugMemHandler;
+}
+
+cmsContext WatchDogContext(void* usr)
+{
+ cmsContext ctx;
+
+ ctx = cmsCreateContext(&DebugMemHandler, usr);
+
+ if (ctx == NULL)
+ Die("Unable to create memory managed context");
+
+ DebugMemDontCheckThis(ctx);
+ return ctx;
+}
+
+
static
void FatalErrorQuit(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
@@ -190,18 +247,29 @@ void FatalErrorQuit(cmsContext ContextID, cmsUInt32Number ErrorCode, const char
cmsUNUSED_PARAMETER(ContextID);
cmsUNUSED_PARAMETER(ErrorCode);
+}
+
+void ResetFatalError(void)
+{
+ cmsSetLogErrorHandler(FatalErrorQuit);
}
+
// Print a dot for gauging
-static
void Dot(void)
{
fprintf(stdout, "."); fflush(stdout);
}
+void Say(const char* str)
+{
+ fprintf(stdout, "%s", str); fflush(stdout);
+}
+
+
// Keep track of the reason to fail
-static
+
void Fail(const char* frm, ...)
{
va_list args;
@@ -211,7 +279,7 @@ void Fail(const char* frm, ...)
}
// Keep track of subtest
-static
+
void SubTest(const char* frm, ...)
{
va_list args;
@@ -222,27 +290,6 @@ void SubTest(const char* frm, ...)
va_end(args);
}
-
-// Memory string
-static
-const char* MemStr(cmsUInt32Number size)
-{
- static char Buffer[1024];
-
- if (size > 1024*1024) {
- sprintf(Buffer, "%g Mb", (cmsFloat64Number) size / (1024.0*1024.0));
- }
- else
- if (size > 1024) {
- sprintf(Buffer, "%g Kb", (cmsFloat64Number) size / 1024.0);
- }
- else
- sprintf(Buffer, "%g bytes", (cmsFloat64Number) size);
-
- return Buffer;
-}
-
-
// The check framework
static
void Check(const char* Title, TestFn Fn)
@@ -259,10 +306,8 @@ void Check(const char* Title, TestFn Fn)
if (Fn() && !TrappedError) {
// It is a good place to check memory
- if (TotalMemory > 0)
- printf("Ok, but %s are left!\n", MemStr(TotalMemory));
- else
- printf("Ok.\n");
+ TestMemoryLeaks(TRUE);
+
}
else {
printf("FAIL!\n");
@@ -571,11 +616,8 @@ cmsInt32Number OneVirtual(cmsHPROFILE h, const char* SubTestTxt, const char* Fil
h = cmsOpenProfileFromFile(FileName, "r");
if (h == NULL) return 0;
-
- // Do some teste....
-
+
cmsCloseProfile(h);
-
return 1;
}
@@ -744,7 +786,7 @@ cmsInt32Number CheckQuickFloor(void)
(_cmsQuickFloor(-32767.1) != -32768)) {
Fail("\nOOOPPSS! _cmsQuickFloor() does not work as expected in your machine!\n\n"
- "Please, edit lcms.h and uncomment the CMS_DONT_USE_FAST_FLOOR toggle.\n");
+ "Please, edit lcms2.h and uncomment the CMS_DONT_USE_FAST_FLOOR toggle.\n");
return 0;
}
@@ -763,7 +805,7 @@ cmsInt32Number CheckQuickFloorWord(void)
if (_cmsQuickFloorWord((cmsFloat64Number) i + 0.1234) != i) {
Fail("\nOOOPPSS! _cmsQuickFloorWord() does not work as expected in your machine!\n\n"
- "Please, edit lcms.h and uncomment the CMS_DONT_USE_FAST_FLOOR toggle.\n");
+ "Please, edit lcms2.h and uncomment the CMS_DONT_USE_FAST_FLOOR toggle.\n");
return 0;
}
}
@@ -787,7 +829,6 @@ cmsInt32Number CheckQuickFloorWord(void)
static cmsFloat64Number MaxErr;
static cmsFloat64Number AllowedErr = FIXED_PRECISION_15_16;
-static
cmsBool IsGoodVal(const char *title, cmsFloat64Number in, cmsFloat64Number out, cmsFloat64Number max)
{
cmsFloat64Number Err = fabs(in - out);
@@ -803,19 +844,18 @@ cmsBool IsGoodVal(const char *title, cmsFloat64Number in, cmsFloat64Number out,
return TRUE;
}
-static
+
cmsBool IsGoodFixed15_16(const char *title, cmsFloat64Number in, cmsFloat64Number out)
{
return IsGoodVal(title, in, out, FIXED_PRECISION_15_16);
}
-static
+
cmsBool IsGoodFixed8_8(const char *title, cmsFloat64Number in, cmsFloat64Number out)
{
return IsGoodVal(title, in, out, FIXED_PRECISION_8_8);
}
-static
cmsBool IsGoodWord(const char *title, cmsUInt16Number in, cmsUInt16Number out)
{
if ((abs(in - out) > 0 )) {
@@ -827,7 +867,6 @@ cmsBool IsGoodWord(const char *title, cmsUInt16Number in, cmsUInt16Number out)
return TRUE;
}
-static
cmsBool IsGoodWordPrec(const char *title, cmsUInt16Number in, cmsUInt16Number out, cmsUInt16Number maxErr)
{
if ((abs(in - out) > maxErr )) {
@@ -891,6 +930,59 @@ cmsInt32Number CheckFixedPoint8_8(void)
return 1;
}
+// D50 constant --------------------------------------------------------------------------------------------
+
+static
+cmsInt32Number CheckD50Roundtrip(void)
+{
+ cmsFloat64Number cmsD50X_2 = 0.96420288;
+ cmsFloat64Number cmsD50Y_2 = 1.0;
+ cmsFloat64Number cmsD50Z_2 = 0.82490540;
+
+ cmsS15Fixed16Number xe = _cmsDoubleTo15Fixed16(cmsD50X);
+ cmsS15Fixed16Number ye = _cmsDoubleTo15Fixed16(cmsD50Y);
+ cmsS15Fixed16Number ze = _cmsDoubleTo15Fixed16(cmsD50Z);
+
+ cmsFloat64Number x = _cms15Fixed16toDouble(xe);
+ cmsFloat64Number y = _cms15Fixed16toDouble(ye);
+ cmsFloat64Number z = _cms15Fixed16toDouble(ze);
+
+ double dx = fabs(cmsD50X - x);
+ double dy = fabs(cmsD50Y - y);
+ double dz = fabs(cmsD50Z - z);
+
+ double euc = sqrt(dx*dx + dy*dy + dz* dz);
+
+ if (euc > 1E-5) {
+
+ Fail("D50 roundtrip |err| > (%f) ", euc);
+ return 0;
+ }
+
+ xe = _cmsDoubleTo15Fixed16(cmsD50X_2);
+ ye = _cmsDoubleTo15Fixed16(cmsD50Y_2);
+ ze = _cmsDoubleTo15Fixed16(cmsD50Z_2);
+
+ x = _cms15Fixed16toDouble(xe);
+ y = _cms15Fixed16toDouble(ye);
+ z = _cms15Fixed16toDouble(ze);
+
+ dx = fabs(cmsD50X_2 - x);
+ dy = fabs(cmsD50Y_2 - y);
+ dz = fabs(cmsD50Z_2 - z);
+
+ euc = sqrt(dx*dx + dy*dy + dz* dz);
+
+ if (euc > 1E-5) {
+
+ Fail("D50 roundtrip |err| > (%f) ", euc);
+ return 0;
+ }
+
+
+ return 1;
+}
+
// Linear interpolation -----------------------------------------------------------------------------------------------
// Since prime factors of 65535 (FFFF) are,
@@ -3664,7 +3756,7 @@ Error:
static cmsBool FormatterFailed;
static
-void CheckSingleFormatter16(cmsUInt32Number Type, const char* Text)
+void CheckSingleFormatter16(cmsContext id, cmsUInt32Number Type, const char* Text)
{
cmsUInt16Number Values[cmsMAXCHANNELS];
cmsUInt8Number Buffer[1024];
@@ -3679,16 +3771,16 @@ void CheckSingleFormatter16(cmsUInt32Number Type, const char* Text)
info.OutputFormat = info.InputFormat = Type;
// Go forth and back
- f = _cmsGetFormatter(Type, cmsFormatterInput, CMS_PACK_FLAGS_16BITS);
- b = _cmsGetFormatter(Type, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS);
+ f = _cmsGetFormatter(id, Type, cmsFormatterInput, CMS_PACK_FLAGS_16BITS);
+ b = _cmsGetFormatter(id, Type, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS);
if (f.Fmt16 == NULL || b.Fmt16 == NULL) {
Fail("no formatter for %s", Text);
FormatterFailed = TRUE;
// Useful for debug
- f = _cmsGetFormatter(Type, cmsFormatterInput, CMS_PACK_FLAGS_16BITS);
- b = _cmsGetFormatter(Type, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS);
+ f = _cmsGetFormatter(id, Type, cmsFormatterInput, CMS_PACK_FLAGS_16BITS);
+ b = _cmsGetFormatter(id, Type, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS);
return;
}
@@ -3733,7 +3825,7 @@ void CheckSingleFormatter16(cmsUInt32Number Type, const char* Text)
}
}
-#define C(a) CheckSingleFormatter16(a, #a)
+#define C(a) CheckSingleFormatter16(0, a, #a)
// Check all formatters
@@ -3931,16 +4023,16 @@ void CheckSingleFormatterFloat(cmsUInt32Number Type, const char* Text)
info.OutputFormat = info.InputFormat = Type;
// Go forth and back
- f = _cmsGetFormatter(Type, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT);
- b = _cmsGetFormatter(Type, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT);
+ f = _cmsGetFormatter(0, Type, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT);
+ b = _cmsGetFormatter(0, Type, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT);
if (f.FmtFloat == NULL || b.FmtFloat == NULL) {
Fail("no formatter for %s", Text);
FormatterFailed = TRUE;
// Useful for debug
- f = _cmsGetFormatter(Type, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT);
- b = _cmsGetFormatter(Type, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT);
+ f = _cmsGetFormatter(0, Type, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT);
+ b = _cmsGetFormatter(0, Type, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT);
return;
}
@@ -4017,8 +4109,10 @@ cmsInt32Number CheckFormattersFloat(void)
C( TYPE_BGRA_HALF_FLT );
C( TYPE_ABGR_HALF_FLT );
+ C( TYPE_XYZ_FLT );
+
- return FormatterFailed == 0 ? 1 : 0;
+ return FormatterFailed == 0 ? 1 : 0;
}
#undef C
@@ -5215,7 +5309,6 @@ cmsInt32Number CheckProfileCreation(void)
SubTest("Tags holding ICC viewing conditions");
if (!CheckICCViewingConditions(Pass, h)) return 0;
-
SubTest("VCGT tags");
if (!CheckVCGT(Pass, h)) return 0;
@@ -5249,6 +5342,44 @@ cmsInt32Number CheckProfileCreation(void)
}
+// Thanks to Christopher James Halse Rogers for the bugfixing and providing this test
+static
+cmsInt32Number CheckVersionHeaderWriting(void)
+{
+ cmsHPROFILE h;
+ int index;
+ float test_versions[] = {
+ 2.3f,
+ 4.08f,
+ 4.09f,
+ 4.3f
+ };
+
+ for (index = 0; index < sizeof(test_versions)/sizeof(test_versions[0]); index++) {
+
+ h = cmsCreateProfilePlaceholder(DbgThread());
+ if (h == NULL) return 0;
+
+ cmsSetProfileVersion(h, test_versions[index]);
+
+ cmsSaveProfileToFile(h, "versions.icc");
+ cmsCloseProfile(h);
+
+ h = cmsOpenProfileFromFileTHR(DbgThread(), "versions.icc", "r");
+
+ // Only the first 3 digits are significant
+ if (fabs(cmsGetProfileVersion(h) - test_versions[index]) > 0.005) {
+ Fail("Version failed to round-trip: wrote %.2f, read %.2f",
+ test_versions[index], cmsGetProfileVersion(h));
+ return 0;
+ }
+
+ cmsCloseProfile(h);
+ remove("versions.icc");
+ }
+ return 1;
+}
+
// Error reporting -------------------------------------------------------------------------------------------------------
@@ -6448,7 +6579,7 @@ cmsInt32Number CheckGamutCheck(void)
SubTest("Gamut check on 16 bits");
- xform = cmsCreateProofingTransformTHR(DbgThread(), hAbove, TYPE_RGB_16, hAbove, TYPE_RGB_16, hAbove,
+ xform = cmsCreateProofingTransformTHR(DbgThread(), hAbove, TYPE_RGB_16, hAbove, TYPE_RGB_16, hSRGB,
INTENT_RELATIVE_COLORIMETRIC, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_GAMUTCHECK);
cmsCloseProfile(hSRGB);
@@ -7484,6 +7615,84 @@ cmsInt32Number CheckReadRAW(void)
}
+static
+cmsInt32Number CheckMeta(void)
+{
+ char *data;
+ cmsHANDLE dict;
+ cmsHPROFILE p;
+ cmsUInt32Number clen;
+ FILE *fp;
+ int rc;
+
+ /* open file */
+ p = cmsOpenProfileFromFile("ibm-t61.icc", "r");
+ if (p == NULL) return 0;
+
+ /* read dictionary, but don't do anything with the value */
+ //COMMENT OUT THE NEXT TWO LINES AND IT WORKS FINE!!!
+ dict = cmsReadTag(p, cmsSigMetaTag);
+ if (dict == NULL) return 0;
+
+ /* serialize profile to memory */
+ rc = cmsSaveProfileToMem(p, NULL, &clen);
+ if (!rc) return 0;
+
+ data = (char*) malloc(clen);
+ rc = cmsSaveProfileToMem(p, data, &clen);
+ if (!rc) return 0;
+
+ /* write the memory blob to a file */
+ //NOTE: The crash does not happen if cmsSaveProfileToFile() is used */
+ fp = fopen("new.icc", "wb");
+ fwrite(data, 1, clen, fp);
+ fclose(fp);
+ free(data);
+
+ cmsCloseProfile(p);
+
+ /* open newly created file and read metadata */
+ p = cmsOpenProfileFromFile("new.icc", "r");
+ //ERROR: Bad dictionary Name/Value
+ //ERROR: Corrupted tag 'meta'
+ //test: test.c:59: main: Assertion `dict' failed.
+ dict = cmsReadTag(p, cmsSigMetaTag);
+ if (dict == NULL) return 0;
+
+ cmsCloseProfile(p);
+ return 1;
+}
+
+
+// Bug on applying null transforms on floating point buffers
+static
+cmsInt32Number CheckFloatNULLxform(void)
+{
+ int i;
+ cmsFloat32Number in[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ cmsFloat32Number out[10];
+
+ cmsHTRANSFORM xform = cmsCreateTransform(NULL, TYPE_GRAY_FLT, NULL, TYPE_GRAY_FLT, INTENT_PERCEPTUAL, cmsFLAGS_NULLTRANSFORM);
+
+ if (xform == NULL) {
+ Fail("Unable to create float null transform");
+ return 0;
+ }
+
+ cmsDoTransform(xform, in, out, 10);
+
+ cmsDeleteTransform(xform);
+ for (i=0; i < 10; i++) {
+
+ if (!IsGoodVal("float nullxform", in[i], out[i], 0.001)) {
+
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
// --------------------------------------------------------------------------------------------------
// P E R F O R M A N C E C H E C K S
@@ -7513,6 +7722,9 @@ void PrintPerformance(cmsUInt32Number Bytes, cmsUInt32Number SizeOfPixel, cmsFlo
}
+
+
+
static
void SpeedTest16bits(const char * Title, cmsHPROFILE hlcmsProfileIn, cmsHPROFILE hlcmsProfileOut, cmsInt32Number Intent)
{
@@ -7880,271 +8092,23 @@ void PrintSupportedIntents(void)
printf("\n");
}
-// ZOO checks ------------------------------------------------------------------------------------------------------------
-
-
-#ifdef CMS_IS_WINDOWS_
-
-static char ZOOfolder[cmsMAX_PATH] = "c:\\colormaps\\";
-static char ZOOwrite[cmsMAX_PATH] = "c:\\colormaps\\write\\";
-static char ZOORawWrite[cmsMAX_PATH] = "c:\\colormaps\\rawwrite\\";
-
-
-// Read all tags on a profile given by its handle
-static
-void ReadAllTags(cmsHPROFILE h)
-{
- cmsInt32Number i, n;
- cmsTagSignature sig;
-
- n = cmsGetTagCount(h);
- for (i=0; i < n; i++) {
-
- sig = cmsGetTagSignature(h, i);
- if (cmsReadTag(h, sig) == NULL) return;
- }
-}
-
-
-// Read all tags on a profile given by its handle
-static
-void ReadAllRAWTags(cmsHPROFILE h)
-{
- cmsInt32Number i, n;
- cmsTagSignature sig;
- cmsInt32Number len;
-
- n = cmsGetTagCount(h);
- for (i=0; i < n; i++) {
-
- sig = cmsGetTagSignature(h, i);
- len = cmsReadRawTag(h, sig, NULL, 0);
- }
-}
-
-
-static
-void PrintInfo(cmsHPROFILE h, cmsInfoType Info)
-{
- wchar_t* text;
- cmsInt32Number len;
- cmsContext id = DbgThread();
-
- len = cmsGetProfileInfo(h, Info, "en", "US", NULL, 0);
- if (len == 0) return;
-
- text = _cmsMalloc(id, len);
- cmsGetProfileInfo(h, Info, "en", "US", text, len);
-
- wprintf(L"%s\n", text);
- _cmsFree(id, text);
-}
-
-
-static
-void PrintAllInfos(cmsHPROFILE h)
-{
- PrintInfo(h, cmsInfoDescription);
- PrintInfo(h, cmsInfoManufacturer);
- PrintInfo(h, cmsInfoModel);
- PrintInfo(h, cmsInfoCopyright);
- printf("\n\n");
-}
-
-static
-void ReadAllLUTS(cmsHPROFILE h)
-{
- cmsPipeline* a;
- cmsCIEXYZ Black;
-
- a = _cmsReadInputLUT(h, INTENT_PERCEPTUAL);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadInputLUT(h, INTENT_RELATIVE_COLORIMETRIC);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadInputLUT(h, INTENT_SATURATION);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadInputLUT(h, INTENT_ABSOLUTE_COLORIMETRIC);
- if (a) cmsPipelineFree(a);
-
-
- a = _cmsReadOutputLUT(h, INTENT_PERCEPTUAL);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadOutputLUT(h, INTENT_RELATIVE_COLORIMETRIC);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadOutputLUT(h, INTENT_SATURATION);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadOutputLUT(h, INTENT_ABSOLUTE_COLORIMETRIC);
- if (a) cmsPipelineFree(a);
-
-
- a = _cmsReadDevicelinkLUT(h, INTENT_PERCEPTUAL);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadDevicelinkLUT(h, INTENT_RELATIVE_COLORIMETRIC);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadDevicelinkLUT(h, INTENT_SATURATION);
- if (a) cmsPipelineFree(a);
-
- a = _cmsReadDevicelinkLUT(h, INTENT_ABSOLUTE_COLORIMETRIC);
- if (a) cmsPipelineFree(a);
-
-
- cmsDetectDestinationBlackPoint(&Black, h, INTENT_PERCEPTUAL, 0);
- cmsDetectDestinationBlackPoint(&Black, h, INTENT_RELATIVE_COLORIMETRIC, 0);
- cmsDetectDestinationBlackPoint(&Black, h, INTENT_SATURATION, 0);
- cmsDetectDestinationBlackPoint(&Black, h, INTENT_ABSOLUTE_COLORIMETRIC, 0);
- cmsDetectTAC(h);
-}
-
-// Check one specimen in the ZOO
-
-static
-cmsInt32Number CheckSingleSpecimen(const char* Profile)
-{
- char BuffSrc[256];
- char BuffDst[256];
- cmsHPROFILE h;
-
- sprintf(BuffSrc, "%s%s", ZOOfolder, Profile);
- sprintf(BuffDst, "%s%s", ZOOwrite, Profile);
-
- h = cmsOpenProfileFromFile(BuffSrc, "r");
- if (h == NULL) return 0;
-
- printf("%s\n", Profile);
- PrintAllInfos(h);
- ReadAllTags(h);
- // ReadAllRAWTags(h);
- ReadAllLUTS(h);
-
- cmsSaveProfileToFile(h, BuffDst);
- cmsCloseProfile(h);
-
- h = cmsOpenProfileFromFile(BuffDst, "r");
- if (h == NULL) return 0;
- ReadAllTags(h);
-
-
- cmsCloseProfile(h);
-
- return 1;
-}
-
-static
-cmsInt32Number CheckRAWSpecimen(const char* Profile)
-{
- char BuffSrc[256];
- char BuffDst[256];
- cmsHPROFILE h;
-
- sprintf(BuffSrc, "%s%s", ZOOfolder, Profile);
- sprintf(BuffDst, "%s%s", ZOORawWrite, Profile);
-
- h = cmsOpenProfileFromFile(BuffSrc, "r");
- if (h == NULL) return 0;
-
- ReadAllTags(h);
- ReadAllRAWTags(h);
- cmsSaveProfileToFile(h, BuffDst);
- cmsCloseProfile(h);
-
- h = cmsOpenProfileFromFile(BuffDst, "r");
- if (h == NULL) return 0;
- ReadAllTags(h);
- cmsCloseProfile(h);
-
- return 1;
-}
-
-
-static
-void CheckProfileZOO(void)
-{
-
- struct _finddata_t c_file;
- intptr_t hFile;
-
- cmsSetLogErrorHandler(NULL);
-
- if ( (hFile = _findfirst("c:\\colormaps\\*.*", &c_file)) == -1L )
- printf("No files in current directory");
- else
- {
- do
- {
-
- printf("%s\n", c_file.name);
- if (strcmp(c_file.name, ".") != 0 &&
- strcmp(c_file.name, "..") != 0) {
-
- CheckSingleSpecimen( c_file.name);
- CheckRAWSpecimen( c_file.name);
-
- if (TotalMemory > 0)
- printf("Ok, but %s are left!\n", MemStr(TotalMemory));
- else
- printf("Ok.\n");
-
- }
-
- } while ( _findnext(hFile, &c_file) == 0 );
-
- _findclose(hFile);
- }
-
- cmsSetLogErrorHandler(FatalErrorQuit);
-}
-
-#endif
-
-
-#if 0
-#define TYPE_709 709
-static double Rec709Math(int Type, const double Params[], double R)
-{ double Fun;
-
-switch (Type)
-{
-case 709:
-
-if (R <= (Params[3]*Params[4])) Fun = R / Params[3];
-else Fun = pow(((R - Params[2])/Params[1]), Params[0]);
-break;
-case -709:
-if (R <= Params[4]) Fun = R * Params[3];
-else Fun = Params[1] * pow(R, (1/Params[0])) + Params[2];
-break;
-}
-return Fun;
-}
+// ---------------------------------------------------------------------------------------
-// Add nonstandard TRC curves -> Rec709
-cmsPluginParametricCurves NewCurvePlugin = {
-{ cmsPluginMagicNumber, 2000, cmsPluginParametricCurveSig, NULL },
-1, {TYPE_709}, {5}, Rec709Math};
+#ifdef LCMS_FAST_EXTENSIONS
+ void* cmsFast8Bitextensions(void);
#endif
-
-
-
-// ---------------------------------------------------------------------------------------
-
int main(int argc, char* argv[])
{
cmsInt32Number Exhaustive = 0;
cmsInt32Number DoSpeedTests = 1;
cmsInt32Number DoCheckTests = 1;
+ cmsInt32Number DoPluginTests = 1;
+ cmsInt32Number DoZooTests = 0;
#ifdef _MSC_VER
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
@@ -8158,6 +8122,12 @@ int main(int argc, char* argv[])
printf("Running exhaustive tests (will take a while...)\n\n");
}
+#ifdef LCMS_FAST_EXTENSIONS
+ printf("Installing fast 8 bit extension ...");
+ cmsPlugin(cmsFast8Bitextensions());
+ printf("done.\n");
+#endif
+
printf("Installing debug memory plug-in ... ");
cmsPlugin(&DebugMemHandler);
printf("done.\n");
@@ -8166,26 +8136,23 @@ int main(int argc, char* argv[])
cmsSetLogErrorHandler(FatalErrorQuit);
printf("done.\n");
-#ifdef CMS_IS_WINDOWS_
- // CheckProfileZOO();
-#endif
PrintSupportedIntents();
-
-
- // Create utility profiles
- Check("Creation of test profiles", CreateTestProfiles);
-
- if (DoCheckTests)
- {
Check("Base types", CheckBaseTypes);
Check("endianess", CheckEndianess);
Check("quick floor", CheckQuickFloor);
Check("quick floor word", CheckQuickFloorWord);
Check("Fixed point 15.16 representation", CheckFixedPoint15_16);
Check("Fixed point 8.8 representation", CheckFixedPoint8_8);
+ Check("D50 roundtrip", CheckD50Roundtrip);
+
+ // Create utility profiles
+ if (DoCheckTests || DoSpeedTests)
+ Check("Creation of test profiles", CreateTestProfiles);
+ if (DoCheckTests) {
+
// Forward 1D interpolation
Check("1D interpolation in 2pt tables", Check1DLERP2);
Check("1D interpolation in 3pt tables", Check1DLERP3);
@@ -8303,7 +8270,7 @@ int main(int argc, char* argv[])
// Profile I/O (this one is huge!)
Check("Profile creation", CheckProfileCreation);
-
+ Check("Header version", CheckVersionHeaderWriting);
// Error reporting
Check("Error reporting on bad profiles", CheckErrReportingOnBadProfiles);
@@ -8358,18 +8325,44 @@ int main(int argc, char* argv[])
Check("Floating Point sampled curve with non-zero start", CheckFloatSamples);
Check("Floating Point segmented curve with short sampled segement", CheckFloatSegments);
Check("Read RAW portions", CheckReadRAW);
+ Check("Check MetaTag", CheckMeta);
+ Check("Null transform on floats", CheckFloatNULLxform);
+ }
+
+ if (DoPluginTests)
+ {
+#ifndef CMS_CONTEXT_IN_LEGACY_MODE
+ Check("Context memory handling", CheckAllocContext);
+ Check("Simple context functionality", CheckSimpleContext);
+ Check("Alarm codes context", CheckAlarmColorsContext);
+ Check("Adaptation state context", CheckAdaptationStateContext);
+ Check("1D interpolation plugin", CheckInterp1DPlugin);
+ Check("3D interpolation plugin", CheckInterp3DPlugin);
+ Check("Parametric curve plugin", CheckParametricCurvePlugin);
+ Check("Formatters plugin", CheckFormattersPlugin);
+ Check("Tag type plugin", CheckTagTypePlugin);
+ Check("MPE type plugin", CheckMPEPlugin);
+ Check("Optimization plugin", CheckOptimizationPlugin);
+ Check("Rendering intent plugin", CheckIntentPlugin);
+ Check("Full transform plugin", CheckTransformPlugin);
+ Check("Mutex plugin", CheckMutexPlugin);
+#endif
}
if (DoSpeedTests)
SpeedTest();
+ if (DoZooTests)
+ CheckProfileZOO();
+
DebugMemPrintTotals();
cmsUnregisterPlugins();
// Cleanup
- RemoveTestProfiles();
+ if (DoCheckTests || DoSpeedTests)
+ RemoveTestProfiles();
return TotalFail;
}
diff --git a/testbed/testcms2.h b/testbed/testcms2.h
new file mode 100755
index 0000000..a1a69fe
--- /dev/null
+++ b/testbed/testcms2.h
@@ -0,0 +1,84 @@
+//---------------------------------------------------------------------------------
+//
+// Little Color Management System
+// Copyright (c) 1998-2014 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.
+//
+//---------------------------------------------------------------------------------
+//
+
+#ifndef TESTCMS2_H
+#define TESTCMS2_H
+
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS 1
+# include "crtdbg.h"
+# include <io.h>
+#endif
+
+#include "lcms2_internal.h"
+
+#define cmsmin(a, b) (((a) < (b)) ? (a) : (b))
+
+// Used to mark special pointers
+void DebugMemDontCheckThis(void *Ptr);
+
+
+cmsBool IsGoodVal(const char *title, cmsFloat64Number in, cmsFloat64Number out, cmsFloat64Number max);
+cmsBool IsGoodFixed15_16(const char *title, cmsFloat64Number in, cmsFloat64Number out);
+cmsBool IsGoodFixed8_8(const char *title, cmsFloat64Number in, cmsFloat64Number out);
+cmsBool IsGoodWord(const char *title, cmsUInt16Number in, cmsUInt16Number out);
+cmsBool IsGoodWordPrec(const char *title, cmsUInt16Number in, cmsUInt16Number out, cmsUInt16Number maxErr);
+
+void* PluginMemHandler(void);
+cmsContext WatchDogContext(void* usr);
+
+void ResetFatalError(void);
+void Die(const char* Reason);
+void Dot(void);
+void Fail(const char* frm, ...);
+void SubTest(const char* frm, ...);
+void TestMemoryLeaks(cmsBool ok);
+void Say(const char* str);
+
+// Plug-in tests
+cmsInt32Number CheckSimpleContext(void);
+cmsInt32Number CheckAllocContext(void);
+cmsInt32Number CheckAlarmColorsContext(void);
+cmsInt32Number CheckAdaptationStateContext(void);
+cmsInt32Number CheckInterp1DPlugin(void);
+cmsInt32Number CheckInterp3DPlugin(void);
+cmsInt32Number CheckParametricCurvePlugin(void);
+cmsInt32Number CheckFormattersPlugin(void);
+cmsInt32Number CheckTagTypePlugin(void);
+cmsInt32Number CheckMPEPlugin(void);
+cmsInt32Number CheckOptimizationPlugin(void);
+cmsInt32Number CheckIntentPlugin(void);
+cmsInt32Number CheckTransformPlugin(void);
+cmsInt32Number CheckMutexPlugin(void);
+
+
+cmsInt32Number CheckOptimizationPluginLeak(void);
+
+// Zoo
+void CheckProfileZOO(void);
+
+#endif
+
diff --git a/testbed/testplugin.c b/testbed/testplugin.c
new file mode 100755
index 0000000..1ba00bc
--- /dev/null
+++ b/testbed/testplugin.c
@@ -0,0 +1,1476 @@
+//---------------------------------------------------------------------------------
+//
+// Little Color Management System
+// Copyright (c) 1998-2014 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 "testcms2.h"
+
+// --------------------------------------------------------------------------------------------------
+// Auxiliar, duplicate a context and mark the block as non-debug because in this case the allocator
+// and deallocator have different context owners
+// --------------------------------------------------------------------------------------------------
+
+static
+cmsContext DupContext(cmsContext src, void* Data)
+{
+ cmsContext cpy = cmsDupContext(src, Data);
+
+ DebugMemDontCheckThis(cpy);
+
+ return cpy;
+}
+
+// --------------------------------------------------------------------------------------------------
+// Simple context functions
+// --------------------------------------------------------------------------------------------------
+
+// Allocation order
+cmsInt32Number CheckAllocContext(void)
+{
+ cmsContext c1, c2, c3, c4;
+
+
+ c1 = cmsCreateContext(NULL, NULL); // This creates a context by using the normal malloc
+ DebugMemDontCheckThis(c1);
+ cmsDeleteContext(c1);
+
+ c2 = cmsCreateContext(PluginMemHandler(), NULL); // This creates a context by using the debug malloc
+ DebugMemDontCheckThis(c2);
+ cmsDeleteContext(c2);
+
+ c1 = cmsCreateContext(NULL, NULL);
+ DebugMemDontCheckThis(c1);
+
+ c2 = cmsCreateContext(PluginMemHandler(), NULL);
+ DebugMemDontCheckThis(c2);
+
+ cmsPluginTHR(c1, PluginMemHandler()); // Now the context have custom allocators
+
+ c3 = DupContext(c1, NULL);
+ c4 = DupContext(c2, NULL);
+
+
+
+ cmsDeleteContext(c1); // Should be deleted by using nomal malloc
+ cmsDeleteContext(c2); // Should be deleted by using debug malloc
+ cmsDeleteContext(c3); // Should be deleted by using nomal malloc
+ cmsDeleteContext(c4); // Should be deleted by using debug malloc
+
+ return 1;
+}
+
+// Test the very basic context capabilities
+cmsInt32Number CheckSimpleContext(void)
+{
+ int a = 1;
+ int b = 32;
+ cmsInt32Number rc = 0;
+
+ cmsContext c1, c2, c3;
+
+ // This function creates a context with a special
+ // memory manager that check allocation
+ c1 = WatchDogContext(&a);
+ cmsDeleteContext(c1);
+
+ c1 = WatchDogContext(&a);
+
+ // Let's check duplication
+ c2 = DupContext(c1, NULL);
+ c3 = DupContext(c2, NULL);
+
+ // User data should have been propagated
+ rc = (*(int*) cmsGetContextUserData(c3)) == 1 ;
+
+ // Free resources
+ cmsDeleteContext(c1);
+ cmsDeleteContext(c2);
+ cmsDeleteContext(c3);
+
+ if (!rc) {
+ Fail("Creation of user data failed");
+ return 0;
+ }
+
+ // Back to create 3 levels of inherance
+ c1 = cmsCreateContext(NULL, &a);
+ DebugMemDontCheckThis(c1);
+
+ c2 = DupContext(c1, NULL);
+ c3 = DupContext(c2, &b);
+
+ rc = (*(int*) cmsGetContextUserData(c3)) == 32 ;
+
+ cmsDeleteContext(c1);
+ cmsDeleteContext(c2);
+ cmsDeleteContext(c3);
+
+ if (!rc) {
+ Fail("Modification of user data failed");
+ return 0;
+ }
+
+ // All seems ok
+ return rc;
+}
+
+
+
+
+// --------------------------------------------------------------------------------------------------
+//Alarm color functions
+// --------------------------------------------------------------------------------------------------
+
+// This function tests the alarm codes across contexts
+cmsInt32Number CheckAlarmColorsContext(void)
+{
+ cmsInt32Number rc = 0;
+ const cmsUInt16Number codes[] = {0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff};
+ cmsUInt16Number out[16];
+ cmsContext c1, c2, c3;
+ int i;
+
+ c1 = WatchDogContext(NULL);
+
+ cmsSetAlarmCodesTHR(c1, codes);
+ c2 = DupContext(c1, NULL);
+ c3 = DupContext(c2, NULL);
+
+ cmsGetAlarmCodesTHR(c3, out);
+
+ rc = 1;
+ for (i=0; i < 16; i++) {
+ if (out[i] != codes[i]) {
+ Fail("Bad alarm code %x != %x", out[i], codes[i]);
+ rc = 0;
+ break;
+ }
+ }
+
+ cmsDeleteContext(c1);
+ cmsDeleteContext(c2);
+ cmsDeleteContext(c3);
+
+ return rc;
+}
+
+
+// --------------------------------------------------------------------------------------------------
+//Adaptation state functions
+// --------------------------------------------------------------------------------------------------
+
+// Similar to the previous, but for adaptation state
+cmsInt32Number CheckAdaptationStateContext(void)
+{
+ cmsInt32Number rc = 0;
+ cmsContext c1, c2, c3;
+ cmsFloat64Number old1, old2;
+
+ old1 = cmsSetAdaptationStateTHR(NULL, -1);
+
+ c1 = WatchDogContext(NULL);
+
+ cmsSetAdaptationStateTHR(c1, 0.7);
+
+ c2 = DupContext(c1, NULL);
+ c3 = DupContext(c2, NULL);
+
+ rc = IsGoodVal("Adaptation state", cmsSetAdaptationStateTHR(c3, -1), 0.7, 0.001);
+
+ cmsDeleteContext(c1);
+ cmsDeleteContext(c2);
+ cmsDeleteContext(c3);
+
+ old2 = cmsSetAdaptationStateTHR(NULL, -1);
+
+ if (old1 != old2) {
+ Fail("Adaptation state has changed");
+ return 0;
+ }
+
+ return rc;
+}
+
+// --------------------------------------------------------------------------------------------------
+// Interpolation plugin check: A fake 1D and 3D interpolation will be used to test the functionality.
+// --------------------------------------------------------------------------------------------------
+
+// This fake interpolation takes always the closest lower node in the interpolation table for 1D
+static
+void Fake1Dfloat(const cmsFloat32Number Value[],
+ cmsFloat32Number Output[],
+ const cmsInterpParams* p)
+{
+ cmsFloat32Number val2;
+ int cell;
+ const cmsFloat32Number* LutTable = (const cmsFloat32Number*) p ->Table;
+
+ // Clip upper values
+ if (Value[0] >= 1.0) {
+ Output[0] = LutTable[p -> Domain[0]];
+ return;
+ }
+
+ val2 = p -> Domain[0] * Value[0];
+ cell = (int) floor(val2);
+ Output[0] = LutTable[cell] ;
+}
+
+// This fake interpolation just uses scrambled negated indexes for output
+static
+void Fake3D16(register const cmsUInt16Number Input[],
+ register cmsUInt16Number Output[],
+ register const struct _cms_interp_struc* p)
+{
+ Output[0] = 0xFFFF - Input[2];
+ Output[1] = 0xFFFF - Input[1];
+ Output[2] = 0xFFFF - Input[0];
+}
+
+// The factory chooses interpolation routines on depending on certain conditions.
+cmsInterpFunction my_Interpolators_Factory(cmsUInt32Number nInputChannels,
+ cmsUInt32Number nOutputChannels,
+ cmsUInt32Number dwFlags)
+{
+ cmsInterpFunction Interpolation;
+ cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
+
+ // Initialize the return to zero as a non-supported mark
+ memset(&Interpolation, 0, sizeof(Interpolation));
+
+ // For 1D to 1D and floating point
+ if (nInputChannels == 1 && nOutputChannels == 1 && IsFloat) {
+
+ Interpolation.LerpFloat = Fake1Dfloat;
+ }
+ else
+ if (nInputChannels == 3 && nOutputChannels == 3 && !IsFloat) {
+
+ // For 3D to 3D and 16 bits
+ Interpolation.Lerp16 = Fake3D16;
+ }
+
+ // Here is the interpolation
+ return Interpolation;
+}
+
+// Interpolation plug-in
+static
+cmsPluginInterpolation InterpPluginSample = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginInterpolationSig, NULL },
+ my_Interpolators_Factory
+};
+
+
+// This is the check code for 1D interpolation plug-in
+cmsInt32Number CheckInterp1DPlugin(void)
+{
+ cmsToneCurve* Sampled1D = NULL;
+ cmsContext ctx = NULL;
+ cmsContext cpy = NULL;
+ const cmsFloat32Number tab[] = { 0.0f, 0.10f, 0.20f, 0.30f, 0.40f, 0.50f, 0.60f, 0.70f, 0.80f, 0.90f, 1.00f }; // A straight line
+
+ // 1st level context
+ ctx = WatchDogContext(NULL);
+ if (ctx == NULL) {
+ Fail("Cannot create context");
+ goto Error;
+ }
+
+ cmsPluginTHR(ctx, &InterpPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ if (cpy == NULL) {
+ Fail("Cannot create context (2)");
+ goto Error;
+ }
+
+ Sampled1D = cmsBuildTabulatedToneCurveFloat(cpy, 11, tab);
+ if (Sampled1D == NULL) {
+ Fail("Cannot create tone curve (1)");
+ goto Error;
+ }
+
+ // Do some interpolations with the plugin
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(Sampled1D, 0.10f), 0.10, 0.01)) goto Error;
+ if (!IsGoodVal("0.13", cmsEvalToneCurveFloat(Sampled1D, 0.13f), 0.10, 0.01)) goto Error;
+ if (!IsGoodVal("0.55", cmsEvalToneCurveFloat(Sampled1D, 0.55f), 0.50, 0.01)) goto Error;
+ if (!IsGoodVal("0.9999", cmsEvalToneCurveFloat(Sampled1D, 0.9999f), 0.90, 0.01)) goto Error;
+
+ cmsFreeToneCurve(Sampled1D);
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+
+ // Now in global context
+ Sampled1D = cmsBuildTabulatedToneCurveFloat(NULL, 11, tab);
+ if (Sampled1D == NULL) {
+ Fail("Cannot create tone curve (2)");
+ goto Error;
+ }
+
+ // Now without the plug-in
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(Sampled1D, 0.10f), 0.10, 0.001)) goto Error;
+ if (!IsGoodVal("0.13", cmsEvalToneCurveFloat(Sampled1D, 0.13f), 0.13, 0.001)) goto Error;
+ if (!IsGoodVal("0.55", cmsEvalToneCurveFloat(Sampled1D, 0.55f), 0.55, 0.001)) goto Error;
+ if (!IsGoodVal("0.9999", cmsEvalToneCurveFloat(Sampled1D, 0.9999f), 0.9999, 0.001)) goto Error;
+
+ cmsFreeToneCurve(Sampled1D);
+ return 1;
+
+Error:
+ if (ctx != NULL) cmsDeleteContext(ctx);
+ if (cpy != NULL) cmsDeleteContext(ctx);
+ if (Sampled1D != NULL) cmsFreeToneCurve(Sampled1D);
+ return 0;
+
+}
+
+// Checks the 3D interpolation
+cmsInt32Number CheckInterp3DPlugin(void)
+{
+
+ cmsPipeline* p;
+ cmsStage* clut;
+ cmsContext ctx;
+ cmsUInt16Number In[3], Out[3];
+ cmsUInt16Number identity[] = {
+
+ 0, 0, 0,
+ 0, 0, 0xffff,
+ 0, 0xffff, 0,
+ 0, 0xffff, 0xffff,
+ 0xffff, 0, 0,
+ 0xffff, 0, 0xffff,
+ 0xffff, 0xffff, 0,
+ 0xffff, 0xffff, 0xffff
+ };
+
+
+ ctx = WatchDogContext(NULL);
+ if (ctx == NULL) {
+ Fail("Cannot create context");
+ return 0;
+ }
+
+
+ cmsPluginTHR(ctx, &InterpPluginSample);
+
+
+ p = cmsPipelineAlloc(ctx, 3, 3);
+ clut = cmsStageAllocCLut16bit(ctx, 2, 3, 3, identity);
+ cmsPipelineInsertStage(p, cmsAT_BEGIN, clut);
+
+ // Do some interpolations with the plugin
+
+ In[0] = 0; In[1] = 0; In[2] = 0;
+ cmsPipelineEval16(In, Out, p);
+
+ if (!IsGoodWord("0", Out[0], 0xFFFF - 0)) goto Error;
+ if (!IsGoodWord("1", Out[1], 0xFFFF - 0)) goto Error;
+ if (!IsGoodWord("2", Out[2], 0xFFFF - 0)) goto Error;
+
+ In[0] = 0x1234; In[1] = 0x5678; In[2] = 0x9ABC;
+ cmsPipelineEval16(In, Out, p);
+
+ if (!IsGoodWord("0", 0xFFFF - 0x9ABC, Out[0])) goto Error;
+ if (!IsGoodWord("1", 0xFFFF - 0x5678, Out[1])) goto Error;
+ if (!IsGoodWord("2", 0xFFFF - 0x1234, Out[2])) goto Error;
+
+ cmsPipelineFree(p);
+ cmsDeleteContext(ctx);
+
+ // Now without the plug-in
+
+ p = cmsPipelineAlloc(NULL, 3, 3);
+ clut = cmsStageAllocCLut16bit(NULL, 2, 3, 3, identity);
+ cmsPipelineInsertStage(p, cmsAT_BEGIN, clut);
+
+ In[0] = 0; In[1] = 0; In[2] = 0;
+ cmsPipelineEval16(In, Out, p);
+
+ if (!IsGoodWord("0", 0, Out[0])) goto Error;
+ if (!IsGoodWord("1", 0, Out[1])) goto Error;
+ if (!IsGoodWord("2", 0, Out[2])) goto Error;
+
+ In[0] = 0x1234; In[1] = 0x5678; In[2] = 0x9ABC;
+ cmsPipelineEval16(In, Out, p);
+
+ if (!IsGoodWord("0", 0x1234, Out[0])) goto Error;
+ if (!IsGoodWord("1", 0x5678, Out[1])) goto Error;
+ if (!IsGoodWord("2", 0x9ABC, Out[2])) goto Error;
+
+ cmsPipelineFree(p);
+ return 1;
+
+Error:
+ cmsPipelineFree(p);
+ return 0;
+
+}
+
+// --------------------------------------------------------------------------------------------------
+// Parametric curve plugin check: sin(x)/cos(x) function will be used to test the functionality.
+// --------------------------------------------------------------------------------------------------
+
+#define TYPE_SIN 1000
+#define TYPE_COS 1010
+#define TYPE_TAN 1020
+#define TYPE_709 709
+
+static cmsFloat64Number my_fns(cmsInt32Number Type,
+ const cmsFloat64Number Params[],
+ cmsFloat64Number R)
+{
+ cmsFloat64Number Val;
+ switch (Type) {
+
+ case TYPE_SIN:
+ Val = Params[0]* sin(R * M_PI);
+ break;
+
+ case -TYPE_SIN:
+ Val = asin(R) / (M_PI * Params[0]);
+ break;
+
+ case TYPE_COS:
+ Val = Params[0]* cos(R * M_PI);
+ break;
+
+ case -TYPE_COS:
+ Val = acos(R) / (M_PI * Params[0]);
+ break;
+
+ default: return -1.0;
+
+ }
+
+ return Val;
+}
+
+static
+cmsFloat64Number my_fns2(cmsInt32Number Type,
+ const cmsFloat64Number Params[],
+ cmsFloat64Number R)
+{
+ cmsFloat64Number Val;
+ switch (Type) {
+
+ case TYPE_TAN:
+ Val = Params[0]* tan(R * M_PI);
+ break;
+
+ case -TYPE_TAN:
+ Val = atan(R) / (M_PI * Params[0]);
+ break;
+
+ default: return -1.0;
+ }
+
+ return Val;
+}
+
+
+static double Rec709Math(int Type, const double Params[], double R)
+{
+ double Fun;
+
+ switch (Type)
+ {
+ case 709:
+
+ if (R <= (Params[3]*Params[4])) Fun = R / Params[3];
+ else Fun = pow(((R - Params[2])/Params[1]), Params[0]);
+ break;
+
+ case -709:
+
+ if (R <= Params[4]) Fun = R * Params[3];
+ else Fun = Params[1] * pow(R, (1/Params[0])) + Params[2];
+ break;
+ }
+ return Fun;
+}
+
+
+// Add nonstandard TRC curves -> Rec709
+
+cmsPluginParametricCurves Rec709Plugin = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginParametricCurveSig, NULL },
+
+ 1, {TYPE_709}, {5}, Rec709Math
+
+};
+
+
+static
+cmsPluginParametricCurves CurvePluginSample = {
+ { cmsPluginMagicNumber, 2060, cmsPluginParametricCurveSig, NULL },
+
+ 2, // nFunctions
+ { TYPE_SIN, TYPE_COS }, // Function Types
+ { 1, 1 }, // ParameterCount
+ my_fns // Evaluator
+};
+
+static
+cmsPluginParametricCurves CurvePluginSample2 = {
+ { cmsPluginMagicNumber, 2060, cmsPluginParametricCurveSig, NULL },
+
+ 1, // nFunctions
+ { TYPE_TAN}, // Function Types
+ { 1 }, // ParameterCount
+ my_fns2 // Evaluator
+};
+
+// --------------------------------------------------------------------------------------------------
+// In this test, the DupContext function will be checked as well
+// --------------------------------------------------------------------------------------------------
+cmsInt32Number CheckParametricCurvePlugin(void)
+{
+ cmsContext ctx = NULL;
+ cmsContext cpy = NULL;
+ cmsContext cpy2 = NULL;
+ cmsToneCurve* sinus;
+ cmsToneCurve* cosinus;
+ cmsToneCurve* tangent;
+ cmsToneCurve* reverse_sinus;
+ cmsToneCurve* reverse_cosinus;
+ cmsFloat64Number scale = 1.0;
+
+
+ ctx = WatchDogContext(NULL);
+
+ cmsPluginTHR(ctx, &CurvePluginSample);
+
+ cpy = DupContext(ctx, NULL);
+
+ cmsPluginTHR(cpy, &CurvePluginSample2);
+
+ cpy2 = DupContext(cpy, NULL);
+
+ cmsPluginTHR(cpy2, &Rec709Plugin);
+
+
+ sinus = cmsBuildParametricToneCurve(cpy, TYPE_SIN, &scale);
+ cosinus = cmsBuildParametricToneCurve(cpy, TYPE_COS, &scale);
+ tangent = cmsBuildParametricToneCurve(cpy, TYPE_TAN, &scale);
+ reverse_sinus = cmsReverseToneCurve(sinus);
+ reverse_cosinus = cmsReverseToneCurve(cosinus);
+
+
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(sinus, 0.10f), sin(0.10 * M_PI) , 0.001)) goto Error;
+ if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(sinus, 0.60f), sin(0.60* M_PI), 0.001)) goto Error;
+ if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(sinus, 0.90f), sin(0.90* M_PI), 0.001)) goto Error;
+
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(cosinus, 0.10f), cos(0.10* M_PI), 0.001)) goto Error;
+ if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(cosinus, 0.60f), cos(0.60* M_PI), 0.001)) goto Error;
+ if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(cosinus, 0.90f), cos(0.90* M_PI), 0.001)) goto Error;
+
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(tangent, 0.10f), tan(0.10* M_PI), 0.001)) goto Error;
+ if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(tangent, 0.60f), tan(0.60* M_PI), 0.001)) goto Error;
+ if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(tangent, 0.90f), tan(0.90* M_PI), 0.001)) goto Error;
+
+
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(reverse_sinus, 0.10f), asin(0.10)/M_PI, 0.001)) goto Error;
+ if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(reverse_sinus, 0.60f), asin(0.60)/M_PI, 0.001)) goto Error;
+ if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(reverse_sinus, 0.90f), asin(0.90)/M_PI, 0.001)) goto Error;
+
+ if (!IsGoodVal("0.10", cmsEvalToneCurveFloat(reverse_cosinus, 0.10f), acos(0.10)/M_PI, 0.001)) goto Error;
+ if (!IsGoodVal("0.60", cmsEvalToneCurveFloat(reverse_cosinus, 0.60f), acos(0.60)/M_PI, 0.001)) goto Error;
+ if (!IsGoodVal("0.90", cmsEvalToneCurveFloat(reverse_cosinus, 0.90f), acos(0.90)/M_PI, 0.001)) goto Error;
+
+ cmsFreeToneCurve(sinus);
+ cmsFreeToneCurve(cosinus);
+ cmsFreeToneCurve(tangent);
+ cmsFreeToneCurve(reverse_sinus);
+ cmsFreeToneCurve(reverse_cosinus);
+
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+ cmsDeleteContext(cpy2);
+
+ return 1;
+
+Error:
+
+ cmsFreeToneCurve(sinus);
+ cmsFreeToneCurve(reverse_sinus);
+ cmsFreeToneCurve(cosinus);
+ cmsFreeToneCurve(reverse_cosinus);
+
+ if (ctx != NULL) cmsDeleteContext(ctx);
+ if (cpy != NULL) cmsDeleteContext(cpy);
+ if (cpy2 != NULL) cmsDeleteContext(cpy2);
+ return 0;
+}
+
+// --------------------------------------------------------------------------------------------------
+// formatters plugin check: 5-6-5 RGB format
+// --------------------------------------------------------------------------------------------------
+
+// We define this special type as 0 bytes not float, and set the upper bit
+
+#define TYPE_RGB_565 (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0) | (1 << 23))
+
+cmsUInt8Number* my_Unroll565(register struct _cmstransform_struct* nfo,
+ register cmsUInt16Number wIn[],
+ register cmsUInt8Number* accum,
+ register cmsUInt32Number Stride)
+{
+ cmsUInt16Number pixel = *(cmsUInt16Number*) accum; // Take whole pixel
+
+ double r = floor(((double) (pixel & 31) * 65535.0) / 31.0 + 0.5);
+ double g = floor((((pixel >> 5) & 63) * 65535.0) / 63.0 + 0.5);
+ double b = floor((((pixel >> 11) & 31) * 65535.0) / 31.0 + 0.5);
+
+ wIn[2] = (cmsUInt16Number) r;
+ wIn[1] = (cmsUInt16Number) g;
+ wIn[0] = (cmsUInt16Number) b;
+
+ return accum + 2;
+}
+
+cmsUInt8Number* my_Pack565(register _cmsTRANSFORM* info,
+ register cmsUInt16Number wOut[],
+ register cmsUInt8Number* output,
+ register cmsUInt32Number Stride)
+{
+
+ register cmsUInt16Number pixel;
+ int r, g, b;
+
+ r = (int) floor(( wOut[2] * 31) / 65535.0 + 0.5);
+ g = (int) floor(( wOut[1] * 63) / 65535.0 + 0.5);
+ b = (int) floor(( wOut[0] * 31) / 65535.0 + 0.5);
+
+
+ pixel = (r & 31) | (( g & 63) << 5) | ((b & 31) << 11);
+
+
+ *(cmsUInt16Number*) output = pixel;
+ return output + 2;
+}
+
+
+cmsFormatter my_FormatterFactory(cmsUInt32Number Type,
+ cmsFormatterDirection Dir,
+ cmsUInt32Number dwFlags)
+{
+ cmsFormatter Result = { NULL };
+
+ if ((Type == TYPE_RGB_565) &&
+ !(dwFlags & CMS_PACK_FLAGS_FLOAT) &&
+ (Dir == cmsFormatterInput)) {
+ Result.Fmt16 = my_Unroll565;
+ }
+ return Result;
+}
+
+
+cmsFormatter my_FormatterFactory2(cmsUInt32Number Type,
+ cmsFormatterDirection Dir,
+ cmsUInt32Number dwFlags)
+{
+ cmsFormatter Result = { NULL };
+
+ if ((Type == TYPE_RGB_565) &&
+ !(dwFlags & CMS_PACK_FLAGS_FLOAT) &&
+ (Dir == cmsFormatterOutput)) {
+ Result.Fmt16 = my_Pack565;
+ }
+ return Result;
+}
+
+static
+cmsPluginFormatters FormattersPluginSample = { {cmsPluginMagicNumber,
+ 2060,
+ cmsPluginFormattersSig,
+ NULL},
+ my_FormatterFactory };
+
+
+
+static
+cmsPluginFormatters FormattersPluginSample2 = { {cmsPluginMagicNumber,
+ 2060,
+ cmsPluginFormattersSig,
+ NULL},
+ my_FormatterFactory2 };
+
+
+cmsInt32Number CheckFormattersPlugin(void)
+{
+ cmsContext ctx = WatchDogContext(NULL);
+ cmsContext cpy;
+ cmsContext cpy2;
+ cmsHTRANSFORM xform;
+ cmsUInt16Number stream[]= { 0xffffU, 0x1234U, 0x0000U, 0x33ddU };
+ cmsUInt16Number result[4];
+ int i;
+
+
+ cmsPluginTHR(ctx, &FormattersPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+
+ cmsPluginTHR(cpy, &FormattersPluginSample2);
+
+ cpy2 = DupContext(cpy, NULL);
+
+ xform = cmsCreateTransformTHR(cpy2, NULL, TYPE_RGB_565, NULL, TYPE_RGB_565, INTENT_PERCEPTUAL, cmsFLAGS_NULLTRANSFORM);
+
+ cmsDoTransform(xform, stream, result, 4);
+
+ cmsDeleteTransform(xform);
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+ cmsDeleteContext(cpy2);
+
+ for (i=0; i < 4; i++)
+ if (stream[i] != result[i]) return 0;
+
+ return 1;
+}
+
+// --------------------------------------------------------------------------------------------------
+// TagTypePlugin plugin check
+// --------------------------------------------------------------------------------------------------
+
+#define SigIntType ((cmsTagTypeSignature) 0x74747448) // 'tttH'
+#define SigInt ((cmsTagSignature) 0x74747448) // 'tttH'
+
+static
+void *Type_int_Read(struct _cms_typehandler_struct* self,
+ cmsIOHANDLER* io,
+ cmsUInt32Number* nItems,
+ cmsUInt32Number SizeOfTag)
+{
+ cmsUInt32Number* Ptr = (cmsUInt32Number*) _cmsMalloc(self ->ContextID, sizeof(cmsUInt32Number));
+ if (Ptr == NULL) return NULL;
+ if (!_cmsReadUInt32Number(io, Ptr)) return NULL;
+ *nItems = 1;
+ return Ptr;
+}
+
+static
+cmsBool Type_int_Write(struct _cms_typehandler_struct* self,
+ cmsIOHANDLER* io,
+ void* Ptr, cmsUInt32Number nItems)
+{
+ return _cmsWriteUInt32Number(io, *(cmsUInt32Number*) Ptr);
+}
+
+static
+void* Type_int_Dup(struct _cms_typehandler_struct* self,
+ const void *Ptr, cmsUInt32Number n)
+{
+ return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsUInt32Number));
+}
+
+void Type_int_Free(struct _cms_typehandler_struct* self,
+ void* Ptr)
+{
+ _cmsFree(self ->ContextID, Ptr);
+}
+
+
+static cmsPluginTag HiddenTagPluginSample = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginTagSig, NULL},
+ SigInt, { 1, 1, { SigIntType }, NULL }
+};
+
+static cmsPluginTagType TagTypePluginSample = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginTagTypeSig, (cmsPluginBase*) &HiddenTagPluginSample},
+ { SigIntType, Type_int_Read, Type_int_Write, Type_int_Dup, Type_int_Free, NULL }
+};
+
+
+cmsInt32Number CheckTagTypePlugin(void)
+{
+ cmsContext ctx = NULL;
+ cmsContext cpy = NULL;
+ cmsContext cpy2 = NULL;
+ cmsHPROFILE h = NULL;
+ cmsUInt32Number myTag = 1234;
+ cmsUInt32Number rc = 0;
+ char* data = NULL;
+ cmsUInt32Number *ptr = NULL;
+ cmsUInt32Number clen = 0;
+
+
+ ctx = WatchDogContext(NULL);
+ cmsPluginTHR(ctx, &TagTypePluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ cpy2 = DupContext(cpy, NULL);
+
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+
+ h = cmsCreateProfilePlaceholder(cpy2);
+ if (h == NULL) {
+ Fail("Create placeholder failed");
+ goto Error;
+ }
+
+
+ if (!cmsWriteTag(h, SigInt, &myTag)) {
+ Fail("Plug-in failed");
+ goto Error;
+ }
+
+ rc = cmsSaveProfileToMem(h, NULL, &clen);
+ if (!rc) {
+ Fail("Fetch mem size failed");
+ goto Error;
+ }
+
+
+ data = (char*) malloc(clen);
+ if (data == NULL) {
+ Fail("malloc failed ?!?");
+ goto Error;
+ }
+
+
+ rc = cmsSaveProfileToMem(h, data, &clen);
+ if (!rc) {
+ Fail("Save to mem failed");
+ goto Error;
+ }
+
+ cmsCloseProfile(h);
+
+ cmsSetLogErrorHandler(NULL);
+ h = cmsOpenProfileFromMem(data, clen);
+ if (h == NULL) {
+ Fail("Open profile failed");
+ goto Error;
+ }
+
+ ptr = (cmsUInt32Number*) cmsReadTag(h, SigInt);
+ if (ptr != NULL) {
+
+ Fail("read tag/context switching failed");
+ goto Error;
+ }
+
+ cmsCloseProfile(h);
+ ResetFatalError();
+
+ h = cmsOpenProfileFromMemTHR(cpy2, data, clen);
+ if (h == NULL) {
+ Fail("Open profile from mem failed");
+ goto Error;
+ }
+
+ // Get rid of data
+ free(data); data = NULL;
+
+ ptr = (cmsUInt32Number*) cmsReadTag(h, SigInt);
+ if (ptr == NULL) {
+ Fail("Read tag/conext switching failed (2)");
+ return 0;
+ }
+
+ rc = (*ptr == 1234);
+
+ cmsCloseProfile(h);
+
+ cmsDeleteContext(cpy2);
+
+ return rc;
+
+Error:
+
+ if (h != NULL) cmsCloseProfile(h);
+ if (ctx != NULL) cmsDeleteContext(ctx);
+ if (cpy != NULL) cmsDeleteContext(cpy);
+ if (cpy2 != NULL) cmsDeleteContext(cpy2);
+ if (data) free(data);
+
+ return 0;
+}
+
+// --------------------------------------------------------------------------------------------------
+// MPE plugin check:
+// --------------------------------------------------------------------------------------------------
+#define SigNegateType ((cmsStageSignature)0x6E202020)
+
+static
+void EvaluateNegate(const cmsFloat32Number In[],
+ cmsFloat32Number Out[],
+ const cmsStage *mpe)
+{
+ Out[0] = 1.0f - In[0];
+ Out[1] = 1.0f - In[1];
+ Out[2] = 1.0f - In[2];
+}
+
+static
+cmsStage* StageAllocNegate(cmsContext ContextID)
+{
+ return _cmsStageAllocPlaceholder(ContextID,
+ SigNegateType, 3, 3, EvaluateNegate,
+ NULL, NULL, NULL);
+}
+
+static
+void *Type_negate_Read(struct _cms_typehandler_struct* self,
+ cmsIOHANDLER* io,
+ cmsUInt32Number* nItems,
+ cmsUInt32Number SizeOfTag)
+{
+ cmsUInt16Number Chans;
+ if (!_cmsReadUInt16Number(io, &Chans)) return NULL;
+ if (Chans != 3) return NULL;
+
+ *nItems = 1;
+ return StageAllocNegate(self -> ContextID);
+}
+
+static
+cmsBool Type_negate_Write(struct _cms_typehandler_struct* self,
+ cmsIOHANDLER* io,
+ void* Ptr, cmsUInt32Number nItems)
+{
+
+ if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
+ return TRUE;
+}
+
+static
+cmsPluginMultiProcessElement MPEPluginSample = {
+
+ {cmsPluginMagicNumber, 2060, cmsPluginMultiProcessElementSig, NULL},
+
+ { (cmsTagTypeSignature) SigNegateType, Type_negate_Read, Type_negate_Write, NULL, NULL, NULL }
+};
+
+
+cmsInt32Number CheckMPEPlugin(void)
+{
+ cmsContext ctx = NULL;
+ cmsContext cpy = NULL;
+ cmsContext cpy2 = NULL;
+ cmsHPROFILE h = NULL;
+ cmsUInt32Number myTag = 1234;
+ cmsUInt32Number rc = 0;
+ char* data = NULL;
+ cmsUInt32Number clen = 0;
+ cmsFloat32Number In[3], Out[3];
+ cmsPipeline* pipe;
+
+ ctx = WatchDogContext(NULL);
+ cmsPluginTHR(ctx, &MPEPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ cpy2 = DupContext(cpy, NULL);
+
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+
+ h = cmsCreateProfilePlaceholder(cpy2);
+ if (h == NULL) {
+ Fail("Create placeholder failed");
+ goto Error;
+ }
+
+ pipe = cmsPipelineAlloc(cpy2, 3, 3);
+ cmsPipelineInsertStage(pipe, cmsAT_BEGIN, StageAllocNegate(cpy2));
+
+
+ In[0] = 0.3f; In[1] = 0.2f; In[2] = 0.9f;
+ cmsPipelineEvalFloat(In, Out, pipe);
+
+ rc = (IsGoodVal("0", Out[0], 1.0-In[0], 0.001) &&
+ IsGoodVal("1", Out[1], 1.0-In[1], 0.001) &&
+ IsGoodVal("2", Out[2], 1.0-In[2], 0.001));
+
+ if (!rc) {
+ Fail("Pipeline failed");
+ goto Error;
+ }
+
+ if (!cmsWriteTag(h, cmsSigDToB3Tag, pipe)) {
+ Fail("Plug-in failed");
+ goto Error;
+ }
+
+ // This cleans the stage as well
+ cmsPipelineFree(pipe);
+
+ rc = cmsSaveProfileToMem(h, NULL, &clen);
+ if (!rc) {
+ Fail("Fetch mem size failed");
+ goto Error;
+ }
+
+
+ data = (char*) malloc(clen);
+ if (data == NULL) {
+ Fail("malloc failed ?!?");
+ goto Error;
+ }
+
+
+ rc = cmsSaveProfileToMem(h, data, &clen);
+ if (!rc) {
+ Fail("Save to mem failed");
+ goto Error;
+ }
+
+ cmsCloseProfile(h);
+
+
+ cmsSetLogErrorHandler(NULL);
+ h = cmsOpenProfileFromMem(data, clen);
+ if (h == NULL) {
+ Fail("Open profile failed");
+ goto Error;
+ }
+
+ pipe = (cmsPipeline*) cmsReadTag(h, cmsSigDToB3Tag);
+ if (pipe != NULL) {
+
+ // Unsupported stage, should fail
+ Fail("read tag/context switching failed");
+ goto Error;
+ }
+
+ cmsCloseProfile(h);
+
+ ResetFatalError();
+
+ h = cmsOpenProfileFromMemTHR(cpy2, data, clen);
+ if (h == NULL) {
+ Fail("Open profile from mem failed");
+ goto Error;
+ }
+
+ // Get rid of data
+ free(data); data = NULL;
+
+ pipe = (cmsPipeline*) cmsReadTag(h, cmsSigDToB3Tag);
+ if (pipe == NULL) {
+ Fail("Read tag/conext switching failed (2)");
+ return 0;
+ }
+
+ // Evaluate for negation
+ In[0] = 0.3f; In[1] = 0.2f; In[2] = 0.9f;
+ cmsPipelineEvalFloat(In, Out, pipe);
+
+ rc = (IsGoodVal("0", Out[0], 1.0-In[0], 0.001) &&
+ IsGoodVal("1", Out[1], 1.0-In[1], 0.001) &&
+ IsGoodVal("2", Out[2], 1.0-In[2], 0.001));
+
+ cmsCloseProfile(h);
+
+ cmsDeleteContext(cpy2);
+
+ return rc;
+
+Error:
+
+ if (h != NULL) cmsCloseProfile(h);
+ if (ctx != NULL) cmsDeleteContext(ctx);
+ if (cpy != NULL) cmsDeleteContext(cpy);
+ if (cpy2 != NULL) cmsDeleteContext(cpy2);
+ if (data) free(data);
+
+ return 0;
+}
+
+
+// --------------------------------------------------------------------------------------------------
+// Optimization plugin check:
+// --------------------------------------------------------------------------------------------------
+
+static
+void FastEvaluateCurves(register const cmsUInt16Number In[],
+ register cmsUInt16Number Out[],
+ register const void* Data)
+{
+ Out[0] = In[0];
+}
+
+static
+cmsBool MyOptimize(cmsPipeline** Lut,
+ cmsUInt32Number Intent,
+ cmsUInt32Number* InputFormat,
+ cmsUInt32Number* OutputFormat,
+ cmsUInt32Number* dwFlags)
+{
+ cmsStage* mpe;
+ _cmsStageToneCurvesData* Data;
+
+ // Only curves in this LUT? All are identities?
+ for (mpe = cmsPipelineGetPtrToFirstStage(*Lut);
+ mpe != NULL;
+ mpe = cmsStageNext(mpe)) {
+
+ if (cmsStageType(mpe) != cmsSigCurveSetElemType) return FALSE;
+
+ // Check for identity
+ Data = (_cmsStageToneCurvesData*) cmsStageData(mpe);
+ if (Data ->nCurves != 1) return FALSE;
+ if (cmsEstimateGamma(Data->TheCurves[0], 0.1) > 1.0) return FALSE;
+
+ }
+
+ *dwFlags |= cmsFLAGS_NOCACHE;
+ _cmsPipelineSetOptimizationParameters(*Lut, FastEvaluateCurves, NULL, NULL, NULL);
+
+ return TRUE;
+}
+
+cmsPluginOptimization OptimizationPluginSample = {
+
+ {cmsPluginMagicNumber, 2060, cmsPluginOptimizationSig, NULL},
+ MyOptimize
+};
+
+
+cmsInt32Number CheckOptimizationPlugin(void)
+{
+ cmsContext ctx = WatchDogContext(NULL);
+ cmsContext cpy;
+ cmsContext cpy2;
+ cmsHTRANSFORM xform;
+ cmsUInt8Number In[]= { 10, 20, 30, 40 };
+ cmsUInt8Number Out[4];
+ cmsToneCurve* Linear;
+ cmsHPROFILE h;
+ int i;
+
+ cmsPluginTHR(ctx, &OptimizationPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ cpy2 = DupContext(cpy, NULL);
+
+ Linear = cmsBuildGamma(cpy2, 1.0);
+ h = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear);
+ cmsFreeToneCurve(Linear);
+
+ xform = cmsCreateTransformTHR(cpy2, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
+ cmsCloseProfile(h);
+
+ cmsDoTransform(xform, In, Out, 4);
+
+ cmsDeleteTransform(xform);
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+ cmsDeleteContext(cpy2);
+
+ for (i=0; i < 4; i++)
+ if (In[i] != Out[i]) return 0;
+
+ return 1;
+}
+
+
+// --------------------------------------------------------------------------------------------------
+// Check the intent plug-in
+// --------------------------------------------------------------------------------------------------
+
+/*
+ This example creates a new rendering intent, at intent number 300, that is identical to perceptual
+ intent for all color spaces but gray to gray transforms, in this case it bypasses the data.
+ Note that it has to clear all occurrences of intent 300 in the intents array to avoid
+ infinite recursion.
+*/
+
+#define INTENT_DECEPTIVE 300
+
+static
+cmsPipeline* MyNewIntent(cmsContext ContextID,
+ cmsUInt32Number nProfiles,
+ cmsUInt32Number TheIntents[],
+ cmsHPROFILE hProfiles[],
+ cmsBool BPC[],
+ cmsFloat64Number AdaptationStates[],
+ cmsUInt32Number dwFlags)
+{
+ cmsPipeline* Result;
+ cmsUInt32Number ICCIntents[256];
+ cmsUInt32Number i;
+
+ for (i=0; i < nProfiles; i++)
+ ICCIntents[i] = (TheIntents[i] == INTENT_DECEPTIVE) ? INTENT_PERCEPTUAL :
+ TheIntents[i];
+
+ if (cmsGetColorSpace(hProfiles[0]) != cmsSigGrayData ||
+ cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigGrayData)
+ return _cmsDefaultICCintents(ContextID, nProfiles,
+ ICCIntents, hProfiles,
+ BPC, AdaptationStates,
+ dwFlags);
+
+ Result = cmsPipelineAlloc(ContextID, 1, 1);
+ if (Result == NULL) return NULL;
+
+ cmsPipelineInsertStage(Result, cmsAT_BEGIN,
+ cmsStageAllocIdentity(ContextID, 1));
+
+ return Result;
+}
+
+static cmsPluginRenderingIntent IntentPluginSample = {
+
+ {cmsPluginMagicNumber, 2060, cmsPluginRenderingIntentSig, NULL},
+
+ INTENT_DECEPTIVE, MyNewIntent, "bypass gray to gray rendering intent"
+};
+
+cmsInt32Number CheckIntentPlugin(void)
+{
+ cmsContext ctx = WatchDogContext(NULL);
+ cmsContext cpy;
+ cmsContext cpy2;
+ cmsHTRANSFORM xform;
+ cmsHPROFILE h1, h2;
+ cmsToneCurve* Linear1;
+ cmsToneCurve* Linear2;
+ cmsUInt8Number In[]= { 10, 20, 30, 40 };
+ cmsUInt8Number Out[4];
+ int i;
+
+ cmsPluginTHR(ctx, &IntentPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ cpy2 = DupContext(cpy, NULL);
+
+ Linear1 = cmsBuildGamma(cpy2, 3.0);
+ Linear2 = cmsBuildGamma(cpy2, 0.1);
+ h1 = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear1);
+ h2 = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear2);
+
+ cmsFreeToneCurve(Linear1);
+ cmsFreeToneCurve(Linear2);
+
+ xform = cmsCreateTransformTHR(cpy2, h1, TYPE_GRAY_8, h2, TYPE_GRAY_8, INTENT_DECEPTIVE, 0);
+ cmsCloseProfile(h1); cmsCloseProfile(h2);
+
+ cmsDoTransform(xform, In, Out, 4);
+
+ cmsDeleteTransform(xform);
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+ cmsDeleteContext(cpy2);
+
+ for (i=0; i < 4; i++)
+ if (Out[i] != In[i]) return 0;
+
+ return 1;
+}
+
+
+// --------------------------------------------------------------------------------------------------
+// Check the full transform plug-in
+// --------------------------------------------------------------------------------------------------
+
+// This is a sample intent that only works for gray8 as output, and always returns '42'
+static
+void TrancendentalTransform(struct _cmstransform_struct * CMM,
+ const void* InputBuffer,
+ void* OutputBuffer,
+ cmsUInt32Number Size,
+ cmsUInt32Number Stride)
+{
+ cmsUInt32Number i;
+
+ for (i=0; i < Size; i++)
+ {
+ ((cmsUInt8Number*) OutputBuffer)[i] = 0x42;
+ }
+
+}
+
+
+cmsBool TransformFactory(_cmsTransformFn* xformPtr,
+ void** UserData,
+ _cmsFreeUserDataFn* FreePrivateDataFn,
+ cmsPipeline** Lut,
+ cmsUInt32Number* InputFormat,
+ cmsUInt32Number* OutputFormat,
+ cmsUInt32Number* dwFlags)
+
+{
+ if (*OutputFormat == TYPE_GRAY_8)
+ {
+ // *Lut holds the pipeline to be applied
+ *xformPtr = TrancendentalTransform;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+// The Plug-in entry point
+static cmsPluginTransform FullTransformPluginSample = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginTransformSig, NULL},
+
+ TransformFactory
+};
+
+cmsInt32Number CheckTransformPlugin(void)
+{
+ cmsContext ctx = WatchDogContext(NULL);
+ cmsContext cpy;
+ cmsContext cpy2;
+ cmsHTRANSFORM xform;
+ cmsUInt8Number In[]= { 10, 20, 30, 40 };
+ cmsUInt8Number Out[4];
+ cmsToneCurve* Linear;
+ cmsHPROFILE h;
+ int i;
+
+
+ cmsPluginTHR(ctx, &FullTransformPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ cpy2 = DupContext(cpy, NULL);
+
+ Linear = cmsBuildGamma(cpy2, 1.0);
+ h = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear);
+ cmsFreeToneCurve(Linear);
+
+ xform = cmsCreateTransformTHR(cpy2, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
+ cmsCloseProfile(h);
+
+ cmsDoTransform(xform, In, Out, 4);
+
+
+ cmsDeleteTransform(xform);
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+ cmsDeleteContext(cpy2);
+
+ for (i=0; i < 4; i++)
+ if (Out[i] != 0x42) return 0;
+
+ return 1;
+}
+
+
+// --------------------------------------------------------------------------------------------------
+// Check the mutex plug-in
+// --------------------------------------------------------------------------------------------------
+
+typedef struct {
+ int nlocks;
+} MyMtx;
+
+
+static
+void* MyMtxCreate(cmsContext id)
+{
+ MyMtx* mtx = (MyMtx*) _cmsMalloc(id, sizeof(MyMtx));
+ mtx ->nlocks = 0;
+ return mtx;
+}
+
+static
+void MyMtxDestroy(cmsContext id, void* mtx)
+{
+ MyMtx* mtx_ = (MyMtx*) mtx;
+
+ if (mtx_->nlocks != 0)
+ Die("Locks != 0 when setting free a mutex");
+
+ _cmsFree(id, mtx);
+
+}
+
+static
+cmsBool MyMtxLock(cmsContext id, void* mtx)
+{
+ MyMtx* mtx_ = (MyMtx*) mtx;
+ mtx_->nlocks++;
+
+ return TRUE;
+}
+
+static
+void MyMtxUnlock(cmsContext id, void* mtx)
+{
+ MyMtx* mtx_ = (MyMtx*) mtx;
+ mtx_->nlocks--;
+
+}
+
+
+static cmsPluginMutex MutexPluginSample = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginMutexSig, NULL},
+
+ MyMtxCreate, MyMtxDestroy, MyMtxLock, MyMtxUnlock
+};
+
+
+cmsInt32Number CheckMutexPlugin(void)
+{
+ cmsContext ctx = WatchDogContext(NULL);
+ cmsContext cpy;
+ cmsContext cpy2;
+ cmsHTRANSFORM xform;
+ cmsUInt8Number In[]= { 10, 20, 30, 40 };
+ cmsUInt8Number Out[4];
+ cmsToneCurve* Linear;
+ cmsHPROFILE h;
+ int i;
+
+
+ cmsPluginTHR(ctx, &MutexPluginSample);
+
+ cpy = DupContext(ctx, NULL);
+ cpy2 = DupContext(cpy, NULL);
+
+ Linear = cmsBuildGamma(cpy2, 1.0);
+ h = cmsCreateLinearizationDeviceLinkTHR(cpy2, cmsSigGrayData, &Linear);
+ cmsFreeToneCurve(Linear);
+
+ xform = cmsCreateTransformTHR(cpy2, h, TYPE_GRAY_8, h, TYPE_GRAY_8, INTENT_PERCEPTUAL, 0);
+ cmsCloseProfile(h);
+
+ cmsDoTransform(xform, In, Out, 4);
+
+
+ cmsDeleteTransform(xform);
+ cmsDeleteContext(ctx);
+ cmsDeleteContext(cpy);
+ cmsDeleteContext(cpy2);
+
+ for (i=0; i < 4; i++)
+ if (Out[i] != In[i]) return 0;
+
+ return 1;
+}
diff --git a/testbed/testthread.cpp b/testbed/testthread.cpp
index 435445c..d553567 100644
--- a/testbed/testthread.cpp
+++ b/testbed/testthread.cpp
@@ -1,52 +1,120 @@
#include <windows.h>
-#include "lcms.h"
+#include "lcms2_plugin.h"
-static cmsHPROFILE prof_xyz,prof_rgb;
-static cmsHTRANSFORM trans_xyz_to_rgb,trans_rgb_to_xyz;
+static cmsContext ctx;
+static cmsHPROFILE prof_cmyk, prof_rgb;
+static volatile int rc = 0;
-static DWORD WINAPI make_trans_xyz_to_rgb(LPVOID lpParameter)
+
+static
+void* MyMtxCreate(cmsContext id)
{
- trans_xyz_to_rgb = cmsCreateTransform(
- prof_xyz,TYPE_XYZ_DBL,
- prof_rgb,TYPE_RGB_DBL,
- INTENT_ABSOLUTE_COLORIMETRIC,cmsFLAGS_NOTPRECALC);
- return 0;
+ return (void*) CreateMutex( NULL, FALSE, NULL);
}
-static DWORD WINAPI make_trans_rgb_to_xyz(LPVOID lpParameter)
+static
+void MyMtxDestroy(cmsContext id, void* mtx)
{
- trans_rgb_to_xyz = cmsCreateTransform(
- prof_rgb,TYPE_RGB_DBL,
- prof_xyz,TYPE_XYZ_DBL,
- INTENT_ABSOLUTE_COLORIMETRIC,cmsFLAGS_NOTPRECALC);
- return 0;
+ CloseHandle((HANDLE) mtx);
+}
+
+static
+cmsBool MyMtxLock(cmsContext id, void* mtx)
+{
+ WaitForSingleObject((HANDLE) mtx, INFINITE);
+ return TRUE;
+}
+
+static
+void MyMtxUnlock(cmsContext id, void* mtx)
+{
+ ReleaseMutex((HANDLE) mtx);
+}
+
+
+static cmsPluginMutex MutexPluginSample = {
+
+ { cmsPluginMagicNumber, 2060, cmsPluginMutexSig, NULL},
+
+ MyMtxCreate, MyMtxDestroy, MyMtxLock, MyMtxUnlock
+};
+
+
+static DWORD WINAPI one_thread(LPVOID lpParameter)
+{
+ int i, j;
+ cmsUInt8Number rgb[3*1000];
+ cmsUInt8Number cmyk[4*1000];
+
+ Sleep(rand() % 500 );
+ cmsHTRANSFORM xform = cmsCreateTransformTHR(ctx, prof_rgb, TYPE_RGB_8, prof_cmyk, TYPE_CMYK_8, 0, 0);
+
+ for (i=0; i < 10000; i++) {
+
+ for (j=0; j < 1000; j++)
+ {
+ rgb[j * 3 ] = 189;
+ rgb[j * 3 + 1] = 100;
+ rgb[j * 3 + 2] = 75;
+ }
+ cmsDoTransform(xform, rgb, cmyk, 1000);
+ for (j=0; j < 1000; j++)
+ {
+ if (cmyk[j * 4 ] != 37 ||
+ cmyk[j * 4 + 1 ] != 188 ||
+ cmyk[j * 4 + 2 ] != 195 ||
+ cmyk[j * 4 + 3 ] != 7)
+ {
+ OutputDebugString(L"ERROR\n");
+ rc = 1;
+ }
+
+ }
+
+ }
+
+ cmsDeleteTransform(xform);
+
+ return 0;
}
-int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
-lpCmdLine,int nCmdShow)
+int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
- prof_xyz = cmsCreateXYZProfile();
- prof_rgb = cmsOpenProfileFromFile("AdobeRGB1998.icc","rb");
-//cmsCreate_sRGBProfile();
- for (int i=0;i<10;++i)
- {
-#define try_threads
-#ifdef try_threads
- DWORD threadid;
- HANDLE workers[2];
- workers[0] = CreateThread(NULL,0,make_trans_xyz_to_rgb,NULL,0,&threadid);
- workers[1] = CreateThread(NULL,0,make_trans_rgb_to_xyz,NULL,0,&threadid);
- WaitForMultipleObjects(2,workers,TRUE,INFINITE);
- for (unsigned i=0;i<2;++i)
- CloseHandle(workers[i]);
-#else
- make_trans_xyz_to_rgb(0);
- make_trans_rgb_to_xyz(0);
-#endif
- cmsDeleteTransform(trans_xyz_to_rgb);
- cmsDeleteTransform(trans_rgb_to_xyz);
- }
- cmsCloseProfile(prof_rgb);
- cmsCloseProfile(prof_xyz);
+ int i;
+ cmsContext ctx;
+
+ OutputDebugString(L"Test in progress...\n");
+
+ ctx = cmsCreateContext(&MutexPluginSample, 0);
+
+ prof_cmyk = cmsOpenProfileFromFileTHR(ctx, "USWebCoatedSWOP.icc", "r");
+ prof_rgb = cmsOpenProfileFromFileTHR(ctx, "AdobeRGB1998.icc","r");
+
+
+#define NWORKERS 10
+
+ HANDLE workers[NWORKERS];
+
+
+ for (int i=0; i<NWORKERS; ++i)
+ {
+ DWORD threadid;
+
+ workers[i] = CreateThread(NULL,0,one_thread,NULL,0,&threadid);
+ }
+
+ WaitForMultipleObjects(NWORKERS,workers,TRUE,INFINITE);
+
+ for ( i=0;i<NWORKERS;++i)
+ CloseHandle(workers[i]);
+
+
+ cmsCloseProfile(prof_rgb);
+ cmsCloseProfile(prof_cmyk);
+ cmsDeleteContext(ctx);
+
+ OutputDebugString(L"Test Done\n");
+
+ return rc;
}
diff --git a/testbed/zoo_icc.c b/testbed/zoo_icc.c
new file mode 100755
index 0000000..c1e9981
--- /dev/null
+++ b/testbed/zoo_icc.c
@@ -0,0 +1,310 @@
+//---------------------------------------------------------------------------------
+//
+// Little Color Management System
+// Copyright (c) 1998-2014 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 "testcms2.h"
+
+
+// ZOO checks ------------------------------------------------------------------------------------------------------------
+
+
+#ifdef CMS_IS_WINDOWS_
+
+static char ZOOfolder[cmsMAX_PATH] = "c:\\colormaps\\";
+static char ZOOwrite[cmsMAX_PATH] = "c:\\colormaps\\write\\";
+static char ZOORawWrite[cmsMAX_PATH] = "c:\\colormaps\\rawwrite\\";
+
+
+// Read all tags on a profile given by its handle
+static
+void ReadAllTags(cmsHPROFILE h)
+{
+ cmsInt32Number i, n;
+ cmsTagSignature sig;
+
+ n = cmsGetTagCount(h);
+ for (i=0; i < n; i++) {
+
+ sig = cmsGetTagSignature(h, i);
+ if (cmsReadTag(h, sig) == NULL) return;
+ }
+}
+
+
+// Read all tags on a profile given by its handle
+static
+void ReadAllRAWTags(cmsHPROFILE h)
+{
+ cmsInt32Number i, n;
+ cmsTagSignature sig;
+ cmsInt32Number len;
+
+ n = cmsGetTagCount(h);
+ for (i=0; i < n; i++) {
+
+ sig = cmsGetTagSignature(h, i);
+ len = cmsReadRawTag(h, sig, NULL, 0);
+ }
+}
+
+
+static
+void PrintInfo(cmsHPROFILE h, cmsInfoType Info)
+{
+ wchar_t* text;
+ cmsInt32Number len;
+ cmsContext id = 0;
+
+ len = cmsGetProfileInfo(h, Info, "en", "US", NULL, 0);
+ if (len == 0) return;
+
+ text = _cmsMalloc(id, len);
+ cmsGetProfileInfo(h, Info, "en", "US", text, len);
+
+ wprintf(L"%s\n", text);
+ _cmsFree(id, text);
+}
+
+
+static
+void PrintAllInfos(cmsHPROFILE h)
+{
+ PrintInfo(h, cmsInfoDescription);
+ PrintInfo(h, cmsInfoManufacturer);
+ PrintInfo(h, cmsInfoModel);
+ PrintInfo(h, cmsInfoCopyright);
+ printf("\n\n");
+}
+
+static
+void ReadAllLUTS(cmsHPROFILE h)
+{
+ cmsPipeline* a;
+ cmsCIEXYZ Black;
+
+ a = _cmsReadInputLUT(h, INTENT_PERCEPTUAL);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadInputLUT(h, INTENT_RELATIVE_COLORIMETRIC);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadInputLUT(h, INTENT_SATURATION);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadInputLUT(h, INTENT_ABSOLUTE_COLORIMETRIC);
+ if (a) cmsPipelineFree(a);
+
+
+ a = _cmsReadOutputLUT(h, INTENT_PERCEPTUAL);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadOutputLUT(h, INTENT_RELATIVE_COLORIMETRIC);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadOutputLUT(h, INTENT_SATURATION);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadOutputLUT(h, INTENT_ABSOLUTE_COLORIMETRIC);
+ if (a) cmsPipelineFree(a);
+
+
+ a = _cmsReadDevicelinkLUT(h, INTENT_PERCEPTUAL);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadDevicelinkLUT(h, INTENT_RELATIVE_COLORIMETRIC);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadDevicelinkLUT(h, INTENT_SATURATION);
+ if (a) cmsPipelineFree(a);
+
+ a = _cmsReadDevicelinkLUT(h, INTENT_ABSOLUTE_COLORIMETRIC);
+ if (a) cmsPipelineFree(a);
+
+
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_PERCEPTUAL, 0);
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_RELATIVE_COLORIMETRIC, 0);
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_SATURATION, 0);
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_ABSOLUTE_COLORIMETRIC, 0);
+ cmsDetectTAC(h);
+}
+
+// Check one specimen in the ZOO
+
+static
+cmsInt32Number CheckSingleSpecimen(const char* Profile)
+{
+ char BuffSrc[256];
+ char BuffDst[256];
+ cmsHPROFILE h;
+
+ sprintf(BuffSrc, "%s%s", ZOOfolder, Profile);
+ sprintf(BuffDst, "%s%s", ZOOwrite, Profile);
+
+ h = cmsOpenProfileFromFile(BuffSrc, "r");
+ if (h == NULL) return 0;
+
+ printf("%s\n", Profile);
+
+ PrintAllInfos(h);
+ ReadAllTags(h);
+ ReadAllLUTS(h);
+ // ReadAllRAWTags(h);
+
+
+ cmsSaveProfileToFile(h, BuffDst);
+ cmsCloseProfile(h);
+
+ h = cmsOpenProfileFromFile(BuffDst, "r");
+ if (h == NULL) return 0;
+ ReadAllTags(h);
+
+
+ cmsCloseProfile(h);
+
+ return 1;
+}
+
+static
+cmsInt32Number CheckRAWSpecimen(const char* Profile)
+{
+ char BuffSrc[256];
+ char BuffDst[256];
+ cmsHPROFILE h;
+
+ sprintf(BuffSrc, "%s%s", ZOOfolder, Profile);
+ sprintf(BuffDst, "%s%s", ZOORawWrite, Profile);
+
+ h = cmsOpenProfileFromFile(BuffSrc, "r");
+ if (h == NULL) return 0;
+
+ ReadAllTags(h);
+ ReadAllRAWTags(h);
+ cmsSaveProfileToFile(h, BuffDst);
+ cmsCloseProfile(h);
+
+ h = cmsOpenProfileFromFile(BuffDst, "r");
+ if (h == NULL) return 0;
+ ReadAllTags(h);
+ cmsCloseProfile(h);
+
+ return 1;
+}
+
+
+static int input = 0,
+ disp = 0,
+ output = 0,
+ link = 0,
+ abst = 0,
+ color = 0,
+ named = 0;
+
+static int rgb = 0,
+ cmyk = 0,
+ gray = 0,
+ other = 0;
+
+
+
+static
+int count_stats(const char* Profile)
+{
+ char BuffSrc[256];
+ cmsHPROFILE h;
+ cmsCIEXYZ Black;
+
+ sprintf(BuffSrc, "%s%s", ZOOfolder, Profile);
+
+ h = cmsOpenProfileFromFile(BuffSrc, "r");
+ if (h == NULL) return 0;
+
+
+ switch (cmsGetDeviceClass(h)) {
+
+ case cmsSigInputClass : input++; break;
+ case cmsSigDisplayClass : disp++; break;
+ case cmsSigOutputClass : output++; break;
+ case cmsSigLinkClass : link++; break;
+ case cmsSigAbstractClass : abst++; break;
+ case cmsSigColorSpaceClass : color++; break;
+ case cmsSigNamedColorClass : named ++; break;
+ }
+
+
+ switch (cmsGetColorSpace(h)) {
+
+ case cmsSigRgbData: rgb++; break;
+ case cmsSigCmykData: cmyk++; break;
+ case cmsSigGrayData: gray++; break;
+ default: other++;
+ }
+
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_PERCEPTUAL, 0);
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_RELATIVE_COLORIMETRIC, 0);
+ cmsDetectDestinationBlackPoint(&Black, h, INTENT_SATURATION, 0);
+
+ cmsCloseProfile(h);
+
+ return 1;
+}
+
+
+
+void CheckProfileZOO(void)
+{
+
+ struct _finddata_t c_file;
+ intptr_t hFile;
+
+ cmsSetLogErrorHandler(NULL);
+
+ if ( (hFile = _findfirst("c:\\colormaps\\*.*", &c_file)) == -1L )
+ printf("No files in current directory");
+ else
+ {
+ do
+ {
+ if (strcmp(c_file.name, ".") != 0 &&
+ strcmp(c_file.name, "..") != 0) {
+
+ CheckSingleSpecimen( c_file.name);
+ CheckRAWSpecimen( c_file.name);
+
+ count_stats(c_file.name);
+
+ TestMemoryLeaks(FALSE);
+
+ }
+
+ } while ( _findnext(hFile, &c_file) == 0 );
+
+ _findclose(hFile);
+ }
+
+ ResetFatalError();
+}
+
+#endif
diff --git a/utils/delphi/lcms2dll.pas b/utils/delphi/lcms2dll.pas
index 1c2d674..9262cd3 100644
--- a/utils/delphi/lcms2dll.pas
+++ b/utils/delphi/lcms2dll.pas
@@ -3,7 +3,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
-// Copyright (c) 1998-2010 Marti Maria Saguer
+// Copyright (c) 1998-2014 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@@ -25,16 +25,29 @@
//
//---------------------------------------------------------------------------------
//
-// Version 2.1
+// Version 2.6
//
UNIT lcms2dll;
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
INTERFACE
-USES Windows;
+{$IFNDEF MSWINDOWS}
+ USES LCLType, types;
+ Type PWChar = PWideChar;
+{$ELSE}
+ USES Windows;
+{$ENDIF}
+
+ CONST
+
+ LCMS2_SO = {$IFDEF DARWIN} 'liblcms2.2.dylib'; {$ELSE} 'lcms2.dll'; {$ENDIF}
- TYPE
+ TYPE
Uint8 = Byte;
Int8 = Shortint;
@@ -43,7 +56,7 @@ USES Windows;
UInt32 = LongWord;
Int32 = Longint;
- TYPE
+ TYPE
cmsUInt8Number = Uint8;
cmsInt8Number = Int8;
cmsUInt16Number = UInt16;
@@ -58,17 +71,17 @@ USES Windows;
cmsFloat64Number = Double;
LPcmsUInt8Number = ^cmsUInt8Number;
- LPcmsInt8Number = ^cmsInt8Number;
- LPcmsUInt16Number = ^cmsUInt16Number;
- LPcmsInt16Number = ^cmsInt16Number;
-
- LPcmsUInt32Number = ^cmsUInt32Number;
- LPcmsInt32Number = ^cmsInt32Number;
- LPcmsInt64Number = ^cmsInt64Number;
- LPcmsUInt64Number = ^cmsUInt64Number;
-
- LPcmsFloat32Number = ^cmsFloat32Number;
- LPcmsFloat64Number = ^cmsFloat64Number;
+ LPcmsInt8Number = ^cmsInt8Number;
+ LPcmsUInt16Number = ^cmsUInt16Number;
+ LPcmsInt16Number = ^cmsInt16Number;
+
+ LPcmsUInt32Number = ^cmsUInt32Number;
+ LPcmsInt32Number = ^cmsInt32Number;
+ LPcmsInt64Number = ^cmsInt64Number;
+ LPcmsUInt64Number = ^cmsUInt64Number;
+
+ LPcmsFloat32Number = ^cmsFloat32Number;
+ LPcmsFloat64Number = ^cmsFloat64Number;
// Derivative types
@@ -315,7 +328,7 @@ cmsPlatformSignature = (
cmsSigUnices = $2A6E6978 // '*nix' // From argyll -- Not official
);
-CONST
+CONST
// Reference gamut
cmsSigPerceptualReferenceMediumGamut = $70726d67; //'prmg'
@@ -357,7 +370,7 @@ cmsCurveSegSignature = (
cmsSigSegmentedCurve = $63757266 // 'curf'
);
-CONST
+CONST
// Used in ResponseCurveType
cmsSigStatusA = $53746141; //'StaA'
@@ -388,12 +401,12 @@ cmsICCData = PACKED RECORD
// ICC date time
cmsDateTimeNumber = PACKED RECORD
- year: cmsUInt16Number;
- month: cmsUInt16Number;
- day: cmsUInt16Number;
- hours: cmsUInt16Number;
- minutes: cmsUInt16Number;
- seconds: cmsUInt16Number;
+ year: cmsUInt16Number;
+ month: cmsUInt16Number;
+ day: cmsUInt16Number;
+ hours: cmsUInt16Number;
+ minutes: cmsUInt16Number;
+ seconds: cmsUInt16Number;
END;
// ICC XYZ
@@ -443,8 +456,8 @@ END;
// ICC base tag
cmsTagBase = PACKED RECORD
- sig: cmsTagTypeSignature;
- reserved: array[0..3] of cmsInt8Number;
+ sig: cmsTagTypeSignature;
+ reserved: array[0..3] of cmsInt8Number;
END;
// A tag entry in directory
@@ -457,7 +470,7 @@ END;
cmsContext = Pointer; // Context identifier for multithreaded environments
cmsHANDLE = Pointer; // Generic handle
-cmsHPROFILE = Pointer; // Opaque typedefs to hide internals
+cmsHPROFILE = Pointer; // Opaque typedefs to hide internals
cmsHTRANSFORM = Pointer;
@@ -494,17 +507,17 @@ CONST
FUNCTION BYTES_SH(b: cmsUInt32Number):cmsUInt32Number;
- FUNCTION T_FLOAT(a: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_OPTIMIZED(o: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_COLORSPACE(s: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_SWAPFIRST(s: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_FLAVOR(s: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_PLANAR(p: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_ENDIAN16(e: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_DOSWAP(e: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_EXTRA(e: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_CHANNELS(c: cmsUInt32Number): cmsUInt32Number;
- FUNCTION T_BYTES(b: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_FLOAT(a: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_OPTIMIZED(o: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_COLORSPACE(s: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_SWAPFIRST(s: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_FLAVOR(s: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_PLANAR(p: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_ENDIAN16(e: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_DOSWAP(e: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_EXTRA(e: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_CHANNELS(c: cmsUInt32Number): cmsUInt32Number;
+ FUNCTION T_BYTES(b: cmsUInt32Number): cmsUInt32Number;
CONST
@@ -525,7 +538,7 @@ CONST
PT_HSV = 12;
PT_HLS = 13;
PT_Yxy = 14;
-
+
PT_MCH1 = 15;
PT_MCH2 = 16;
PT_MCH3 = 17;
@@ -544,7 +557,7 @@ CONST
PT_LabV2 = 30; // Identical to PT_Lab, but using the V2 old encoding
-
+
// Format descriptors
TYPE_GRAY_8 = $030009;
TYPE_GRAY_8_REV = $032009;
@@ -568,6 +581,9 @@ CONST
TYPE_BGR_16_SE = $040c1a;
TYPE_RGBA_8 = $040099;
TYPE_RGBA_8_PLANAR = $041099;
+ TYPE_ARGB_8_PLANAR = $045099;
+ TYPE_ABGR_8_PLANAR = $041499;
+ TYPE_BGRA_8_PLANAR = $045499;
TYPE_RGBA_16 = $04009a;
TYPE_RGBA_16_PLANAR = $04109a;
TYPE_RGBA_16_SE = $04089a;
@@ -686,6 +702,7 @@ CONST
TYPE_XYZA_FLT = $49009c;
TYPE_LabA_FLT = $4a009c;
TYPE_RGBA_FLT = $44009c;
+
TYPE_XYZ_DBL = $490018;
TYPE_Lab_DBL = $4a0018;
TYPE_GRAY_DBL = $430008;
@@ -695,7 +712,16 @@ CONST
TYPE_ALabV2_8 = $1e0499;
TYPE_LabV2_16 = $1e001a;
-
+ TYPE_GRAY_HALF_FLT = $43000a;
+ TYPE_RGB_HALF_FLT = $44001a;
+ TYPE_RGBA_HALF_FLT = $44009a;
+ TYPE_CMYK_HALF_FLT = $460022;
+
+ TYPE_ARGB_HALF_FLT = $44409a;
+ TYPE_BGR_HALF_FLT = $44041a;
+ TYPE_BGRA_HALF_FLT = $44449a;
+ TYPE_ABGR_HALF_FLT = $44041a;
+
TYPE
@@ -751,7 +777,7 @@ CONST
cmsILLUMINANT_TYPE_A = $0000006;
cmsILLUMINANT_TYPE_E = $0000007;
cmsILLUMINANT_TYPE_F8 = $0000008;
-
+
TYPE
cmsICCMeasurementConditions = PACKED RECORD
@@ -771,6 +797,13 @@ TYPE
END;
+// Context --------------------------------------------------------------------------------------------------------------
+
+FUNCTION cmsCreateContext(Plugin : Pointer; UserData : Pointer) : cmsContext; StdCall;
+PROCEDURE cmsDeleteContext(ContextID: cmsContext); StdCall;
+FUNCTION cmsDupContext(ContextID: cmsContext; NewUserData: Pointer): cmsContext; StdCall;
+FUNCTION cmsGetContextUserData(ContextID: cmsContext): Pointer; StdCall;
+
// Plug-In registering ---------------------------------------------------------------------------------------------------
FUNCTION cmsPlugin(Plugin: Pointer): cmsBool; StdCall;
@@ -888,7 +921,7 @@ FUNCTION cmsAdaptToIlluminant(Result: LPcmsCIEXYZ; SourceWhitePt: LPcmsCIEXYZ;
LPcmsViewingConditions = ^cmsViewingConditions;
-
+
FUNCTION cmsCIECAM02Init(pVC : LPcmsViewingConditions ) : Pointer; StdCall;
PROCEDURE cmsCIECAM02Done(hModel : Pointer); StdCall;
PROCEDURE cmsCIECAM02Forward(hModel: Pointer; pIn: LPcmsCIEXYZ; pOut: LPcmsJCh ); StdCall;
@@ -899,7 +932,7 @@ PROCEDURE cmsCIECAM02Reverse(hModel: Pointer; pIn: LPcmsJCh; pOut: LPcmsCIEX
// This describes a curve segment. For a table of supported types, see the manual. User can increase the number of
// available types by using a proper plug-in. Parametric segments allow 10 parameters at most
-TYPE
+TYPE
cmsCurveSegment = PACKED RECORD
x0, x1: cmsFloat32Number; // Domain; for x0 < x <= x1
PType: cmsInt32Number; // Parametric type, Type == 0 means sampled segment. Negative values are reserved
@@ -947,6 +980,8 @@ FUNCTION cmsIsToneCurveMonotonic(t: LPcmsToneCurve):cmsBool; StdCall;
FUNCTION cmsIsToneCurveDescending(t: LPcmsToneCurve):cmsBool; StdCall;
FUNCTION cmsGetToneCurveParametricType(t: LPcmsToneCurve):cmsInt32Number; StdCall;
FUNCTION cmsEstimateGamma(t: LPcmsToneCurve; Precision:cmsFloat64Number):cmsFloat64Number; StdCall;
+FUNCTION cmsGetToneCurveEstimatedTableEntries(t: LPcmsToneCurve): cmsUInt32Number; StdCall;
+FUNCTION cmsGetToneCurveEstimatedTable(t: LPcmsToneCurve): LPcmsUInt16Number; StdCall;
// Implements pipelines of multi-processing elements -------------------------------------------------------------
@@ -955,11 +990,12 @@ TYPE
LPcmsPipeline = Pointer;
LPcmsStage = Pointer;
LPLPcmsStage = ^LPcmsStage;
-
+
// Those are hi-level pipelines
FUNCTION cmsPipelineAlloc(ContextID: cmsContext; InputChannels, OutputChannels: cmsUInt32Number): LPcmsPipeline; StdCall;
PROCEDURE cmsPipelineFree(lut: LPcmsPipeline); StdCall;
-FUNCTION cmsPipelineDup(Orig: LPcmsPipeline): LPcmsPipeline; StdCall;
+FUNCTION cmsPipelineDup(Orig: LPcmsPipeline): LPcmsPipeline; StdCall;
+FUNCTION cmsGetPipelineContextID(lut: LPcmsPipeline) : cmsContext; StdCall;
FUNCTION cmsPipelineInputChannels(lut: LPcmsPipeline): cmsUInt32Number; StdCall;
FUNCTION cmsPipelineOutputChannels(lut: LPcmsPipeline): cmsUInt32Number; StdCall;
@@ -1011,7 +1047,7 @@ FUNCTION cmsStageType(mpe: LPcmsStage): cmsStageSignature; StdCall;
FUNCTION cmsStageData(mpe: LPcmsStage): Pointer; StdCall;
// Sampling
-
+
Type
cmsSAMPLER16 = FUNCTION (Inp, Outp: LPcmsUInt16NumberArray; Cargo: Pointer): cmsInt32Number; CDecl;
cmsSAMPLERFLOAT = FUNCTION (Inp, Outp: LPcmsFloat32NumberArray; Cargo: Pointer): cmsInt32Number; CDecl;
@@ -1046,9 +1082,9 @@ cmsNoLanguage = #0#0#0;
cmsNoCountry = #0#0#0;
-FUNCTION cmsMLUalloc(ContextID: cmsContext; nItems: cmsUInt32Number): LPcmsMLU; StdCall;
+FUNCTION cmsMLUalloc(ContextID: cmsContext; nItems: cmsUInt32Number): LPcmsMLU; StdCall;
PROCEDURE cmsMLUfree(mlu: LPcmsMLU); StdCall;
-FUNCTION cmsMLUdup(mlu: LPcmsMLU): LPcmsMLU; StdCall;
+FUNCTION cmsMLUdup(mlu: LPcmsMLU): LPcmsMLU; StdCall;
FUNCTION cmsMLUsetASCII(mlu: LPcmsMLU; LanguageCode, CountryCode, ASCIIString: PAnsiChar): cmsBool; StdCall;
FUNCTION cmsMLUsetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; WideString: PWChar): cmsBool; StdCall;
@@ -1056,7 +1092,7 @@ FUNCTION cmsMLUsetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Wid
FUNCTION cmsMLUgetASCII(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Buffer: PAnsiChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall;
FUNCTION cmsMLUgetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Buffer: PWChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall;
-
+
FUNCTION cmsMLUgetTranslation(mlu: LPcmsMLU; LanguageCode, CountryCode, ObtainedLanguage, ObtainedCountry: PAnsiChar): cmsBool; StdCall;
// Undercolorremoval & black generation -------------------------------------------------------------------------------------
@@ -1085,13 +1121,13 @@ Const
cmsSPOT_LINE = 5;
cmsSPOT_SQUARE = 6;
cmsSPOT_CROSS = 7;
-
+
Type
cmsScreeningChannel = PACKED RECORD
- Frequency,
+ Frequency,
ScreenAngle: cmsFloat64Number;
SpotShape: cmsUInt32Number;
@@ -1137,12 +1173,12 @@ Type
cmsPSEQDESC = PACKED RECORD
deviceMfg, deviceModel: cmsSignature;
-
+
attributes: cmsUInt64Number;
technology: cmsTechnologySignature;
ProfileID: cmsProfileID;
- Manufacturer,
- Model,
+ Manufacturer,
+ Model,
Description : LPcmsMLU;
END;
@@ -1167,11 +1203,11 @@ TYPE
LPcmsDICTentry = ^cmsDICTentry;
-cmsDICTentry = PACKED RECORD
+cmsDICTentry = PACKED RECORD
Next: LPcmsDICTentry;
- DisplayName, DisplayValue: LPcmsMLU;
+ DisplayName, DisplayValue: LPcmsMLU;
Name, Value : PWChar;
END;
@@ -1390,7 +1426,7 @@ INTENT_PRESERVE_K_ONLY_SATURATION = 12;
INTENT_PRESERVE_K_PLANE_PERCEPTUAL = 13;
INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC = 14;
INTENT_PRESERVE_K_PLANE_SATURATION = 15;
-
+
Type
LPPAnsiChar = ^PAnsiChar;
@@ -1507,6 +1543,8 @@ FUNCTION cmsCreateExtendedTransform(ContextID: cmsContext;
PROCEDURE cmsDeleteTransform(hTransform: cmsHTRANSFORM); StdCall;
PROCEDURE cmsDoTransform(Transform: cmsHTRANSFORM; InputBuffer, OutputBuffer: Pointer; size: cmsUInt32Number); StdCall;
+PROCEDURE cmsDoTransformStride(Transform: cmsHTRANSFORM; InputBuffer, OutputBuffer: Pointer; size: cmsUInt32Number; stride: cmsUInt32Number); StdCall;
+
PROCEDURE cmsSetAlarmCodes( NewAlarm: LPcmsUInt16NumberArray); StdCall;
PROCEDURE cmsGetAlarmCodes(NewAlarm: LPcmsUInt16NumberArray); StdCall;
@@ -1624,7 +1662,7 @@ FUNCTION cmsDetectTAC(hProfile: cmsHPROFILE): cmsFloat64Number; StdCall;
// Poor man's gamut mapping
FUNCTION cmsDesaturateLab(Lab: LPcmsCIELab; amax, amin, bmax, bmin: cmsFloat64Number): cmsBool; StdCall;
-
+
IMPLEMENTATION
@@ -1643,275 +1681,282 @@ IMPLEMENTATION
FUNCTION BYTES_SH(b: cmsUInt32Number):cmsUInt32Number; begin BYTES_SH := (b) end;
- FUNCTION T_FLOAT(a: cmsUInt32Number): cmsUInt32Number; begin T_FLOAT := (((a) shr 22) and 1) end;
- FUNCTION T_OPTIMIZED(o: cmsUInt32Number): cmsUInt32Number; begin T_OPTIMIZED := (((o) shr 21) and 1) end;
- FUNCTION T_COLORSPACE(s: cmsUInt32Number): cmsUInt32Number; begin T_COLORSPACE := (((s) shr 16) and 31) end;
- FUNCTION T_SWAPFIRST(s: cmsUInt32Number): cmsUInt32Number; begin T_SWAPFIRST := (((s) shr 14) and 1) end;
+ FUNCTION T_FLOAT(a: cmsUInt32Number): cmsUInt32Number; begin T_FLOAT := (((a) shr 22) and 1) end;
+ FUNCTION T_OPTIMIZED(o: cmsUInt32Number): cmsUInt32Number; begin T_OPTIMIZED := (((o) shr 21) and 1) end;
+ FUNCTION T_COLORSPACE(s: cmsUInt32Number): cmsUInt32Number; begin T_COLORSPACE := (((s) shr 16) and 31) end;
+ FUNCTION T_SWAPFIRST(s: cmsUInt32Number): cmsUInt32Number; begin T_SWAPFIRST := (((s) shr 14) and 1) end;
FUNCTION T_FLAVOR(s: cmsUInt32Number): cmsUInt32Number; begin T_FLAVOR := (((s) shr 13) and 1) end;
- FUNCTION T_PLANAR(p: cmsUInt32Number): cmsUInt32Number; begin T_PLANAR := (((p) shr 12) and 1) end;
- FUNCTION T_ENDIAN16(e: cmsUInt32Number): cmsUInt32Number; begin T_ENDIAN16 := (((e) shr 11) and 1) end;
- FUNCTION T_DOSWAP(e: cmsUInt32Number): cmsUInt32Number; begin T_DOSWAP := (((e) shr 10) and 1) end;
- FUNCTION T_EXTRA(e: cmsUInt32Number): cmsUInt32Number; begin T_EXTRA := (((e) shr 7) and 7) end;
- FUNCTION T_CHANNELS(c: cmsUInt32Number): cmsUInt32Number; begin T_CHANNELS := (((c) shr 3) and 15) end;
+ FUNCTION T_PLANAR(p: cmsUInt32Number): cmsUInt32Number; begin T_PLANAR := (((p) shr 12) and 1) end;
+ FUNCTION T_ENDIAN16(e: cmsUInt32Number): cmsUInt32Number; begin T_ENDIAN16 := (((e) shr 11) and 1) end;
+ FUNCTION T_DOSWAP(e: cmsUInt32Number): cmsUInt32Number; begin T_DOSWAP := (((e) shr 10) and 1) end;
+ FUNCTION T_EXTRA(e: cmsUInt32Number): cmsUInt32Number; begin T_EXTRA := (((e) shr 7) and 7) end;
+ FUNCTION T_CHANNELS(c: cmsUInt32Number): cmsUInt32Number; begin T_CHANNELS := (((c) shr 3) and 15) end;
FUNCTION T_BYTES(b: cmsUInt32Number): cmsUInt32Number; begin T_BYTES := ((b) and 7) end;
-//
-
-
-FUNCTION cmsPlugin(Plugin: Pointer): cmsBool; StdCall; external 'lcms2.dll';
-PROCEDURE cmsUnregisterPlugins; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetLogErrorHandler(Fn: cmsLogErrorHandlerFunction); StdCall; external 'lcms2.dll';
-FUNCTION cmsD50_XYZ: LPcmsCIEXYZ; StdCall; external 'lcms2.dll';
-FUNCTION cmsD50_xyY: LPcmsCIExyY; StdCall; external 'lcms2.dll';
-PROCEDURE cmsXYZ2xyY(Dest: LPcmsCIExyY; Source: LPcmsCIEXYZ); StdCall; external 'lcms2.dll';
-PROCEDURE cmsxyY2XYZ(Dest: LPcmsCIEXYZ; Source: LPcmsCIExyY); StdCall; external 'lcms2.dll';
-PROCEDURE cmsLab2XYZ(WhitePoint: LPcmsCIEXYZ; xyz: LPcmsCIEXYZ; Lab: LPcmsCIELab); StdCall; external 'lcms2.dll';
-PROCEDURE cmsXYZ2Lab(WhitePoint: LPcmsCIEXYZ; Lab: LPcmsCIELab; xyz: LPcmsCIEXYZ); StdCall; external 'lcms2.dll';
-PROCEDURE cmsLab2LCh(LCh: LPcmsCIELCh; Lab: LPcmsCIELab); StdCall; external 'lcms2.dll';
-PROCEDURE cmsLCh2Lab(Lab: LPcmsCIELab; LCh: LPcmsCIELCh); StdCall; external 'lcms2.dll';
-PROCEDURE cmsLabEncoded2Float(Lab: LPcmsCIELab; wLab: Pointer); StdCall; external 'lcms2.dll';
-PROCEDURE cmsLabEncoded2FloatV2(Lab: LPcmsCIELab; wLab: Pointer); StdCall; external 'lcms2.dll';
-PROCEDURE cmsFloat2LabEncoded(wLab: Pointer; Lab: LPcmsCIELab); StdCall; external 'lcms2.dll';
-PROCEDURE cmsFloat2LabEncodedV2(wLab: Pointer; Lab: LPcmsCIELab); StdCall; external 'lcms2.dll';
-PROCEDURE cmsXYZEncoded2Float(fxyz : LPcmsCIEXYZ; XYZ: Pointer); StdCall; external 'lcms2.dll';
-PROCEDURE cmsFloat2XYZEncoded(XYZ: Pointer; fXYZ: LPcmsCIEXYZ); StdCall; external 'lcms2.dll';
-FUNCTION cmsDeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external 'lcms2.dll';
-FUNCTION cmsCIE94DeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external 'lcms2.dll';
-FUNCTION cmsBFDdeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external 'lcms2.dll';
-FUNCTION cmsCMCdeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external 'lcms2.dll';
-FUNCTION cmsCIE2000DeltaE(Lab1, Lab2: LPcmsCIELab; Kl, Kc, Kh: Double): Double; StdCall; external 'lcms2.dll';
-FUNCTION cmsWhitePointFromTemp(var WhitePoint: cmsCIExyY; TempK: cmsFloat64Number) : cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsTempFromWhitePoint(var TeampK: cmsFloat64Number; var WhitePoint: cmsCIExyY) : cmsBool; StdCall; external 'lcms2.dll';
+//
+
+FUNCTION cmsCreateContext(Plugin : Pointer; UserData : Pointer) : cmsContext; StdCall; external LCMS2_SO;
+PROCEDURE cmsDeleteContext(ContextID: cmsContext); StdCall; external LCMS2_SO;
+FUNCTION cmsDupContext(ContextID: cmsContext; NewUserData: Pointer): cmsContext; StdCall; external LCMS2_SO;
+FUNCTION cmsGetContextUserData(ContextID: cmsContext): Pointer; StdCall; external LCMS2_SO;
+
+FUNCTION cmsPlugin(Plugin: Pointer): cmsBool; StdCall; external LCMS2_SO;
+PROCEDURE cmsUnregisterPlugins; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetLogErrorHandler(Fn: cmsLogErrorHandlerFunction); StdCall; external LCMS2_SO;
+FUNCTION cmsD50_XYZ: LPcmsCIEXYZ; StdCall; external LCMS2_SO;
+FUNCTION cmsD50_xyY: LPcmsCIExyY; StdCall; external LCMS2_SO;
+PROCEDURE cmsXYZ2xyY(Dest: LPcmsCIExyY; Source: LPcmsCIEXYZ); StdCall; external LCMS2_SO;
+PROCEDURE cmsxyY2XYZ(Dest: LPcmsCIEXYZ; Source: LPcmsCIExyY); StdCall; external LCMS2_SO;
+PROCEDURE cmsLab2XYZ(WhitePoint: LPcmsCIEXYZ; xyz: LPcmsCIEXYZ; Lab: LPcmsCIELab); StdCall; external LCMS2_SO;
+PROCEDURE cmsXYZ2Lab(WhitePoint: LPcmsCIEXYZ; Lab: LPcmsCIELab; xyz: LPcmsCIEXYZ); StdCall; external LCMS2_SO;
+PROCEDURE cmsLab2LCh(LCh: LPcmsCIELCh; Lab: LPcmsCIELab); StdCall; external LCMS2_SO;
+PROCEDURE cmsLCh2Lab(Lab: LPcmsCIELab; LCh: LPcmsCIELCh); StdCall; external LCMS2_SO;
+PROCEDURE cmsLabEncoded2Float(Lab: LPcmsCIELab; wLab: Pointer); StdCall; external LCMS2_SO;
+PROCEDURE cmsLabEncoded2FloatV2(Lab: LPcmsCIELab; wLab: Pointer); StdCall; external LCMS2_SO;
+PROCEDURE cmsFloat2LabEncoded(wLab: Pointer; Lab: LPcmsCIELab); StdCall; external LCMS2_SO;
+PROCEDURE cmsFloat2LabEncodedV2(wLab: Pointer; Lab: LPcmsCIELab); StdCall; external LCMS2_SO;
+PROCEDURE cmsXYZEncoded2Float(fxyz : LPcmsCIEXYZ; XYZ: Pointer); StdCall; external LCMS2_SO;
+PROCEDURE cmsFloat2XYZEncoded(XYZ: Pointer; fXYZ: LPcmsCIEXYZ); StdCall; external LCMS2_SO;
+FUNCTION cmsDeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external LCMS2_SO;
+FUNCTION cmsCIE94DeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external LCMS2_SO;
+FUNCTION cmsBFDdeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external LCMS2_SO;
+FUNCTION cmsCMCdeltaE(Lab1, Lab2: LPcmsCIELab): Double; StdCall; external LCMS2_SO;
+FUNCTION cmsCIE2000DeltaE(Lab1, Lab2: LPcmsCIELab; Kl, Kc, Kh: Double): Double; StdCall; external LCMS2_SO;
+FUNCTION cmsWhitePointFromTemp(var WhitePoint: cmsCIExyY; TempK: cmsFloat64Number) : cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsTempFromWhitePoint(var TeampK: cmsFloat64Number; var WhitePoint: cmsCIExyY) : cmsBool; StdCall; external LCMS2_SO;
FUNCTION cmsAdaptToIlluminant(Result: LPcmsCIEXYZ; SourceWhitePt: LPcmsCIEXYZ;
- Illuminant: LPcmsCIEXYZ; Value: LPcmsCIEXYZ): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsCIECAM02Init(pVC : LPcmsViewingConditions ) : Pointer; StdCall; external 'lcms2.dll';
-PROCEDURE cmsCIECAM02Done(hModel : Pointer); StdCall; external 'lcms2.dll';
-PROCEDURE cmsCIECAM02Forward(hModel: Pointer; pIn: LPcmsCIEXYZ; pOut: LPcmsJCh ); StdCall; external 'lcms2.dll';
-PROCEDURE cmsCIECAM02Reverse(hModel: Pointer; pIn: LPcmsJCh; pOut: LPcmsCIEXYZ ); StdCall; external 'lcms2.dll';
-FUNCTION cmsBuildSegmentedToneCurve(ContextID: cmsContext; nSegments: cmsInt32Number; Segments: LPcmsCurveSegmentArray): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsBuildParametricToneCurve(ContextID: cmsContext; CType: cmsInt32Number; Params: LPcmsFloat64NumberArray): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsBuildGamma(ContextID: cmsContext; Gamma: cmsFloat64Number): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsBuildTabulatedToneCurve16(ContextID: cmsContext; nEntries: cmsInt32Number; values: LPcmsUInt16NumberArray): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsBuildTabulatedToneCurveFloat(ContextID: cmsContext; nEntries: cmsUInt32Number; values: LPcmsFloat32NumberArray): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-PROCEDURE cmsFreeToneCurve(Curve: LPcmsToneCurve); StdCall; external 'lcms2.dll';
-PROCEDURE cmsFreeToneCurveTriple(Curve: LPLPcmsToneCurveArray); StdCall; external 'lcms2.dll';
-FUNCTION cmsDupToneCurve(Src: LPcmsToneCurve): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsReverseToneCurve(InGamma: LPcmsToneCurve): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsReverseToneCurveEx(nResultSamples: cmsInt32Number; InGamma: LPcmsToneCurve): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsJoinToneCurve(ContextID: cmsContext; X, Y: LPcmsToneCurve; nPoints: cmsUInt32Number ): LPcmsToneCurve; StdCall; external 'lcms2.dll';
-FUNCTION cmsSmoothToneCurve(Tab: LPcmsToneCurve; lambda: cmsFloat64Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsEvalToneCurveFloat(Curve: LPcmsToneCurve; v: cmsFloat32Number):cmsFloat32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsEvalToneCurve16(Curve: LPcmsToneCurve; v:cmsUInt16Number):cmsUInt16Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsToneCurveMultisegment(InGamma: LPcmsToneCurve):cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsToneCurveLinear(Curve: LPcmsToneCurve):cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsToneCurveMonotonic(t: LPcmsToneCurve):cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsToneCurveDescending(t: LPcmsToneCurve):cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsGetToneCurveParametricType(t: LPcmsToneCurve):cmsInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsEstimateGamma(t: LPcmsToneCurve; Precision:cmsFloat64Number):cmsFloat64Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineAlloc(ContextID: cmsContext; InputChannels, OutputChannels: cmsUInt32Number): LPcmsPipeline; StdCall; external 'lcms2.dll';
-PROCEDURE cmsPipelineFree(lut: LPcmsPipeline); StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineDup(Orig: LPcmsPipeline): LPcmsPipeline; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineInputChannels(lut: LPcmsPipeline): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineOutputChannels(lut: LPcmsPipeline): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineStageCount(lut: LPcmsPipeline): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineGetPtrToFirstStage(lut: LPcmsPipeline): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineGetPtrToLastStage(lut: LPcmsPipeline): LPcmsStage; StdCall; external 'lcms2.dll';
-
-PROCEDURE cmsPipelineEval16(Inv, Outv: LPcmsUInt16NumberArray; lut: LPcmsPipeline); StdCall; external 'lcms2.dll';
-PROCEDURE cmsPipelineEvalFloat(Inv, Outv: LPcmsFloat32NumberArray; lut: LPcmsPipeline); StdCall; external 'lcms2.dll';
-
-FUNCTION cmsPipelineEvalReverseFloat(Target, Result, Hint: LPcmsFloat32NumberArray; lut: LPcmsPipeline): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineCat(l1, l2: LPcmsPipeline): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsPipelineSetSaveAs8bitsFlag(lut: LPcmsPipeline; On: cmsBool): cmsBool; StdCall; external 'lcms2.dll';
-PROCEDURE cmsPipelineInsertStage(lut: LPcmsPipeline; loc: cmsStageLoc; mpe: LPcmsStage); StdCall; external 'lcms2.dll';
-PROCEDURE cmsPipelineUnlinkStage(lut: LPcmsPipeline; loc: cmsStageLoc; mpe: LPLPcmsStage); StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocIdentity(ContextID: cmsContext; nChannels: cmsUInt32Number): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocToneCurves(ContextID: cmsContext; nChannels: cmsUInt32Number; Curves: LPLPcmsToneCurveArray): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocMatrix(ContextID: cmsContext; Rows, Cols: cmsUInt32Number; Matrix, Offset: LPcmsFloat64NumberArray): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocCLut16bit(ContextID: cmsContext; nGridPoints: cmsUInt32Number; inputChan, outputChan: cmsUInt32Number; Table: LPcmsUInt16NumberArray): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocCLutFloat(ContextID: cmsContext; nGridPoints: cmsUInt32Number; inputChan, outputChan: cmsUInt32Number; Table: LPcmsFloat32NumberArray): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocCLut16bitGranular(ContextID: cmsContext; nGridPoints: LPcmsUInt32NumberArray; inputChan, outputChan: cmsUInt32Number; Table: LPcmsUInt16NumberArray): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageAllocCLutFloatGranular(ContextID: cmsContext; nGridPoints: LPcmsUInt32NumberArray; inputChan, outputChan: cmsUInt32Number; Table: LPcmsFloat32NumberArray): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageDup(mpe: LPcmsStage): LPcmsStage; StdCall; external 'lcms2.dll';
-PROCEDURE cmsStageFree(mpe: LPcmsStage); StdCall; external 'lcms2.dll';
-FUNCTION cmsStageNext(mpe: LPcmsStage): LPcmsStage; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageInputChannels(mpe: LPcmsStage): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageOutputChannels(mpe: LPcmsStage): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageType(mpe: LPcmsStage): cmsStageSignature; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageData(mpe: LPcmsStage): Pointer; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageSampleCLut16bit(mpe: LPcmsStage; Sampler: cmsSAMPLER16; Cargo: Pointer; dwFlags: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsStageSampleCLutFloat(mpe: LPcmsStage; Sampler: cmsSAMPLERFLOAT; Cargo: Pointer; dwFlags: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
+ Illuminant: LPcmsCIEXYZ; Value: LPcmsCIEXYZ): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsCIECAM02Init(pVC : LPcmsViewingConditions ) : Pointer; StdCall; external LCMS2_SO;
+PROCEDURE cmsCIECAM02Done(hModel : Pointer); StdCall; external LCMS2_SO;
+PROCEDURE cmsCIECAM02Forward(hModel: Pointer; pIn: LPcmsCIEXYZ; pOut: LPcmsJCh ); StdCall; external LCMS2_SO;
+PROCEDURE cmsCIECAM02Reverse(hModel: Pointer; pIn: LPcmsJCh; pOut: LPcmsCIEXYZ ); StdCall; external LCMS2_SO;
+FUNCTION cmsBuildSegmentedToneCurve(ContextID: cmsContext; nSegments: cmsInt32Number; Segments: LPcmsCurveSegmentArray): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsBuildParametricToneCurve(ContextID: cmsContext; CType: cmsInt32Number; Params: LPcmsFloat64NumberArray): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsBuildGamma(ContextID: cmsContext; Gamma: cmsFloat64Number): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsBuildTabulatedToneCurve16(ContextID: cmsContext; nEntries: cmsInt32Number; values: LPcmsUInt16NumberArray): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsBuildTabulatedToneCurveFloat(ContextID: cmsContext; nEntries: cmsUInt32Number; values: LPcmsFloat32NumberArray): LPcmsToneCurve; StdCall; external LCMS2_SO;
+PROCEDURE cmsFreeToneCurve(Curve: LPcmsToneCurve); StdCall; external LCMS2_SO;
+PROCEDURE cmsFreeToneCurveTriple(Curve: LPLPcmsToneCurveArray); StdCall; external LCMS2_SO;
+FUNCTION cmsDupToneCurve(Src: LPcmsToneCurve): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsReverseToneCurve(InGamma: LPcmsToneCurve): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsReverseToneCurveEx(nResultSamples: cmsInt32Number; InGamma: LPcmsToneCurve): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsJoinToneCurve(ContextID: cmsContext; X, Y: LPcmsToneCurve; nPoints: cmsUInt32Number ): LPcmsToneCurve; StdCall; external LCMS2_SO;
+FUNCTION cmsSmoothToneCurve(Tab: LPcmsToneCurve; lambda: cmsFloat64Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsEvalToneCurveFloat(Curve: LPcmsToneCurve; v: cmsFloat32Number):cmsFloat32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsEvalToneCurve16(Curve: LPcmsToneCurve; v:cmsUInt16Number):cmsUInt16Number; StdCall; external LCMS2_SO;
+FUNCTION cmsIsToneCurveMultisegment(InGamma: LPcmsToneCurve):cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIsToneCurveLinear(Curve: LPcmsToneCurve):cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIsToneCurveMonotonic(t: LPcmsToneCurve):cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIsToneCurveDescending(t: LPcmsToneCurve):cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsGetToneCurveParametricType(t: LPcmsToneCurve):cmsInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsEstimateGamma(t: LPcmsToneCurve; Precision:cmsFloat64Number):cmsFloat64Number; StdCall; external LCMS2_SO;
+FUNCTION cmsGetToneCurveEstimatedTableEntries(t: LPcmsToneCurve): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsGetToneCurveEstimatedTable(t: LPcmsToneCurve): LPcmsUInt16Number; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineAlloc(ContextID: cmsContext; InputChannels, OutputChannels: cmsUInt32Number): LPcmsPipeline; StdCall; external LCMS2_SO;
+PROCEDURE cmsPipelineFree(lut: LPcmsPipeline); StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineDup(Orig: LPcmsPipeline): LPcmsPipeline; StdCall; external LCMS2_SO;
+FUNCTION cmsGetPipelineContextID(lut: LPcmsPipeline) : cmsContext; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineInputChannels(lut: LPcmsPipeline): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineOutputChannels(lut: LPcmsPipeline): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineStageCount(lut: LPcmsPipeline): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineGetPtrToFirstStage(lut: LPcmsPipeline): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineGetPtrToLastStage(lut: LPcmsPipeline): LPcmsStage; StdCall; external LCMS2_SO;
+
+PROCEDURE cmsPipelineEval16(Inv, Outv: LPcmsUInt16NumberArray; lut: LPcmsPipeline); StdCall; external LCMS2_SO;
+PROCEDURE cmsPipelineEvalFloat(Inv, Outv: LPcmsFloat32NumberArray; lut: LPcmsPipeline); StdCall; external LCMS2_SO;
+
+FUNCTION cmsPipelineEvalReverseFloat(Target, Result, Hint: LPcmsFloat32NumberArray; lut: LPcmsPipeline): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineCat(l1, l2: LPcmsPipeline): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsPipelineSetSaveAs8bitsFlag(lut: LPcmsPipeline; On: cmsBool): cmsBool; StdCall; external LCMS2_SO;
+PROCEDURE cmsPipelineInsertStage(lut: LPcmsPipeline; loc: cmsStageLoc; mpe: LPcmsStage); StdCall; external LCMS2_SO;
+PROCEDURE cmsPipelineUnlinkStage(lut: LPcmsPipeline; loc: cmsStageLoc; mpe: LPLPcmsStage); StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocIdentity(ContextID: cmsContext; nChannels: cmsUInt32Number): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocToneCurves(ContextID: cmsContext; nChannels: cmsUInt32Number; Curves: LPLPcmsToneCurveArray): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocMatrix(ContextID: cmsContext; Rows, Cols: cmsUInt32Number; Matrix, Offset: LPcmsFloat64NumberArray): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocCLut16bit(ContextID: cmsContext; nGridPoints: cmsUInt32Number; inputChan, outputChan: cmsUInt32Number; Table: LPcmsUInt16NumberArray): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocCLutFloat(ContextID: cmsContext; nGridPoints: cmsUInt32Number; inputChan, outputChan: cmsUInt32Number; Table: LPcmsFloat32NumberArray): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocCLut16bitGranular(ContextID: cmsContext; nGridPoints: LPcmsUInt32NumberArray; inputChan, outputChan: cmsUInt32Number; Table: LPcmsUInt16NumberArray): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageAllocCLutFloatGranular(ContextID: cmsContext; nGridPoints: LPcmsUInt32NumberArray; inputChan, outputChan: cmsUInt32Number; Table: LPcmsFloat32NumberArray): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageDup(mpe: LPcmsStage): LPcmsStage; StdCall; external LCMS2_SO;
+PROCEDURE cmsStageFree(mpe: LPcmsStage); StdCall; external LCMS2_SO;
+FUNCTION cmsStageNext(mpe: LPcmsStage): LPcmsStage; StdCall; external LCMS2_SO;
+FUNCTION cmsStageInputChannels(mpe: LPcmsStage): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsStageOutputChannels(mpe: LPcmsStage): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsStageType(mpe: LPcmsStage): cmsStageSignature; StdCall; external LCMS2_SO;
+FUNCTION cmsStageData(mpe: LPcmsStage): Pointer; StdCall; external LCMS2_SO;
+FUNCTION cmsStageSampleCLut16bit(mpe: LPcmsStage; Sampler: cmsSAMPLER16; Cargo: Pointer; dwFlags: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsStageSampleCLutFloat(mpe: LPcmsStage; Sampler: cmsSAMPLERFLOAT; Cargo: Pointer; dwFlags: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
FUNCTION cmsSliceSpace16(nInputs: cmsUInt32Number; clutPoints: LPcmsUInt32NumberArray;
- Sampler: cmsSAMPLER16; Cargo: Pointer): cmsBool; StdCall; external 'lcms2.dll';
+ Sampler: cmsSAMPLER16; Cargo: Pointer): cmsBool; StdCall; external LCMS2_SO;
FUNCTION cmsSliceSpaceFloat(nInputs: cmsUInt32Number; clutPoints: LPcmsUInt32NumberArray;
- Sampler: cmsSAMPLERFLOAT; Cargo: Pointer): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsMLUalloc(ContextID: cmsContext; nItems: cmsUInt32Number): LPcmsMLU; StdCall; external 'lcms2.dll';
-PROCEDURE cmsMLUfree(mlu: LPcmsMLU); StdCall; external 'lcms2.dll';
-FUNCTION cmsMLUdup(mlu: LPcmsMLU): LPcmsMLU; StdCall; external 'lcms2.dll';
+ Sampler: cmsSAMPLERFLOAT; Cargo: Pointer): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsMLUalloc(ContextID: cmsContext; nItems: cmsUInt32Number): LPcmsMLU; StdCall; external LCMS2_SO;
+PROCEDURE cmsMLUfree(mlu: LPcmsMLU); StdCall; external LCMS2_SO;
+FUNCTION cmsMLUdup(mlu: LPcmsMLU): LPcmsMLU; StdCall; external LCMS2_SO;
-FUNCTION cmsMLUsetASCII(mlu: LPcmsMLU; LanguageCode, CountryCode, ASCIIString: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsMLUsetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; WideString: PWChar): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsMLUsetASCII(mlu: LPcmsMLU; LanguageCode, CountryCode, ASCIIString: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsMLUsetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; WideString: PWChar): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsMLUgetASCII(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Buffer: PAnsiChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsMLUgetASCII(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Buffer: PAnsiChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external LCMS2_SO;
-FUNCTION cmsMLUgetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Buffer: PWChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external 'lcms2.dll';
-
-FUNCTION cmsMLUgetTranslation(mlu: LPcmsMLU; LanguageCode, CountryCode, ObtainedLanguage, ObtainedCountry: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsMLUgetWide(mlu: LPcmsMLU; LanguageCode, CountryCode: PAnsiChar; Buffer: PWChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external LCMS2_SO;
+
+FUNCTION cmsMLUgetTranslation(mlu: LPcmsMLU; LanguageCode, CountryCode, ObtainedLanguage, ObtainedCountry: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
FUNCTION cmsAllocNamedColorList(ContextID: cmsContext; n, ColorantCount :cmsUInt32Number;
- Prefix, Suffix: PAnsiChar): LPcmsNAMEDCOLORLIST; StdCall; external 'lcms2.dll';
+ Prefix, Suffix: PAnsiChar): LPcmsNAMEDCOLORLIST; StdCall; external LCMS2_SO;
-PROCEDURE cmsFreeNamedColorList(v: LPcmsNAMEDCOLORLIST); StdCall; external 'lcms2.dll';
-FUNCTION cmsDupNamedColorList(v: LPcmsNAMEDCOLORLIST): LPcmsNAMEDCOLORLIST; StdCall; external 'lcms2.dll';
+PROCEDURE cmsFreeNamedColorList(v: LPcmsNAMEDCOLORLIST); StdCall; external LCMS2_SO;
+FUNCTION cmsDupNamedColorList(v: LPcmsNAMEDCOLORLIST): LPcmsNAMEDCOLORLIST; StdCall; external LCMS2_SO;
FUNCTION cmsAppendNamedColor(v: LPcmsNAMEDCOLORLIST; Name: PAnsiChar;
- PCS, Colorant : LPcmsUInt16NumberArray): cmsBool; StdCall; external 'lcms2.dll';
+ PCS, Colorant : LPcmsUInt16NumberArray): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsNamedColorCount(v: LPcmsNAMEDCOLORLIST): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsNamedColorIndex(v: LPcmsNAMEDCOLORLIST; Name: PAnsiChar): cmsInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsNamedColorCount(v: LPcmsNAMEDCOLORLIST): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsNamedColorIndex(v: LPcmsNAMEDCOLORLIST; Name: PAnsiChar): cmsInt32Number; StdCall; external LCMS2_SO;
FUNCTION cmsNamedColorInfo(v: LPcmsNAMEDCOLORLIST; nColor : cmsUInt32Number;
Name,Prefix, Suffix : PAnsiChar;
- PCS, Colorant : LPcmsUInt16NumberArray): cmsBool; StdCall; external 'lcms2.dll';
+ PCS, Colorant : LPcmsUInt16NumberArray): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsGetNamedColorList(xform: cmsHTRANSFORM ): LPcmsNAMEDCOLORLIST; StdCall; external 'lcms2.dll';
+FUNCTION cmsGetNamedColorList(xform: cmsHTRANSFORM ): LPcmsNAMEDCOLORLIST; StdCall; external LCMS2_SO;
-FUNCTION cmsAllocProfileSequenceDescription(ContextID: cmsContext; n: cmsUInt32Number):LPcmsSEQ; StdCall; external 'lcms2.dll';
-FUNCTION cmsDupProfileSequenceDescription(pseq: LPcmsSEQ):LPcmsSEQ; StdCall; external 'lcms2.dll';
-PROCEDURE cmsFreeProfileSequenceDescription(pseq: LPcmsSEQ); StdCall; external 'lcms2.dll';
+FUNCTION cmsAllocProfileSequenceDescription(ContextID: cmsContext; n: cmsUInt32Number):LPcmsSEQ; StdCall; external LCMS2_SO;
+FUNCTION cmsDupProfileSequenceDescription(pseq: LPcmsSEQ):LPcmsSEQ; StdCall; external LCMS2_SO;
+PROCEDURE cmsFreeProfileSequenceDescription(pseq: LPcmsSEQ); StdCall; external LCMS2_SO;
-FUNCTION cmsDictAlloc(ContextID: cmsContext): cmsHANDLE; StdCall; external 'lcms2.dll';
-PROCEDURE cmsDictFree(hDict: cmsHANDLE); StdCall; external 'lcms2.dll';
-FUNCTION cmsDictDup(hDict: cmsHANDLE): cmsHANDLE; StdCall; external 'lcms2.dll';
+FUNCTION cmsDictAlloc(ContextID: cmsContext): cmsHANDLE; StdCall; external LCMS2_SO;
+PROCEDURE cmsDictFree(hDict: cmsHANDLE); StdCall; external LCMS2_SO;
+FUNCTION cmsDictDup(hDict: cmsHANDLE): cmsHANDLE; StdCall; external LCMS2_SO;
-FUNCTION cmsDictAddEntry(hDict: cmsHANDLE; Name, Value: PWChar; DisplayName, DisplayValue : LPcmsMLU): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsDictGetEntryList(hDict: cmsHANDLE): LPcmsDICTentry; StdCall; external 'lcms2.dll';
-FUNCTION cmsDictNextEntry(e : LPcmsDICTentry): LPcmsDICTentry; StdCall; external 'lcms2.dll';
+FUNCTION cmsDictAddEntry(hDict: cmsHANDLE; Name, Value: PWChar; DisplayName, DisplayValue : LPcmsMLU): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsDictGetEntryList(hDict: cmsHANDLE): LPcmsDICTentry; StdCall; external LCMS2_SO;
+FUNCTION cmsDictNextEntry(e : LPcmsDICTentry): LPcmsDICTentry; StdCall; external LCMS2_SO;
-FUNCTION cmsCreateProfilePlaceholder(ContextID: cmsContext): cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsCreateProfilePlaceholder(ContextID: cmsContext): cmsHPROFILE; StdCall; external LCMS2_SO;
-FUNCTION cmsGetProfileContextID(hProfile: cmsHPROFILE):cmsContext; StdCall; external 'lcms2.dll';
-FUNCTION cmsGetTagCount(hProfile: cmsHPROFILE): cmsInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsGetTagSignature(hProfile: cmsHPROFILE; n: cmsUInt32Number): cmsTagSignature; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsTag(hProfile: cmsHPROFILE; sig: cmsTagSignature ): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsGetProfileContextID(hProfile: cmsHPROFILE):cmsContext; StdCall; external LCMS2_SO;
+FUNCTION cmsGetTagCount(hProfile: cmsHPROFILE): cmsInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsGetTagSignature(hProfile: cmsHPROFILE; n: cmsUInt32Number): cmsTagSignature; StdCall; external LCMS2_SO;
+FUNCTION cmsIsTag(hProfile: cmsHPROFILE; sig: cmsTagSignature ): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsReadTag(hProfile: cmsHPROFILE; sig: cmsTagSignature ): Pointer; StdCall; external 'lcms2.dll';
-FUNCTION cmsWriteTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; data: Pointer): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsLinkTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; dest: cmsTagSignature): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsTagLinkedTo(hProfile: cmsHPROFILE; sig: cmsTagSignature):cmsTagSignature; StdCall; external 'lcms2.dll';
+FUNCTION cmsReadTag(hProfile: cmsHPROFILE; sig: cmsTagSignature ): Pointer; StdCall; external LCMS2_SO;
+FUNCTION cmsWriteTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; data: Pointer): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsLinkTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; dest: cmsTagSignature): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsTagLinkedTo(hProfile: cmsHPROFILE; sig: cmsTagSignature):cmsTagSignature; StdCall; external LCMS2_SO;
-FUNCTION cmsReadRawTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; Buffer: Pointer; BufferSize: cmsUInt32Number): cmsInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsWriteRawTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; data: Pointer; Size: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsReadRawTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; Buffer: Pointer; BufferSize: cmsUInt32Number): cmsInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsWriteRawTag(hProfile: cmsHPROFILE; sig: cmsTagSignature; data: Pointer; Size: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsGetHeaderFlags(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external 'lcms2.dll';
-PROCEDURE cmsGetHeaderAttributes(hProfile: cmsHPROFILE; Flags: LPcmsUInt64Number); StdCall; external 'lcms2.dll';
-PROCEDURE cmsGetHeaderProfileID(hProfile: cmsHPROFILE; ProfileID: LPcmsUInt8Number); StdCall; external 'lcms2.dll';
+FUNCTION cmsGetHeaderFlags(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external LCMS2_SO;
+PROCEDURE cmsGetHeaderAttributes(hProfile: cmsHPROFILE; Flags: LPcmsUInt64Number); StdCall; external LCMS2_SO;
+PROCEDURE cmsGetHeaderProfileID(hProfile: cmsHPROFILE; ProfileID: LPcmsUInt8Number); StdCall; external LCMS2_SO;
-FUNCTION cmsGetHeaderRenderingIntent(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetHeaderFlags(hProfile: cmsHPROFILE; Flags: cmsUInt32Number); StdCall; external 'lcms2.dll';
-FUNCTION cmsGetHeaderManufacturer(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetHeaderManufacturer(hProfile: cmsHPROFILE; manufacturer: cmsUInt32Number ); StdCall; external 'lcms2.dll';
-FUNCTION cmsGetHeaderModel(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetHeaderModel(hProfile: cmsHPROFILE; model: cmsUInt32Number ); StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetHeaderAttributes(hProfile: cmsHPROFILE; Flags: cmsUInt64Number); StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetHeaderProfileID(hProfile: cmsHPROFILE; ProfileID: LPcmsUInt8Number); StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetHeaderRenderingIntent(hProfile: cmsHPROFILE; RenderingIntent: cmsUInt32Number ); StdCall; external 'lcms2.dll';
+FUNCTION cmsGetHeaderRenderingIntent(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetHeaderFlags(hProfile: cmsHPROFILE; Flags: cmsUInt32Number); StdCall; external LCMS2_SO;
+FUNCTION cmsGetHeaderManufacturer(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetHeaderManufacturer(hProfile: cmsHPROFILE; manufacturer: cmsUInt32Number ); StdCall; external LCMS2_SO;
+FUNCTION cmsGetHeaderModel(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetHeaderModel(hProfile: cmsHPROFILE; model: cmsUInt32Number ); StdCall; external LCMS2_SO;
+PROCEDURE cmsSetHeaderAttributes(hProfile: cmsHPROFILE; Flags: cmsUInt64Number); StdCall; external LCMS2_SO;
+PROCEDURE cmsSetHeaderProfileID(hProfile: cmsHPROFILE; ProfileID: LPcmsUInt8Number); StdCall; external LCMS2_SO;
+PROCEDURE cmsSetHeaderRenderingIntent(hProfile: cmsHPROFILE; RenderingIntent: cmsUInt32Number ); StdCall; external LCMS2_SO;
-FUNCTION cmsGetPCS(hProfile: cmsHPROFILE):cmsColorSpaceSignature; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetPCS(hProfile: cmsHPROFILE; pcs: cmsColorSpaceSignature); StdCall; external 'lcms2.dll';
-FUNCTION cmsGetColorSpace(hProfile: cmsHPROFILE): cmsColorSpaceSignature; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetColorSpace(hProfile: cmsHPROFILE; sig: cmsColorSpaceSignature); StdCall; external 'lcms2.dll';
-FUNCTION cmsGetDeviceClass(hProfile: cmsHPROFILE): cmsProfileClassSignature; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetDeviceClass(hProfile: cmsHPROFILE; sig: cmsProfileClassSignature); StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetProfileVersion(hProfile: cmsHPROFILE; Version: cmsFloat64Number); StdCall; external 'lcms2.dll';
-FUNCTION cmsGetProfileVersion(hProfile: cmsHPROFILE): cmsFloat64Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsGetPCS(hProfile: cmsHPROFILE):cmsColorSpaceSignature; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetPCS(hProfile: cmsHPROFILE; pcs: cmsColorSpaceSignature); StdCall; external LCMS2_SO;
+FUNCTION cmsGetColorSpace(hProfile: cmsHPROFILE): cmsColorSpaceSignature; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetColorSpace(hProfile: cmsHPROFILE; sig: cmsColorSpaceSignature); StdCall; external LCMS2_SO;
+FUNCTION cmsGetDeviceClass(hProfile: cmsHPROFILE): cmsProfileClassSignature; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetDeviceClass(hProfile: cmsHPROFILE; sig: cmsProfileClassSignature); StdCall; external LCMS2_SO;
+PROCEDURE cmsSetProfileVersion(hProfile: cmsHPROFILE; Version: cmsFloat64Number); StdCall; external LCMS2_SO;
+FUNCTION cmsGetProfileVersion(hProfile: cmsHPROFILE): cmsFloat64Number; StdCall; external LCMS2_SO;
-FUNCTION cmsGetEncodedICCversion(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external 'lcms2.dll';
-PROCEDURE cmsSetEncodedICCversion(hProfile: cmsHPROFILE; Version: cmsUInt32Number); StdCall; external 'lcms2.dll';
+FUNCTION cmsGetEncodedICCversion(hProfile: cmsHPROFILE): cmsUInt32Number; StdCall; external LCMS2_SO;
+PROCEDURE cmsSetEncodedICCversion(hProfile: cmsHPROFILE; Version: cmsUInt32Number); StdCall; external LCMS2_SO;
-FUNCTION cmsIsIntentSupported(hProfile: cmsHPROFILE; Intent: cmsUInt32Number; UsedDirection: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsMatrixShaper(hProfile: cmsHPROFILE): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIsCLUT(hProfile: cmsHPROFILE; Intent: cmsUInt32Number; UsedDirection: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION _cmsICCcolorSpace(OurNotation: Integer): cmsColorSpaceSignature; StdCall; external 'lcms2.dll';
-FUNCTION _cmsLCMScolorSpace(ProfileSpace: cmsColorSpaceSignature): Integer; StdCall; external 'lcms2.dll';
+FUNCTION cmsIsIntentSupported(hProfile: cmsHPROFILE; Intent: cmsUInt32Number; UsedDirection: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIsMatrixShaper(hProfile: cmsHPROFILE): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIsCLUT(hProfile: cmsHPROFILE; Intent: cmsUInt32Number; UsedDirection: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION _cmsICCcolorSpace(OurNotation: Integer): cmsColorSpaceSignature; StdCall; external LCMS2_SO;
+FUNCTION _cmsLCMScolorSpace(ProfileSpace: cmsColorSpaceSignature): Integer; StdCall; external LCMS2_SO;
-FUNCTION cmsChannelsOf( ColorSpace: cmsColorSpaceSignature): cmsUInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsChannelsOf( ColorSpace: cmsColorSpaceSignature): cmsUInt32Number; StdCall; external LCMS2_SO;
-FUNCTION cmsFormatterForColorspaceOfProfile(hProfile: cmsHPROFILE; nBytes: cmsUInt32Number; lIsFloat: cmsBool): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsFormatterForPCSOfProfile(hProfile: cmsHPROFILE; nBytes: cmsUInt32Number; lIsFloat: cmsBool): cmsUInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsFormatterForColorspaceOfProfile(hProfile: cmsHPROFILE; nBytes: cmsUInt32Number; lIsFloat: cmsBool): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsFormatterForPCSOfProfile(hProfile: cmsHPROFILE; nBytes: cmsUInt32Number; lIsFloat: cmsBool): cmsUInt32Number; StdCall; external LCMS2_SO;
FUNCTION cmsGetProfileInfo(hProfile: cmsHPROFILE; Info: cmsInfoType; LanguageCode, CountryCode: PAnsiChar;
- Buffer: PWChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external 'lcms2.dll';
+ Buffer: PWChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external LCMS2_SO;
FUNCTION cmsGetProfileInfoASCII(hProfile: cmsHPROFILE; Info: cmsInfoType; LanguageCode, CountryCode: PAnsiChar;
- Buffer: PAnsiChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external 'lcms2.dll';
+ Buffer: PAnsiChar; BufferSize: cmsUInt32Number): cmsUInt32Number; StdCall; external LCMS2_SO;
-FUNCTION cmsOpenIOhandlerFromFile(ContextID: cmsContext; FileName, AccessMode: PAnsiChar): LPcmsIOHANDLER; StdCall; external 'lcms2.dll';
-// FUNCTION cmsOpenIOhandlerFromStream(ContextID: cmsContext; FILE* Stream): LPcmsIOHANDLER; StdCall; external 'lcms2.dll';
-FUNCTION cmsOpenIOhandlerFromMem(ContextID: cmsContext; Buffer: Pointer; size: cmsUInt32Number; AccessMode: PAnsiChar): LPcmsIOHANDLER; StdCall; external 'lcms2.dll';
-FUNCTION cmsOpenIOhandlerFromNULL(ContextID: cmsContext): LPcmsIOHANDLER; StdCall; external 'lcms2.dll';
-FUNCTION cmsCloseIOhandler(io: LPcmsIOHANDLER): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsOpenIOhandlerFromFile(ContextID: cmsContext; FileName, AccessMode: PAnsiChar): LPcmsIOHANDLER; StdCall; external LCMS2_SO;
+// FUNCTION cmsOpenIOhandlerFromStream(ContextID: cmsContext; FILE* Stream): LPcmsIOHANDLER; StdCall; external LCMS2_SO;
+FUNCTION cmsOpenIOhandlerFromMem(ContextID: cmsContext; Buffer: Pointer; size: cmsUInt32Number; AccessMode: PAnsiChar): LPcmsIOHANDLER; StdCall; external LCMS2_SO;
+FUNCTION cmsOpenIOhandlerFromNULL(ContextID: cmsContext): LPcmsIOHANDLER; StdCall; external LCMS2_SO;
+FUNCTION cmsCloseIOhandler(io: LPcmsIOHANDLER): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsMD5computeID(hProfile: cmsHPROFILE): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsMD5computeID(hProfile: cmsHPROFILE): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsOpenProfileFromFile(ICCProfile : PAnsiChar; sAccess: PAnsiChar): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsOpenProfileFromFileTHR(ContextID: cmsContext; ICCProfile, sAccess: PAnsiChar): cmsHPROFILE; StdCall; external 'lcms2.dll';
-// FUNCTION CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char* sAccess): cmsHPROFILE; StdCall; external 'lcms2.dll';
-// FUNCTION CMSEXPORT cmsOpenProfileFromStreamTHR(ContextID: cmsContext; FILE* ICCProfile, const char* sAccess): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsOpenProfileFromMem(MemPtr: Pointer; dwSize: cmsUInt32Number): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsOpenProfileFromMemTHR(ContextID: cmsContext; MemPtr: Pointer; dwSize: cmsUInt32Number): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsOpenProfileFromIOhandlerTHR(ContextID: cmsContext; io: LPcmsIOHANDLER): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCloseProfile(hProfile: cmsHPROFILE): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsOpenProfileFromFile(ICCProfile : PAnsiChar; sAccess: PAnsiChar): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsOpenProfileFromFileTHR(ContextID: cmsContext; ICCProfile, sAccess: PAnsiChar): cmsHPROFILE; StdCall; external LCMS2_SO;
+// FUNCTION CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char* sAccess): cmsHPROFILE; StdCall; external LCMS2_SO;
+// FUNCTION CMSEXPORT cmsOpenProfileFromStreamTHR(ContextID: cmsContext; FILE* ICCProfile, const char* sAccess): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsOpenProfileFromMem(MemPtr: Pointer; dwSize: cmsUInt32Number): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsOpenProfileFromMemTHR(ContextID: cmsContext; MemPtr: Pointer; dwSize: cmsUInt32Number): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsOpenProfileFromIOhandlerTHR(ContextID: cmsContext; io: LPcmsIOHANDLER): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCloseProfile(hProfile: cmsHPROFILE): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsSaveProfileToFile(hProfile: cmsHPROFILE; FileName: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
-// FUNCTION CMSEXPORT cmsSaveProfileToStream(hProfile: cmsHPROFILE, FILE* Stream): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsSaveProfileToMem(hProfile: cmsHPROFILE; MemPtr: Pointer; BytesNeeded: LPcmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsSaveProfileToIOhandler(hProfile: cmsHPROFILE; io: LPcmsIOHANDLER):cmsUInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsSaveProfileToFile(hProfile: cmsHPROFILE; FileName: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
+// FUNCTION CMSEXPORT cmsSaveProfileToStream(hProfile: cmsHPROFILE, FILE* Stream): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsSaveProfileToMem(hProfile: cmsHPROFILE; MemPtr: Pointer; BytesNeeded: LPcmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsSaveProfileToIOhandler(hProfile: cmsHPROFILE; io: LPcmsIOHANDLER):cmsUInt32Number; StdCall; external LCMS2_SO;
FUNCTION cmsCreateRGBProfileTHR(ContextID: cmsContext;
WhitePoint: LPcmsCIExyY;
Primaries: LPcmsCIExyYTRIPLE;
- TransferFunction: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TransferFunction: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateRGBProfile(WhitePoint: LPcmsCIExyY;
Primaries: LPcmsCIExyYTRIPLE;
- TransferFunction: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TransferFunction: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateGrayProfileTHR(ContextID: cmsContext;
WhitePoint: LPcmsCIExyY;
- TransferFunction: LPcmsToneCurve): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TransferFunction: LPcmsToneCurve): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateGrayProfile(WhitePoint: LPcmsCIExyY;
- TransferFunction: LPcmsToneCurve): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TransferFunction: LPcmsToneCurve): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateLinearizationDeviceLinkTHR(ContextID: cmsContext;
ColorSpace: cmsColorSpaceSignature;
- TransferFunctions: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TransferFunctions: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateLinearizationDeviceLink(ColorSpace: cmsColorSpaceSignature;
- TransferFunctions: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TransferFunctions: LPLPcmsToneCurveArray): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateInkLimitingDeviceLinkTHR(ContextID: cmsContext;
- ColorSpace: cmsColorSpaceSignature; Limit: cmsFloat64Number): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ ColorSpace: cmsColorSpaceSignature; Limit: cmsFloat64Number): cmsHPROFILE; StdCall; external LCMS2_SO;
-FUNCTION cmsCreateInkLimitingDeviceLink(ColorSpace: cmsColorSpaceSignature; Limit: cmsFloat64Number): cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsCreateInkLimitingDeviceLink(ColorSpace: cmsColorSpaceSignature; Limit: cmsFloat64Number): cmsHPROFILE; StdCall; external LCMS2_SO;
-FUNCTION cmsCreateLab2ProfileTHR(ContextID: cmsContext; WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCreateLab2Profile(WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCreateLab4ProfileTHR(ContextID: cmsContext; WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCreateLab4Profile(WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsCreateLab2ProfileTHR(ContextID: cmsContext; WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCreateLab2Profile(WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCreateLab4ProfileTHR(ContextID: cmsContext; WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCreateLab4Profile(WhitePoint: LPcmsCIExyY): cmsHPROFILE; StdCall; external LCMS2_SO;
-FUNCTION cmsCreateXYZProfileTHR(ContextID: cmsContext): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCreateXYZProfile: cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsCreateXYZProfileTHR(ContextID: cmsContext): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCreateXYZProfile: cmsHPROFILE; StdCall; external LCMS2_SO;
-FUNCTION cmsCreate_sRGBProfileTHR(ContextID: cmsContext): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCreate_sRGBProfile: cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsCreate_sRGBProfileTHR(ContextID: cmsContext): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCreate_sRGBProfile: cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateBCHSWabstractProfileTHR(ContextID: cmsContext;
nLUTPoints: Integer;
@@ -1920,7 +1965,7 @@ FUNCTION cmsCreateBCHSWabstractProfileTHR(ContextID: cmsContext;
Hue,
Saturation: cmsFloat64Number;
TempSrc,
- TempDest: Integer): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TempDest: Integer): cmsHPROFILE; StdCall; external LCMS2_SO;
FUNCTION cmsCreateBCHSWabstractProfile( nLUTPoints: Integer;
Bright,
@@ -1928,16 +1973,16 @@ FUNCTION cmsCreateBCHSWabstractProfile( nLUTPoints: Integer;
Hue,
Saturation: cmsFloat64Number;
TempSrc,
- TempDest: Integer): cmsHPROFILE; StdCall; external 'lcms2.dll';
+ TempDest: Integer): cmsHPROFILE; StdCall; external LCMS2_SO;
-FUNCTION cmsCreateNULLProfileTHR(ContextID: cmsContext): cmsHPROFILE; StdCall; external 'lcms2.dll';
-FUNCTION cmsCreateNULLProfile: cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsCreateNULLProfileTHR(ContextID: cmsContext): cmsHPROFILE; StdCall; external LCMS2_SO;
+FUNCTION cmsCreateNULLProfile: cmsHPROFILE; StdCall; external LCMS2_SO;
// Converts a transform to a devicelink profile
-FUNCTION cmsTransform2DeviceLink(hTransform: cmsHTRANSFORM; Version: cmsFloat64Number; dwFlags: cmsUInt32Number): cmsHPROFILE; StdCall; external 'lcms2.dll';
+FUNCTION cmsTransform2DeviceLink(hTransform: cmsHTRANSFORM; Version: cmsFloat64Number; dwFlags: cmsUInt32Number): cmsHPROFILE; StdCall; external LCMS2_SO;
// Call with NULL as parameters to get the intent count
-FUNCTION cmsGetSupportedIntents(nMax: cmsUInt32Number; Codes: LPcmsUInt32Number; Descriptions: LPPAnsiChar): cmsUInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsGetSupportedIntents(nMax: cmsUInt32Number; Codes: LPcmsUInt32Number; Descriptions: LPPAnsiChar): cmsUInt32Number; StdCall; external LCMS2_SO;
FUNCTION cmsFLAGS_GRIDPOINTS(n: Integer): Integer; begin cmsFLAGS_GRIDPOINTS := (((n) and $FF) shl 16) end;
@@ -1948,14 +1993,14 @@ FUNCTION cmsCreateTransformTHR(ContextID: cmsContext;
Output: cmsHPROFILE;
OutputFormat: cmsUInt32Number;
Intent: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
FUNCTION cmsCreateTransform(Input: cmsHPROFILE;
InputFormat: cmsUInt32Number;
Output: cmsHPROFILE;
OutputFormat: cmsUInt32Number;
Intent: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
FUNCTION cmsCreateProofingTransformTHR(ContextID: cmsContext;
Input: cmsHPROFILE;
@@ -1965,7 +2010,7 @@ FUNCTION cmsCreateProofingTransformTHR(ContextID: cmsContext;
Proofing: cmsHPROFILE;
Intent: cmsUInt32Number;
ProofingIntent: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
FUNCTION cmsCreateProofingTransform(Input: cmsHPROFILE;
InputFormat: cmsUInt32Number;
@@ -1974,7 +2019,7 @@ FUNCTION cmsCreateProofingTransform(Input: cmsHPROFILE;
Proofing: cmsHPROFILE;
Intent: cmsUInt32Number;
ProofingIntent: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
FUNCTION cmsCreateMultiprofileTransformTHR(ContextID: cmsContext;
hProfiles: LPcmsHPROFILEArray;
@@ -1982,7 +2027,7 @@ FUNCTION cmsCreateMultiprofileTransformTHR(ContextID: cmsContext;
InputFormat: cmsUInt32Number;
OutputFormat: cmsUInt32Number;
Intent: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
FUNCTION cmsCreateMultiprofileTransform( hProfiles: LPcmsHPROFILEArray;
@@ -1990,7 +2035,7 @@ FUNCTION cmsCreateMultiprofileTransform( hProfiles: LPcmsHPROFILEArray;
InputFormat: cmsUInt32Number;
OutputFormat: cmsUInt32Number;
Intent: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
FUNCTION cmsCreateExtendedTransform(ContextID: cmsContext;
@@ -2003,23 +2048,23 @@ FUNCTION cmsCreateExtendedTransform(ContextID: cmsContext;
nGamutPCSposition: cmsUInt32Number;
InputFormat,
OutputFormat: cmsUInt32Number;
- dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external 'lcms2.dll';
-
-PROCEDURE cmsDeleteTransform(hTransform: cmsHTRANSFORM); StdCall; external 'lcms2.dll';
+ dwFlags: cmsUInt32Number): cmsHTRANSFORM; StdCall; external LCMS2_SO;
-PROCEDURE cmsDoTransform(Transform: cmsHTRANSFORM; InputBuffer, OutputBuffer: Pointer; size: cmsUInt32Number); StdCall; external 'lcms2.dll';
+PROCEDURE cmsDeleteTransform(hTransform: cmsHTRANSFORM); StdCall; external LCMS2_SO;
-PROCEDURE cmsSetAlarmCodes( NewAlarm: LPcmsUInt16NumberArray); StdCall; external 'lcms2.dll';
-PROCEDURE cmsGetAlarmCodes(NewAlarm: LPcmsUInt16NumberArray); StdCall; external 'lcms2.dll';
+PROCEDURE cmsDoTransform(Transform: cmsHTRANSFORM; InputBuffer, OutputBuffer: Pointer; size: cmsUInt32Number); StdCall; external LCMS2_SO;
+PROCEDURE cmsDoTransformStride(Transform: cmsHTRANSFORM; InputBuffer, OutputBuffer: Pointer; size: cmsUInt32Number; stride: cmsUInt32Number); StdCall; external LCMS2_SO;
+PROCEDURE cmsSetAlarmCodes( NewAlarm: LPcmsUInt16NumberArray); StdCall; external LCMS2_SO;
+PROCEDURE cmsGetAlarmCodes(NewAlarm: LPcmsUInt16NumberArray); StdCall; external LCMS2_SO;
// Adaptation state for absolute colorimetric intent
-FUNCTION cmsSetAdaptationState(d: cmsFloat64Number):cmsFloat64Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsSetAdaptationState(d: cmsFloat64Number):cmsFloat64Number; StdCall; external LCMS2_SO;
// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed
-FUNCTION cmsGetTransformContextID(hTransform: cmsHTRANSFORM):cmsContext; StdCall; external 'lcms2.dll';
+FUNCTION cmsGetTransformContextID(hTransform: cmsHTRANSFORM):cmsContext; StdCall; external LCMS2_SO;
// For backwards compatibility
-FUNCTION cmsChangeBuffersFormat(hTransform: cmsHTRANSFORM; InputFormat, OutputFormat: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsChangeBuffersFormat(hTransform: cmsHTRANSFORM; InputFormat, OutputFormat: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
// lcms2 unified method to access postscript color resources
@@ -2027,85 +2072,85 @@ FUNCTION cmsGetPostScriptColorResource(ContextID: cmsContext; RType: cmsPSReso
hProfile: cmsHPROFILE;
Intent: cmsUInt32Number;
dwFlags: cmsUInt32Number;
- io: LPcmsIOHANDLER): cmsUInt32Number; StdCall; external 'lcms2.dll';
+ io: LPcmsIOHANDLER): cmsUInt32Number; StdCall; external LCMS2_SO;
-FUNCTION cmsGetPostScriptCSA(ContextID: cmsContext; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number; Buffer: Pointer; dwBufferLen: cmsUInt32Number ): cmsUInt32Number; StdCall; external 'lcms2.dll';
-FUNCTION cmsGetPostScriptCRD(ContextID: cmsContext; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number; Buffer: Pointer; dwBufferLen: cmsUInt32Number): cmsUInt32Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsGetPostScriptCSA(ContextID: cmsContext; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number; Buffer: Pointer; dwBufferLen: cmsUInt32Number ): cmsUInt32Number; StdCall; external LCMS2_SO;
+FUNCTION cmsGetPostScriptCRD(ContextID: cmsContext; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number; Buffer: Pointer; dwBufferLen: cmsUInt32Number): cmsUInt32Number; StdCall; external LCMS2_SO;
// CGATS.13 parser
-FUNCTION cmsIT8Alloc: cmsHANDLE; StdCall; external 'lcms2.dll';
-PROCEDURE cmsIT8Free(hIT8: cmsHANDLE); StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8Alloc: cmsHANDLE; StdCall; external LCMS2_SO;
+PROCEDURE cmsIT8Free(hIT8: cmsHANDLE); StdCall; external LCMS2_SO;
// Tables
-FUNCTION cmsIT8TableCount(hIT8: cmsHANDLE): Integer; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SetTable(hIT8: cmsHANDLE; nTable: Integer): Integer; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8TableCount(hIT8: cmsHANDLE): Integer; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SetTable(hIT8: cmsHANDLE; nTable: Integer): Integer; StdCall; external LCMS2_SO;
// Persistence
-FUNCTION cmsIT8LoadFromFile(cFileName: PAnsiChar): cmsHANDLE; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8LoadFromMem(Ptr: Pointer; size :DWord): cmsHANDLE; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8LoadFromFile(cFileName: PAnsiChar): cmsHANDLE; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8LoadFromMem(Ptr: Pointer; size :DWord): cmsHANDLE; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SaveToFile(hIT8: cmsHANDLE; cFileName: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SaveToMem(hIT8: cmsHANDLE; MemPtr: Pointer; BytesNeeded: LPcmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SaveToFile(hIT8: cmsHANDLE; cFileName: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SaveToMem(hIT8: cmsHANDLE; MemPtr: Pointer; BytesNeeded: LPcmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
// Properties
-FUNCTION cmsIT8GetSheetType(hIT8: cmsHANDLE): PAnsiChar; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SetSheetType(hIT8: cmsHANDLE; TheType: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8GetSheetType(hIT8: cmsHANDLE): PAnsiChar; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SetSheetType(hIT8: cmsHANDLE; TheType: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SetComment(hIT8: cmsHANDLE; cComment: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetComment(hIT8: cmsHANDLE; cComment: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SetPropertyStr(hIT8: cmsHANDLE; cProp, Str: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SetPropertyDbl(hIT8: cmsHANDLE; cProp: PAnsiChar; Val: Double): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SetPropertyHex(hIT8: cmsHANDLE; cProp: PAnsiChar; Val: Integer): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SetPropertyUncooked(hIT8: cmsHANDLE; Key, Buffer: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetPropertyStr(hIT8: cmsHANDLE; cProp, Str: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SetPropertyDbl(hIT8: cmsHANDLE; cProp: PAnsiChar; Val: Double): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SetPropertyHex(hIT8: cmsHANDLE; cProp: PAnsiChar; Val: Integer): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SetPropertyUncooked(hIT8: cmsHANDLE; Key, Buffer: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8GetProperty(hIT8: cmsHANDLE; cProp: PAnsiChar): PAnsiChar; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8GetPropertyDbl(hIT8: cmsHANDLE; cProp: PAnsiChar): Double; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8EnumProperties(hIT8: cmsHANDLE; var PropertyNames: LPPAnsiChar): Integer; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8GetProperty(hIT8: cmsHANDLE; cProp: PAnsiChar): PAnsiChar; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8GetPropertyDbl(hIT8: cmsHANDLE; cProp: PAnsiChar): Double; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8EnumProperties(hIT8: cmsHANDLE; var PropertyNames: LPPAnsiChar): Integer; StdCall; external LCMS2_SO;
// Datasets
-FUNCTION cmsIT8GetDataRowCol(hIT8: cmsHANDLE; row, col: Integer): PAnsiChar; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8GetDataRowColDbl(hIT8: cmsHANDLE; row, col: Integer): Double; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8GetDataRowCol(hIT8: cmsHANDLE; row, col: Integer): PAnsiChar; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8GetDataRowColDbl(hIT8: cmsHANDLE; row, col: Integer): Double; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SetDataRowCol(hIT8: cmsHANDLE; row, col: Integer; Val: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8SetDataRowColDbl(hIT8: cmsHANDLE; row, col: Integer; Val: Double): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetDataRowCol(hIT8: cmsHANDLE; row, col: Integer; Val: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8SetDataRowColDbl(hIT8: cmsHANDLE; row, col: Integer; Val: Double): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8GetData(hIT8: cmsHANDLE; cPatch, cSample: PAnsiChar): PAnsiChar; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8GetData(hIT8: cmsHANDLE; cPatch, cSample: PAnsiChar): PAnsiChar; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8GetDataDbl(hIT8: cmsHANDLE;cPatch, cSample: PAnsiChar): Double; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8GetDataDbl(hIT8: cmsHANDLE;cPatch, cSample: PAnsiChar): Double; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SetData(hIT8: cmsHANDLE; cPatch, cSample, Val: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetData(hIT8: cmsHANDLE; cPatch, cSample, Val: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SetDataDbl(hIT8: cmsHANDLE; cPatch, cSample: PAnsiChar; Val: Double): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetDataDbl(hIT8: cmsHANDLE; cPatch, cSample: PAnsiChar; Val: Double): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8SetDataFormat(hIT8: cmsHANDLE; n: Integer; Sample: PAnsiChar): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8EnumDataFormat(hIT8: cmsHANDLE; var SampleNames: LPPAnsiChar): Integer; StdCall; external 'lcms2.dll';
-FUNCTION cmsIT8GetPatchName(hIT8: cmsHANDLE; nPatch: Integer; Buffer: PAnsiChar): PAnsiChar; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetDataFormat(hIT8: cmsHANDLE; n: Integer; Sample: PAnsiChar): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8EnumDataFormat(hIT8: cmsHANDLE; var SampleNames: LPPAnsiChar): Integer; StdCall; external LCMS2_SO;
+FUNCTION cmsIT8GetPatchName(hIT8: cmsHANDLE; nPatch: Integer; Buffer: PAnsiChar): PAnsiChar; StdCall; external LCMS2_SO;
// The LABEL extension
-FUNCTION cmsIT8SetTableByLabel(hIT8: cmsHANDLE; cSet, cField, ExpectedType: PAnsiChar): Integer; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8SetTableByLabel(hIT8: cmsHANDLE; cSet, cField, ExpectedType: PAnsiChar): Integer; StdCall; external LCMS2_SO;
-FUNCTION cmsIT8FindDataFormat(hIT8: cmsHANDLE; cSample: PAnsiChar): Integer; StdCall; external 'lcms2.dll';
+FUNCTION cmsIT8FindDataFormat(hIT8: cmsHANDLE; cSample: PAnsiChar): Integer; StdCall; external LCMS2_SO;
// Formatter for double
-PROCEDURE cmsIT8DefineDblFormat(hIT8: cmsHANDLE; Formatter: PAnsiChar); StdCall; external 'lcms2.dll';
+PROCEDURE cmsIT8DefineDblFormat(hIT8: cmsHANDLE; Formatter: PAnsiChar); StdCall; external LCMS2_SO;
+
+FUNCTION cmsGBDAlloc(ContextID: cmsContext):cmsHANDLE; StdCall; external LCMS2_SO;
+PROCEDURE cmsGBDFree(hGBD: cmsHANDLE); StdCall; external LCMS2_SO;
+FUNCTION cmsGDBAddPoint(hGBD: cmsHANDLE; Lab: LPcmsCIELab): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsGDBCompute(hGDB: cmsHANDLE; dwFlags: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsGDBCheckPoint(hGBD: cmsHANDLE; Lab: LPcmsCIELab): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsGBDAlloc(ContextID: cmsContext):cmsHANDLE; StdCall; external 'lcms2.dll';
-PROCEDURE cmsGBDFree(hGBD: cmsHANDLE); StdCall; external 'lcms2.dll';
-FUNCTION cmsGDBAddPoint(hGBD: cmsHANDLE; Lab: LPcmsCIELab): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsGDBCompute(hGDB: cmsHANDLE; dwFlags: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsGDBCheckPoint(hGBD: cmsHANDLE; Lab: LPcmsCIELab): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsDetectBlackPoint( BlackPoint: LPcmsCIEXYZ; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
+FUNCTION cmsDetectDestinationBlackPoint( BlackPoint: LPcmsCIEXYZ; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsDetectBlackPoint( BlackPoint: LPcmsCIEXYZ; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
-FUNCTION cmsDetectDestinationBlackPoint( BlackPoint: LPcmsCIEXYZ; hProfile: cmsHPROFILE; Intent: cmsUInt32Number; dwFlags: cmsUInt32Number): cmsBool; StdCall; external 'lcms2.dll';
+FUNCTION cmsDetectTAC(hProfile: cmsHPROFILE): cmsFloat64Number; StdCall; external LCMS2_SO;
-FUNCTION cmsDetectTAC(hProfile: cmsHPROFILE): cmsFloat64Number; StdCall; external 'lcms2.dll';
+FUNCTION cmsDesaturateLab(Lab: LPcmsCIELab; amax, amin, bmax, bmin: cmsFloat64Number): cmsBool; StdCall; external LCMS2_SO;
-FUNCTION cmsDesaturateLab(Lab: LPcmsCIELab; amax, amin, bmax, bmin: cmsFloat64Number): cmsBool; StdCall; external 'lcms2.dll';
-
END.
diff --git a/utils/jpgicc/jpgicc.c b/utils/jpgicc/jpgicc.c
index 3b18b54..e129a77 100644
--- a/utils/jpgicc/jpgicc.c
+++ b/utils/jpgicc/jpgicc.c
@@ -72,13 +72,6 @@ static struct my_error_mgr {
cmsUInt16Number Alarm[4] = {128,128,128,0};
-// Out of mem
-static
-void OutOfMem(size_t size)
-{
- FatalError("Out of memory on allocating %d bytes.", size);
-}
-
static
void my_error_exit (j_common_ptr cinfo)
@@ -840,7 +833,7 @@ void DoEmbedProfile(const char* ProfileFile)
fclose(f);
EmbedBuffer[EmbedLen] = 0;
- write_icc_profile (&Compressor, EmbedBuffer, EmbedLen);
+ write_icc_profile (&Compressor, EmbedBuffer, (unsigned int) EmbedLen);
free(EmbedBuffer);
}
diff --git a/utils/psicc/psicc.c b/utils/psicc/psicc.c
index 1c3fe6c..9d6a280 100644
--- a/utils/psicc/psicc.c
+++ b/utils/psicc/psicc.c
@@ -185,7 +185,7 @@ void GenerateCRD(void)
if (n == 0) return;
Buffer = (char*) malloc(n + 1);
- cmsGetPostScriptCRD(0, hProfile, Intent, dwFlags, Buffer, n);
+ cmsGetPostScriptCRD(0, hProfile, Intent, dwFlags, Buffer, (cmsUInt32Number) n);
Buffer[n] = 0;
fprintf(OutFile, "%s", Buffer);
diff --git a/utils/tificc/tificc.c b/utils/tificc/tificc.c
index 76fb15a..5101932 100644
--- a/utils/tificc/tificc.c
+++ b/utils/tificc/tificc.c
@@ -670,7 +670,7 @@ void DoEmbedProfile(TIFF* Out, const char* ProfileFile)
return;
}
- EmbedLen = fread(EmbedBuffer, 1, size, f);
+ EmbedLen = (cmsUInt32Number) fread(EmbedBuffer, 1, (size_t) size, f);
if (EmbedLen != size)
FatalError("Cannot read %ld bytes to %s", size, ProfileFile);
diff --git a/utils/transicc/transicc.1 b/utils/transicc/transicc.1
index d99eb25..eb52ac9 100644
--- a/utils/transicc/transicc.1
+++ b/utils/transicc/transicc.1
@@ -1,5 +1,5 @@
.\"Shiju P. Nair September 30, 2004
-.TH ICCTRANS 1 "September 30, 2004"
+.TH TRANSICC 1 "MAY 30, 2011"
.SH NAME
icctrans - little cms ColorSpace conversion calculator.
.SH SYNOPSIS