Update lcms (#544)

Update to mm2/Little-CMS@0e8234e090
This commit is contained in:
Matthieu Darbois 2016-04-30 17:58:04 +02:00
parent 72deb588cb
commit 9a20f8e8d1
32 changed files with 1630 additions and 975 deletions

View File

@ -877,6 +877,8 @@ int main(int argc, char **argv)
printf("<DartMeasurement name=\"NumberOfPixelsWithDifferences_%d\" type=\"numeric/int\"> %d </DartMeasurement> \n", it_comp, nbPixelDiff);
printf("<DartMeasurement name=\"ComponentError_%d\" type=\"numeric/double\"> %f </DartMeasurement> \n", it_comp, sumDiff);
printf("<DartMeasurement name=\"PEAK_%d\" type=\"numeric/double\"> %f </DartMeasurement> \n", it_comp, PEAK);
printf("<DartMeasurement name=\"MSE_%d\" type=\"numeric/double\"> %f </DartMeasurement> \n", it_comp, MSE);
#ifdef OPJ_HAVE_LIBPNG
{

View File

@ -27,9 +27,9 @@ dbabd772b1e53959e1e1c4bdf58e0108 issue135.j2k_1.pgx
aa7461b31e14641586803b23b7fb04f2 issue142.j2k_0.pgx
a809006e7a0c1eed68bc86c96af43fe3 issue142.j2k_1.pgx
74f7a7a194a74a947245b843c62c4054 issue142.j2k_2.pgx
c44662b1f7fe01caa2ebf3ad62948e3e issue171.jp2_0.pgx
f70e8a4e5dbefeb44d50edd79b6c4cf6 issue171.jp2_1.pgx
18bc167a1c851db2fd9f8c7af3289134 issue171.jp2_2.pgx
f9d1ada7f0f16c8c4f929217a1924416 issue171.jp2_0.pgx
0d4a8507e226130bc44ef7de7e5539f6 issue171.jp2_1.pgx
fde95f3c3bd8639b2258332eb6f658e4 issue171.jp2_2.pgx
adda4f5e46845b96dd3df14a76aa7229 issue188_beach_64bitsbox.jp2_0.pgx
90a9709c166019d1e101e7b96d257ed9 issue188_beach_64bitsbox.jp2_1.pgx
37e23d2df06ee60bf0f9f5e1c16054d8 issue188_beach_64bitsbox.jp2_2.pgx
@ -291,10 +291,10 @@ ddfff2ce2df4a9102518c92a362e6d25 dwt_interleave_h.gsr105.jp2_2.pgx
b01ed87dbac424bc820b2ac590e4884e issue236-ESYCC-CDEF.jp2_0.pgx
2635cc00b1e18ef11adcba09e845d459 issue236-ESYCC-CDEF.jp2_1.pgx
f9c95d0aec2f6e7b814fa1d09edcdbda issue236-ESYCC-CDEF.jp2_2.pgx
5f0c1d5c5127c1eabb86a5e0112f139b issue559-eci-090-CIELab.jp2_0.pgx
cdae87485eaada56be3671eec39452e6 issue559-eci-090-CIELab.jp2_1.pgx
e163102afcc857cf001337178241f518 issue559-eci-090-CIELab.jp2_2.pgx
b004b2e08b0dfb217c131b353cf157eb issue559-eci-091-CIELab.jp2_0.pgx
2400da6b8ed6b1747b9913af544580f9 issue559-eci-091-CIELab.jp2_1.pgx
cf73dda887967928dbcf5cc87ab204cc issue559-eci-091-CIELab.jp2_2.pgx
4c3a5c669aaaa330134c7014b26ed06f issue559-eci-090-CIELab.jp2_0.pgx
d6698c71d1ed3861edaadc430af928eb issue559-eci-090-CIELab.jp2_1.pgx
04f3ec1fea6049769c43b1ac3b05794e issue559-eci-090-CIELab.jp2_2.pgx
a190e10941e6145e69816c909f832c1a issue559-eci-091-CIELab.jp2_0.pgx
3fccf3c7ecd3b9de46b94b53a1fa0362 issue559-eci-091-CIELab.jp2_1.pgx
f3081c8e9e9a175f223382a7443b480f issue559-eci-091-CIELab.jp2_2.pgx
3bf91c974abc17e520c6a5efa883a58a issue653-zero-unknownbox.jp2.png

View File

@ -1,5 +1,5 @@
Little CMS
Copyright (c) 1998-2010 Marti Maria Saguer
Copyright (c) 1998-2011 Marti Maria Saguer
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2014 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -23,7 +23,7 @@
//
//---------------------------------------------------------------------------------
//
// Version 2.6
// Version 2.8beta0
//
#ifndef _lcms2_H
@ -75,7 +75,7 @@ extern "C" {
#endif
// Version/release
#define LCMS_VERSION 2060
#define LCMS_VERSION 2080
// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@ -173,46 +173,45 @@ typedef int cmsBool;
# define CMS_IS_WINDOWS_ 1
#endif
// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here.
// you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar
// Try to detect big endian platforms. This list can be endless, so primarily rely on the configure script
// on Unix-like systems, and allow it to be set on the compiler command line using
// -DCMS_USE_BIG_ENDIAN or something similar
#ifdef CMS_USE_BIG_ENDIAN // set at compiler command line takes overall precedence
#if defined(__sgi__) || defined(__sgi) || defined(sparc)
# define CMS_USE_BIG_ENDIAN 1
#endif
#if defined(__s390__) || defined(__s390x__)
# define CMS_USE_BIG_ENDIAN 1
#endif
# ifdef TARGET_CPU_PPC
# if TARGET_CPU_PPC
# define CMS_USE_BIG_ENDIAN 1
# endif
# if CMS_USE_BIG_ENDIAN == 0
# undef CMS_USE_BIG_ENDIAN
# endif
#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_CPU_PPC)
# define CMS_USE_BIG_ENDIAN 1
# if defined (__GNUC__) && defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
# if __BYTE_ORDER == __LITTLE_ENDIAN
// // Don't use big endian for PowerPC little endian mode
# undef CMS_USE_BIG_ENDIAN
# endif
# endif
#endif
#else // CMS_USE_BIG_ENDIAN
// WORDS_BIGENDIAN takes precedence
#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
# define CMS_USE_BIG_ENDIAN 1
#endif
# ifdef WORDS_BIGENDIAN // set by configure (or explicitly on compiler command line)
# define CMS_USE_BIG_ENDIAN 1
# else // WORDS_BIGENDIAN
// Fall back to platform/compiler specific tests
# if defined(__sgi__) || defined(__sgi) || defined(sparc)
# define CMS_USE_BIG_ENDIAN 1
# endif
# if defined(__s390__) || defined(__s390x__)
# define CMS_USE_BIG_ENDIAN 1
# endif
# ifdef macintosh
# ifdef __BIG_ENDIAN__
# define CMS_USE_BIG_ENDIAN 1
# endif
# ifdef __LITTLE_ENDIAN__
# undef CMS_USE_BIG_ENDIAN
# endif
# endif
# endif // WORDS_BIGENDIAN
# if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__)
# define CMS_USE_BIG_ENDIAN 1
# endif
#endif // CMS_USE_BIG_ENDIAN
#ifdef macintosh
# ifdef __BIG_ENDIAN__
# define CMS_USE_BIG_ENDIAN 1
# endif
# ifdef __LITTLE_ENDIAN__
# undef CMS_USE_BIG_ENDIAN
# endif
#endif
// Calling convention -- this is hardly platform and compiler dependent
#ifdef CMS_IS_WINDOWS_
@ -221,7 +220,7 @@ typedef int cmsBool;
# define CMSEXPORT __stdcall _export
# define CMSAPI
# else
# define CMSEXPORT _stdcall
# define CMSEXPORT __stdcall
# ifdef CMS_DLL_BUILD
# define CMSAPI __declspec(dllexport)
# else
@ -383,7 +382,8 @@ typedef enum {
cmsSigViewingCondDescTag = 0x76756564, // 'vued'
cmsSigViewingConditionsTag = 0x76696577, // 'view'
cmsSigVcgtTag = 0x76636774, // 'vcgt'
cmsSigMetaTag = 0x6D657461 // 'meta'
cmsSigMetaTag = 0x6D657461, // 'meta'
cmsSigArgyllArtsTag = 0x61727473 // 'arts'
} cmsTagSignature;
@ -516,7 +516,7 @@ typedef enum {
cmsSigNamedColorElemType = 0x6E636C20, // 'ncl '
cmsSigLabV2toV4 = 0x32203420, // '2 4 '
cmsSigLabV4toV2 = 0x34203220, // '4 2 '
// Identities
cmsSigIdentityElemType = 0x69646E20, // 'idn '
@ -524,7 +524,8 @@ typedef enum {
cmsSigLab2FloatPCS = 0x64326C20, // 'd2l '
cmsSigFloatPCS2Lab = 0x6C326420, // 'l2d '
cmsSigXYZ2FloatPCS = 0x64327820, // 'd2x '
cmsSigFloatPCS2XYZ = 0x78326420 // 'x2d '
cmsSigFloatPCS2XYZ = 0x78326420, // 'x2d '
cmsSigClipNegativesElemType = 0x636c7020 // 'clp '
} cmsStageSignature;
@ -898,7 +899,7 @@ typedef void* cmsHTRANSFORM;
#define TYPE_ARGB_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|SWAPFIRST_SH(1))
#define TYPE_BGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_BGRA_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_ABGR_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(4)|DOSWAP_SH(1))
#define TYPE_CMYK_FLT (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(4))
@ -1002,6 +1003,10 @@ typedef struct {
} cmsICCViewingConditions;
// Get LittleCMS version (for shared objects) -----------------------------------------------------------------------------
CMSAPI int CMSEXPORT cmsGetEncodedCMMversion(void);
// Support of non-standard functions --------------------------------------------------------------------------------------
CMSAPI int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
@ -1380,7 +1385,7 @@ typedef struct {
typedef struct {
cmsUInt32Number n;
cmsContext ContextID;
cmsContext ContextID;
cmsPSEQDESC* seq;
} cmsSEQ;
@ -1480,7 +1485,7 @@ CMSAPI int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignat
CMSAPI cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace);
// Build a suitable formatter for the colorspace of this profile
// Build a suitable formatter for the colorspace of this profile. nBytes=1 means 8 bits, nBytes=2 means 16 bits.
CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
CMSAPI cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
@ -1509,6 +1514,7 @@ CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream);
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode);
CMSAPI cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID);
CMSAPI cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile);
CMSAPI cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io);
// MD5 message digest --------------------------------------------------------------------------------------------------
@ -1643,6 +1649,12 @@ CMSAPI cmsUInt32Number CMSEXPORT cmsGetSupportedIntentsTHR(cmsContext ContextID
#define cmsFLAGS_CLUT_POST_LINEARIZATION 0x0001 // create postlinearization tables if possible
#define cmsFLAGS_CLUT_PRE_LINEARIZATION 0x0010 // create prelinearization tables if possible
// Specific to unbounded mode
#define cmsFLAGS_NONEGATIVES 0x8000 // Prevent negative numbers in floating point transforms
// Copy alpha channels when transforming
#define cmsFLAGS_COPY_ALPHA 0x04000000 // Alpha channels are copied on cmsDoTransform()
// Fine-tune control over number of gridpoints
#define cmsFLAGS_GRIDPOINTS(n) (((n) & 0xFF) << 16)
@ -1720,12 +1732,22 @@ CMSAPI void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
void * OutputBuffer,
cmsUInt32Number Size);
CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform,
CMSAPI void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform, // Deprecated
const void * InputBuffer,
void * OutputBuffer,
cmsUInt32Number Size,
cmsUInt32Number Stride);
CMSAPI void CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM Transform,
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
cmsUInt32Number BytesPerLineIn,
cmsUInt32Number BytesPerLineOut,
cmsUInt32Number BytesPerPlaneIn,
cmsUInt32Number BytesPerPlaneOut);
CMSAPI void CMSEXPORT cmsSetAlarmCodes(const cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
CMSAPI void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -342,8 +342,8 @@ struct _cmstransform_struct;
typedef cmsUInt8Number* (* cmsFormatter16)(register struct _cmstransform_struct* CMMcargo,
register cmsUInt16Number Values[],
register cmsUInt8Number* Buffer,
register cmsUInt32Number Stride);
register cmsUInt8Number* Buffer,
register cmsUInt32Number Stride);
typedef cmsUInt8Number* (* cmsFormatterFloat)(struct _cmstransform_struct* CMMcargo,
cmsFloat32Number Values[],
@ -571,11 +571,28 @@ typedef struct {
//----------------------------------------------------------------------------------------------------------
// Full xform
typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo,
typedef struct {
cmsUInt32Number BytesPerLineIn;
cmsUInt32Number BytesPerLineOut;
cmsUInt32Number BytesPerPlaneIn;
cmsUInt32Number BytesPerPlaneOut;
} cmsStride;
typedef void (* _cmsTransformFn)(struct _cmstransform_struct *CMMcargo, // Legacy function, handles just ONE scanline.
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number Size,
cmsUInt32Number Stride);
cmsUInt32Number Stride); // Stride in bytes to the next plana in planar formats
typedef void (*_cmsTransform2Fn)(struct _cmstransform_struct *CMMcargo,
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride);
typedef cmsBool (* _cmsTransformFactory)(_cmsTransformFn* xform,
void** UserData,
@ -585,6 +602,14 @@ typedef cmsBool (* _cmsTransformFactory)(_cmsTransformFn* xform,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags);
typedef cmsBool (* _cmsTransform2Factory)(_cmsTransform2Fn* xform,
void** UserData,
_cmsFreeUserDataFn* FreePrivateDataFn,
cmsPipeline** Lut,
cmsUInt32Number* InputFormat,
cmsUInt32Number* OutputFormat,
cmsUInt32Number* dwFlags);
// Retrieve user data as specified by the factory
CMSAPI void CMSEXPORT _cmsSetTransformUserData(struct _cmstransform_struct *CMMcargo, void* ptr, _cmsFreeUserDataFn FreePrivateDataFn);
@ -599,7 +624,10 @@ typedef struct {
cmsPluginBase base;
// Transform entry point
_cmsTransformFactory Factory;
union {
_cmsTransformFactory legacy_xform;
_cmsTransform2Factory xform;
} factories;
} cmsPluginTransform;

481
thirdparty/liblcms2/src/cmsalpha.c vendored Normal file
View File

@ -0,0 +1,481 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//---------------------------------------------------------------------------------
//
#include "lcms2_internal.h"
// Alpha copy ------------------------------------------------------------------------------------------------------------------
// Floor to byte, taking care of saturation
cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d)
{
d += 0.5;
if (d <= 0) return 0;
if (d >= 255.0) return 255;
return (cmsUInt8Number) _cmsQuickFloorWord(d);
}
// Return the size in bytes of a given formatter
static
int trueBytesSize(cmsUInt32Number Format)
{
int fmt_bytes = T_BYTES(Format);
// For double, the T_BYTES field returns zero
if (fmt_bytes == 0)
return sizeof(double);
// Otherwise, it is already correct for all formats
return fmt_bytes;
}
// Several format converters
typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src);
// From 8
static
void copy8(void* dst, const void* src)
{
memmove(dst, src, 1);
}
static
void from8to16(void* dst, const void* src)
{
cmsUInt8Number n = *(cmsUInt8Number*)src;
*(cmsUInt16Number*) dst = FROM_8_TO_16(n);
}
static
void from8toFLT(void* dst, const void* src)
{
*(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f;
}
static
void from8toDBL(void* dst, const void* src)
{
*(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0;
}
static
void from8toHLF(void* dst, const void* src)
{
cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f;
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
}
// From 16
static
void from16to8(void* dst, const void* src)
{
cmsUInt16Number n = *(cmsUInt16Number*)src;
*(cmsUInt8Number*) dst = FROM_16_TO_8(n);
}
static
void copy16(void* dst, const void* src)
{
memmove(dst, src, 2);
}
void from16toFLT(void* dst, const void* src)
{
*(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
}
void from16toDBL(void* dst, const void* src)
{
*(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
}
static
void from16toHLF(void* dst, const void* src)
{
cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f;
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
}
// From Float
static
void fromFLTto8(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
}
static
void fromFLTto16(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
}
static
void copy32(void* dst, const void* src)
{
memmove(dst, src, sizeof(cmsFloat32Number));
}
static
void fromFLTtoDBL(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
*(cmsFloat64Number*)dst = (cmsFloat64Number)n;
}
static
void fromFLTtoHLF(void* dst, const void* src)
{
cmsFloat32Number n = *(cmsFloat32Number*)src;
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
}
// From HALF
static
void fromHLFto8(void* dst, const void* src)
{
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
}
static
void fromHLFto16(void* dst, const void* src)
{
cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
}
static
void fromHLFtoFLT(void* dst, const void* src)
{
*(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src);
}
static
void fromHLFtoDBL(void* dst, const void* src)
{
*(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src);
}
// From double
static
void fromDBLto8(void* dst, const void* src)
{
cmsFloat64Number n = *(cmsFloat64Number*)src;
*(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
}
static
void fromDBLto16(void* dst, const void* src)
{
cmsFloat64Number n = *(cmsFloat64Number*)src;
*(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
}
static
void fromDBLtoFLT(void* dst, const void* src)
{
cmsFloat64Number n = *(cmsFloat64Number*)src;
*(cmsFloat32Number*)dst = (cmsFloat32Number) n;
}
static
void fromDBLtoHLF(void* dst, const void* src)
{
cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src;
*(cmsUInt16Number*)dst = _cmsFloat2Half(n);
}
static
void copy64(void* dst, const void* src)
{
memmove(dst, src, sizeof(cmsFloat64Number));
}
// Returns the position (x or y) of the formatter in the table of functions
static
int FormatterPos(cmsUInt32Number frm)
{
int b = T_BYTES(frm);
if (b == 0 && T_FLOAT(frm))
return 4; // DBL
if (b == 2 && T_FLOAT(frm))
return 2; // HLF
if (b == 4 && T_FLOAT(frm))
return 3; // FLT
if (b == 2 && !T_FLOAT(frm))
return 1; // 16
if (b == 1 && !T_FLOAT(frm))
return 0; // 8
return -1; // not recognized
}
// Obtains a alpha-to-alpha funmction formatter
static
cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out)
{
static cmsFormatterAlphaFn FormattersAlpha[5][5] = {
/* from 8 */ { copy8, from8to16, from8toHLF, from8toFLT, from8toDBL },
/* from 16*/ { from16to8, copy16, from16toHLF, from16toFLT, from16toDBL },
/* from HLF*/ { fromHLFto8, fromHLFto16, copy16, fromHLFtoFLT, fromHLFtoDBL },
/* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTtoHLF, copy32, fromFLTtoDBL },
/* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLtoHLF, fromDBLtoFLT, copy64 }};
int in_n = FormatterPos(in);
int out_n = FormatterPos(out);
if (in_n < 0 || out_n < 0 || in_n > 4 || out_n > 4) {
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width");
return NULL;
}
return FormattersAlpha[in_n][out_n];
}
// This function computes the distance from each component to the next one in bytes.
static
void ComputeIncrementsForChunky(cmsUInt32Number Format,
cmsUInt32Number ComponentStartingOrder[],
cmsUInt32Number ComponentPointerIncrements[])
{
cmsUInt32Number channels[cmsMAXCHANNELS];
int extra = T_EXTRA(Format);
int nchannels = T_CHANNELS(Format);
int total_chans = nchannels + extra;
int i;
int channelSize = trueBytesSize(Format);
int pixelSize = channelSize * total_chans;
// Sanity check
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
return;
memset(channels, 0, sizeof(channels));
// Separation is independent of starting point and only depends on channel size
for (i = 0; i < extra; i++)
ComponentPointerIncrements[i] = pixelSize;
// Handle do swap
for (i = 0; i < total_chans; i++)
{
if (T_DOSWAP(Format)) {
channels[i] = total_chans - i - 1;
}
else {
channels[i] = i;
}
}
// Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012
if (T_SWAPFIRST(Format) && total_chans > 1) {
cmsUInt32Number tmp = channels[0];
for (i = 0; i < total_chans-1; i++)
channels[i] = channels[i + 1];
channels[total_chans - 1] = tmp;
}
// Handle size
if (channelSize > 1)
for (i = 0; i < total_chans; i++) {
channels[i] *= channelSize;
}
for (i = 0; i < extra; i++)
ComponentStartingOrder[i] = channels[i + nchannels];
}
// On planar configurations, the distance is the stride added to any non-negative
static
void ComputeIncrementsForPlanar(cmsUInt32Number Format,
cmsUInt32Number BytesPerPlane,
cmsUInt32Number ComponentStartingOrder[],
cmsUInt32Number ComponentPointerIncrements[])
{
cmsUInt32Number channels[cmsMAXCHANNELS];
int extra = T_EXTRA(Format);
int nchannels = T_CHANNELS(Format);
int total_chans = nchannels + extra;
int i;
int channelSize = trueBytesSize(Format);
// Sanity check
if (total_chans <= 0 || total_chans >= cmsMAXCHANNELS)
return;
memset(channels, 0, sizeof(channels));
// Separation is independent of starting point and only depends on channel size
for (i = 0; i < extra; i++)
ComponentPointerIncrements[i] = channelSize;
// Handle do swap
for (i = 0; i < total_chans; i++)
{
if (T_DOSWAP(Format)) {
channels[i] = total_chans - i - 1;
}
else {
channels[i] = i;
}
}
// Handle swap first (ROL of positions), example CMYK -> KCMY | 0123 -> 3012
if (T_SWAPFIRST(Format) && total_chans > 0) {
cmsUInt32Number tmp = channels[0];
for (i = 0; i < total_chans - 1; i++)
channels[i] = channels[i + 1];
channels[total_chans - 1] = tmp;
}
// Handle size
for (i = 0; i < total_chans; i++) {
channels[i] *= BytesPerPlane;
}
for (i = 0; i < extra; i++)
ComponentStartingOrder[i] = channels[i + nchannels];
}
// Dispatcher por chunky and planar RGB
static
void ComputeComponentIncrements(cmsUInt32Number Format,
cmsUInt32Number BytesPerPlane,
cmsUInt32Number ComponentStartingOrder[],
cmsUInt32Number ComponentPointerIncrements[])
{
if (T_PLANAR(Format)) {
ComputeIncrementsForPlanar(Format, BytesPerPlane, ComponentStartingOrder, ComponentPointerIncrements);
}
else {
ComputeIncrementsForChunky(Format, ComponentStartingOrder, ComponentPointerIncrements);
}
}
// Handles extra channels copying alpha if requested by the flags
void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
size_t i, j, k;
cmsUInt32Number nExtra;
cmsUInt32Number SourceStartingOrder[cmsMAXCHANNELS];
cmsUInt32Number SourceIncrements[cmsMAXCHANNELS];
cmsUInt32Number DestStartingOrder[cmsMAXCHANNELS];
cmsUInt32Number DestIncrements[cmsMAXCHANNELS];
cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
cmsFormatterAlphaFn copyValueFn;
// Make sure we need some copy
if (!(p->dwOriginalFlags & cmsFLAGS_COPY_ALPHA))
return;
// Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time.
nExtra = T_EXTRA(p->InputFormat);
if (nExtra != T_EXTRA(p->OutputFormat))
return;
// Anything to do?
if (nExtra == 0)
return;
// Compute the increments
ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements);
ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements);
// Check for conversions 8, 16, half, float, dbl
copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
// The loop itself
for (i = 0; i < LineCount; i++) {
// Prepare pointers for the loop
for (j = 0; j < nExtra; j++) {
SourcePtr[j] = (cmsUInt8Number*)in + SourceStartingOrder[j] + SourceStrideIncrements[j];
DestPtr[j] = (cmsUInt8Number*)out + DestStartingOrder[j] + DestStrideIncrements[j];
}
for (j = 0; j < PixelsPerLine; j++) {
for (k = 0; k < nExtra; k++) {
copyValueFn(DestPtr[k], SourcePtr[k]);
SourcePtr[k] += SourceIncrements[k];
DestPtr[k] += DestIncrements[k];
}
}
for (j = 0; j < nExtra; j++) {
SourceStrideIncrements[j] += Stride->BytesPerLineIn;
DestStrideIncrements[j] += Stride->BytesPerLineOut;
}
}
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -48,7 +48,7 @@
// Symbols
typedef enum {
SNONE,
SUNDEFINED,
SINUM, // Integer
SDNUM, // Real
SIDENT, // Identifier
@ -324,7 +324,7 @@ static const char* PredefinedSampleID[] = {
"XYZ_X", // X component of tristimulus data
"XYZ_Y", // Y component of tristimulus data
"XYZ_Z", // Z component of tristimulus data
"XYY_X" // x component of chromaticity data
"XYY_X", // x component of chromaticity data
"XYY_Y", // y component of chromaticity data
"XYY_CAPY", // Y component of tristimulus data
"LAB_L", // L* component of Lab data
@ -521,7 +521,7 @@ SYMBOL BinSrchKey(const char *id)
else l = x + 1;
}
return SNONE;
return SUNDEFINED;
}
@ -706,7 +706,7 @@ void InSymbol(cmsIT8* it8)
key = BinSrchKey(it8->id);
if (key == SNONE) it8->sy = SIDENT;
if (key == SUNDEFINED) it8->sy = SIDENT;
else it8->sy = key;
}
@ -801,11 +801,11 @@ void InSymbol(cmsIT8* it8)
if (it8 ->sy == SINUM) {
sprintf(it8->id, "%d", it8->inum);
snprintf(it8->id, 127, "%d", it8->inum);
}
else {
sprintf(it8->id, it8 ->DoubleFormatter, it8->dnum);
snprintf(it8->id, 127, it8 ->DoubleFormatter, it8->dnum);
}
k = (int) strlen(it8 ->id);
@ -1297,7 +1297,7 @@ cmsHANDLE CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
it8->ValidKeywords = NULL;
it8->ValidSampleID = NULL;
it8 -> sy = SNONE;
it8 -> sy = SUNDEFINED;
it8 -> ch = ' ';
it8 -> Source = NULL;
it8 -> inum = 0;
@ -1363,7 +1363,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFlo
cmsIT8* it8 = (cmsIT8*) hIT8;
char Buffer[1024];
sprintf(Buffer, it8->DoubleFormatter, Val);
snprintf(Buffer, 1023, it8->DoubleFormatter, Val);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;
}
@ -1373,7 +1373,7 @@ cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUIn
cmsIT8* it8 = (cmsIT8*) hIT8;
char Buffer[1024];
sprintf(Buffer, "%u", Val);
snprintf(Buffer, 1023, "%u", Val);
return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
}
@ -2516,8 +2516,10 @@ int LocateSample(cmsIT8* it8, const char* cSample)
for (i=0; i < t->nSamples; i++) {
fld = GetDataFormat(it8, i);
if (cmsstrcasecmp(fld, cSample) == 0)
return i;
if (fld != NULL) {
if (cmsstrcasecmp(fld, cSample) == 0)
return i;
}
}
return -1;
@ -2575,7 +2577,7 @@ cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFl
_cmsAssert(hIT8 != NULL);
sprintf(Buff, it8->DoubleFormatter, Val);
snprintf(Buff, 255, it8->DoubleFormatter, Val);
return SetData(it8, row, col, Buff);
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -269,6 +269,9 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
{
cmsMAT3 Scale, m1, m2, m3, m4;
// TODO: Follow Marc Mahy's recommendation to check if CHAD is same by using M1*M2 == M2*M1. If so, do nothing.
// TODO: Add support for ArgyllArts tag
// Adaptation state
if (AdaptationState == 1.0) {
@ -288,7 +291,7 @@ cmsBool ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
if (AdaptationState == 0.0) {
m1 = *ChromaticAdaptationMatrixOut;
_cmsMAT3per(&m2, &m1, &Scale);
// m2 holds CHAD from output white to D50 times abs. col. scaling
@ -530,7 +533,7 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
cmsHPROFILE hProfile;
cmsMAT3 m;
cmsVEC3 off;
cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace;
cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut = cmsSigLabData, CurrentColorSpace;
cmsProfileClassSignature ClassSig;
cmsUInt32Number i, Intent;
@ -632,6 +635,22 @@ cmsPipeline* DefaultICCintents(cmsContext ContextID,
CurrentColorSpace = ColorSpaceOut;
}
// Check for non-negatives clip
if (dwFlags & cmsFLAGS_NONEGATIVES) {
if (ColorSpaceOut == cmsSigGrayData ||
ColorSpaceOut == cmsSigRgbData ||
ColorSpaceOut == cmsSigCmykData) {
cmsStage* clip = _cmsStageClipNegatives(Result->ContextID, cmsChannelsOf(ColorSpaceOut));
if (clip == NULL) goto Error;
if (!cmsPipelineInsertStage(Result, cmsAT_END, clip))
goto Error;
}
}
return Result;
Error:
@ -1045,7 +1064,7 @@ cmsPipeline* _cmsLinkProfiles(cmsContext ContextID,
if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) {
// Force BPC for V4 profiles in perceptual and saturation
if (cmsGetProfileVersion(hProfiles[i]) >= 4.0)
if (cmsGetEncodedICCversion(hProfiles[i]) >= 0x4000000)
BPC[i] = TRUE;
}
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,13 @@
#include "lcms2_internal.h"
// This function is here to help applications to prevent mixing lcms versions on header and shared objects.
int CMSEXPORT cmsGetEncodedCMMversion(void)
{
return LCMS_VERSION;
}
// I am so tired about incompatibilities on those functions that here are some replacements
// that hopefully would be fully portable.

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -929,7 +929,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[],
Rest = c1 * rx + c2 * ry + c3 * rz;
Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
Tmp1[OutChan] = (cmsUInt16Number) ( c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
}
@ -993,7 +993,7 @@ void Eval4Inputs(register const cmsUInt16Number Input[],
Rest = c1 * rx + c2 * ry + c3 * rz;
Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -453,6 +453,14 @@ cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io)
// -------------------------------------------------------------------------------------------------------
cmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile)
{
_cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile;
if (Icc == NULL) return NULL;
return Icc->IOhandler;
}
// Creates an empty structure holding all required parameters
cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
{
@ -623,6 +631,32 @@ cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig)
}
// Enforces that the profile version is per. spec.
// Operates on the big endian bytes from the profile.
// Called before converting to platform endianness.
// Byte 0 is BCD major version, so max 9.
// Byte 1 is 2 BCD digits, one per nibble.
// Reserved bytes 2 & 3 must be 0.
static
cmsUInt32Number _validatedVersion(cmsUInt32Number DWord)
{
cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;
cmsUInt8Number temp1;
cmsUInt8Number temp2;
if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09;
temp1 = *(pByte+1) & 0xf0;
temp2 = *(pByte+1) & 0x0f;
if (temp1 > 0x90) temp1 = 0x90;
if (temp2 > 0x09) temp2 = 0x09;
*(pByte+1) = (cmsUInt8Number)(temp1 | temp2);
*(pByte+2) = (cmsUInt8Number)0;
*(pByte+3) = (cmsUInt8Number)0;
return DWord;
}
// Read profile header and validate it
cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
{
@ -657,7 +691,7 @@ cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
Icc -> creator = _cmsAdjustEndianess32(Header.creator);
_cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes);
Icc -> Version = _cmsAdjustEndianess32(Header.version);
Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version));
// Get size as reported in header
HeaderSize = _cmsAdjustEndianess32(Header.size);
@ -773,7 +807,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace)
// Get true count
for (i=0; i < Icc -> TagCount; i++) {
if (Icc ->TagNames[i] != 0)
if (Icc ->TagNames[i] != (cmsTagSignature) 0)
Count++;
}
@ -782,7 +816,7 @@ cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace)
for (i=0; i < Icc -> TagCount; i++) {
if (Icc ->TagNames[i] == 0) continue; // It is just a placeholder
if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // It is just a placeholder
Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]);
Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]);
@ -1132,7 +1166,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
for (i=0; i < Icc -> TagCount; i++) {
if (Icc ->TagNames[i] == 0) continue;
if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue;
// Linked tags are not written
if (Icc ->TagLinked[i] != (cmsTagSignature) 0) continue;
@ -1265,12 +1299,16 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
cmsContext ContextID;
_cmsAssert(hProfile != NULL);
if (!_cmsLockMutex(Icc->ContextID, Icc->UsrMutex)) return 0;
memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
ContextID = cmsGetProfileContextID(hProfile);
PrevIO = Icc ->IOhandler = cmsOpenIOhandlerFromNULL(ContextID);
if (PrevIO == NULL) return 0;
if (PrevIO == NULL) {
_cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex);
return 0;
}
// Pass #1 does compute offsets
@ -1290,7 +1328,10 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
}
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
if (!cmsCloseIOhandler(PrevIO)) return 0;
if (!cmsCloseIOhandler(PrevIO))
UsedSpace = 0; // As a error marker
_cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex);
return UsedSpace;
@ -1298,6 +1339,8 @@ cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOH
Error:
cmsCloseIOhandler(PrevIO);
memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
_cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex);
return 0;
}
@ -1794,7 +1837,7 @@ Error:
// Similar to the anterior. This function allows to write directly to the ICC profile any data, without
// checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading
// it as cooked without serializing does result into an error. If that is wha you want, you will need to dump
// it as cooked without serializing does result into an error. If that is what you want, you will need to dump
// the profile to memry or disk and then reopen it.
cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size)
{
@ -1818,6 +1861,11 @@ cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, cons
Icc ->TagSizes[i] = Size;
_cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex);
if (Icc->TagPtrs[i] == NULL) {
Icc->TagNames[i] = (cmsTagSignature) 0;
return FALSE;
}
return TRUE;
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -310,8 +310,8 @@ Error:
cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
{
cmsTagTypeSignature OriginalType;
cmsTagSignature tag16 = Device2PCS16[Intent];
cmsTagSignature tagFloat = Device2PCSFloat[Intent];
cmsTagSignature tag16;
cmsTagSignature tagFloat;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
// On named color, take the appropiate tag
@ -340,6 +340,9 @@ cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
// matter other LUT are present and have precedence. Intent = -1 means just this.
if (Intent != -1) {
tag16 = Device2PCS16[Intent];
tagFloat = Device2PCSFloat[Intent];
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4, but the encoding range is no
@ -582,13 +585,16 @@ Error:
cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
{
cmsTagTypeSignature OriginalType;
cmsTagSignature tag16 = PCS2Device16[Intent];
cmsTagSignature tagFloat = PCS2DeviceFloat[Intent];
cmsContext ContextID = cmsGetProfileContextID(hProfile);
cmsTagSignature tag16;
cmsTagSignature tagFloat;
cmsContext ContextID = cmsGetProfileContextID(hProfile);
if (Intent != -1) {
tag16 = PCS2Device16[Intent];
tagFloat = PCS2DeviceFloat[Intent];
if (cmsIsTag(hProfile, tagFloat)) { // Float tag takes precedence
// Floating point LUT are always V4
@ -906,7 +912,7 @@ cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq)
{
if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE;
if (cmsGetProfileVersion(hProfile) >= 4.0) {
if (cmsGetEncodedICCversion(hProfile) >= 0x4000000) {
if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE;
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -505,7 +505,7 @@ void* CLUTElemDup(cmsStage* mpe)
goto Error;
} else {
NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number));
if (NewElem ->Tab.TFloat == NULL)
if (NewElem ->Tab.T == NULL)
goto Error;
}
}
@ -1125,7 +1125,23 @@ cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID)
return mpe;
}
// Clips values smaller than zero
static
void Clipper(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
{
cmsUInt32Number i;
for (i = 0; i < mpe->InputChannels; i++) {
cmsFloat32Number n = In[i];
Out[i] = n < 0 ? 0 : n;
}
}
cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels)
{
return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType,
nChannels, nChannels, Clipper, NULL, NULL, NULL);
}
// ********************************************************************************
// Type cmsSigXYZ2LabElemType
@ -1437,7 +1453,8 @@ cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut)
First = FALSE;
}
else {
Anterior ->Next = NewMPE;
if (Anterior != NULL)
Anterior ->Next = NewMPE;
}
Anterior = NewMPE;
@ -1482,7 +1499,7 @@ int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage
for (pt = lut ->Elements;
pt != NULL;
pt = pt -> Next) Anterior = pt;
Anterior ->Next = mpe;
mpe ->Next = NULL;
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2012 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -92,7 +92,7 @@ cmsBool GrowMLUpool(cmsMLU* mlu)
static
cmsBool GrowMLUtable(cmsMLU* mlu)
{
int AllocatedEntries;
cmsUInt32Number AllocatedEntries;
_cmsMLUentry *NewPtr;
// Sanity check
@ -118,7 +118,7 @@ cmsBool GrowMLUtable(cmsMLU* mlu)
static
int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
{
int i;
cmsUInt32Number i;
// Sanity check
if (mlu == NULL) return -1;
@ -178,6 +178,33 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
return TRUE;
}
// Convert from a 3-char code to a cmsUInt16Number. It is done inthis way because some
// compilers don't properly align beginning of strings
static
cmsUInt16Number strTo16(const char str[3])
{
cmsUInt16Number n = ((cmsUInt16Number) str[0] << 8) | str[1];
return n; // Always big endian in this case
}
static
void strFrom16(char str[3], cmsUInt16Number n)
{
// Assiming this would be aligned
union {
cmsUInt16Number n;
char str[2];
} c;
c.n = n; // Always big endian in this case
str[0] = c.str[0]; str[1] = c.str[1]; str[2] = 0;
}
// Add an ASCII entry.
cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
@ -185,8 +212,8 @@ cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const
cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1;
wchar_t* WStr;
cmsBool rc;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number Lang = strTo16(LanguageCode);
cmsUInt16Number Cntry = strTo16(CountryCode);
if (mlu == NULL) return FALSE;
@ -220,8 +247,8 @@ cmsUInt32Number mywcslen(const wchar_t *s)
// Add a wide entry
cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString)
{
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country);
cmsUInt16Number Lang = strTo16(Language);
cmsUInt16Number Cntry = strTo16(Country);
cmsUInt32Number len;
if (mlu == NULL) return FALSE;
@ -298,8 +325,8 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
{
int i;
int Best = -1;
cmsUInt32Number i;
cmsInt32Number Best = -1;
_cmsMLUentry* v;
if (mlu == NULL) return NULL;
@ -350,8 +377,8 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
cmsUInt32Number StrLen = 0;
cmsUInt32Number ASCIIlen, i;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number Lang = strTo16(LanguageCode);
cmsUInt16Number Cntry = strTo16(CountryCode);
// Sanitize
if (mlu == NULL) return 0;
@ -394,8 +421,8 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
const wchar_t *Wide;
cmsUInt32Number StrLen = 0;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number Lang = strTo16(LanguageCode);
cmsUInt16Number Cntry = strTo16(CountryCode);
// Sanitize
if (mlu == NULL) return 0;
@ -427,8 +454,8 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
{
const wchar_t *Wide;
cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number Lang = strTo16(LanguageCode);
cmsUInt16Number Cntry = strTo16(CountryCode);
cmsUInt16Number ObtLang, ObtCode;
// Sanitize
@ -438,10 +465,9 @@ CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
if (Wide == NULL) return FALSE;
// Get used language and code
*(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang);
*(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode);
strFrom16(ObtainedLanguage, ObtLang);
strFrom16(ObtainedCountry, ObtCode);
ObtainedLanguage[2] = ObtainedCountry[2] = 0;
return TRUE;
}
@ -464,12 +490,12 @@ cmsBool CMSEXPORT cmsMLUtranslationsCodes(const cmsMLU* mlu,
if (mlu == NULL) return FALSE;
if (idx >= (cmsUInt32Number) mlu->UsedEntries) return FALSE;
if (idx >= mlu->UsedEntries) return FALSE;
entry = &mlu->Entries[idx];
*(cmsUInt16Number *)LanguageCode = _cmsAdjustEndianess16(entry->Language);
*(cmsUInt16Number *)CountryCode = _cmsAdjustEndianess16(entry->Country);
strFrom16(LanguageCode, entry->Language);
strFrom16(CountryCode, entry->Country);
return TRUE;
}
@ -514,8 +540,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUIn
v ->nColors = 0;
v ->ContextID = ContextID;
while (v -> Allocated < n)
GrowNamedColorList(v);
while (v -> Allocated < n){
if (!GrowNamedColorList(v)) return NULL;
}
strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix)-1);
strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix)-1);
@ -544,8 +571,9 @@ cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
if (NewNC == NULL) return NULL;
// For really large tables we need this
while (NewNC ->Allocated < v ->Allocated)
GrowNamedColorList(NewNC);
while (NewNC ->Allocated < v ->Allocated){
if (!GrowNamedColorList(NewNC)) return NULL;
}
memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix));
memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix));

View File

@ -1,8 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -163,6 +162,89 @@ cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op
return AnyOpt;
}
static
cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b)
{
return fabs(b - a) < 0.00001f;
}
static
cmsBool isFloatMatrixIdentity(const cmsMAT3* a)
{
cmsMAT3 Identity;
int i, j;
_cmsMAT3identity(&Identity);
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE;
return TRUE;
}
// if two adjacent matrices are found, multiply them.
static
cmsBool _MultiplyMatrix(cmsPipeline* Lut)
{
cmsStage** pt1;
cmsStage** pt2;
cmsStage* chain;
cmsBool AnyOpt = FALSE;
pt1 = &Lut->Elements;
if (*pt1 == NULL) return AnyOpt;
while (*pt1 != NULL) {
pt2 = &((*pt1)->Next);
if (*pt2 == NULL) return AnyOpt;
if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) {
// Get both matrices
_cmsStageMatrixData* m1 = (_cmsStageMatrixData*) cmsStageData(*pt1);
_cmsStageMatrixData* m2 = (_cmsStageMatrixData*) cmsStageData(*pt2);
cmsMAT3 res;
// Input offset and output offset should be zero to use this optimization
if (m1->Offset != NULL || m2 ->Offset != NULL ||
cmsStageInputChannels(*pt1) != 3 || cmsStageOutputChannels(*pt1) != 3 ||
cmsStageInputChannels(*pt2) != 3 || cmsStageOutputChannels(*pt2) != 3)
return FALSE;
// Multiply both matrices to get the result
_cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double);
// Get the next in chain afer the matrices
chain = (*pt2)->Next;
// Remove both matrices
_RemoveElement(pt2);
_RemoveElement(pt1);
// Now what if the result is a plain identity?
if (!isFloatMatrixIdentity(&res)) {
// We can not get rid of full matrix
cmsStage* Multmat = cmsStageAllocMatrix(Lut->ContextID, 3, 3, (const cmsFloat64Number*) &res, NULL);
if (Multmat == NULL) return FALSE; // Should never happen
// Recover the chain
Multmat->Next = chain;
*pt1 = Multmat;
}
AnyOpt = TRUE;
}
else
pt1 = &((*pt1)->Next);
}
return AnyOpt;
}
// Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed
// by a v4 to v2 and vice-versa. The elements are then discarded.
static
@ -195,6 +277,9 @@ cmsBool PreOptimize(cmsPipeline* Lut)
// Remove float pcs Lab conversions
Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ);
// Simplify matrix.
Opt |= _MultiplyMatrix(Lut);
if (Opt) AnyOpt = TRUE;
} while (Opt);
@ -251,12 +336,12 @@ static
void* Prelin16dup(cmsContext ContextID, const void* ptr)
{
Prelin16Data* p16 = (Prelin16Data*) ptr;
Prelin16Data* Duped = _cmsDupMem(ContextID, p16, sizeof(Prelin16Data));
Prelin16Data* Duped = (Prelin16Data*) _cmsDupMem(ContextID, p16, sizeof(Prelin16Data));
if (Duped == NULL) return NULL;
Duped ->EvalCurveOut16 = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
Duped->EvalCurveOut16 = (_cmsInterpFn16*) _cmsDupMem(ContextID, p16->EvalCurveOut16, p16->nOutputs * sizeof(_cmsInterpFn16));
Duped->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16->ParamsCurveOut16, p16->nOutputs * sizeof(cmsInterpParams*));
return Duped;
}
@ -269,7 +354,7 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
int nOutputs, cmsToneCurve** Out )
{
int i;
Prelin16Data* p16 = _cmsMallocZero(ContextID, sizeof(Prelin16Data));
Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data));
if (p16 == NULL) return NULL;
p16 ->nInputs = nInputs;
@ -590,7 +675,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
cmsStage* PreLin = cmsPipelineGetPtrToFirstStage(Src);
// Check if suitable
if (PreLin ->Type == cmsSigCurveSetElemType) {
if (PreLin && PreLin ->Type == cmsSigCurveSetElemType) {
// Maybe this is a linear tram, so we can avoid the whole stuff
if (!AllCurvesAreLinear(PreLin)) {
@ -623,7 +708,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
cmsStage* PostLin = cmsPipelineGetPtrToLastStage(Src);
// Check if suitable
if (cmsStageType(PostLin) == cmsSigCurveSetElemType) {
if (PostLin && cmsStageType(PostLin) == cmsSigCurveSetElemType) {
// Maybe this is a linear tram, so we can avoid the whole stuff
if (!AllCurvesAreLinear(PostLin)) {
@ -758,7 +843,7 @@ Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cms
cmsS15Fixed16Number v1, v2, v3;
Prelin8Data* p8;
p8 = _cmsMallocZero(ContextID, sizeof(Prelin8Data));
p8 = (Prelin8Data*)_cmsMallocZero(ContextID, sizeof(Prelin8Data));
if (p8 == NULL) return NULL;
// Since this only works for 8 bit input, values comes always as x * 257,
@ -832,7 +917,7 @@ void PrelinEval8(register const cmsUInt16Number Input[],
Prelin8Data* p8 = (Prelin8Data*) D;
register const cmsInterpParams* p = p8 ->p;
int TotalOut = p -> nOutputs;
const cmsUInt16Number* LutTable = p -> Table;
const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table;
r = Input[0] >> 8;
g = Input[1] >> 8;
@ -925,8 +1010,8 @@ cmsBool IsDegenerated(const cmsToneCurve* g)
}
if (Zeros == 1 && Poles == 1) return FALSE; // For linear tables
if (Zeros > (nEntries / 4)) return TRUE; // Degenerated, mostly zeros
if (Poles > (nEntries / 4)) return TRUE; // Degenerated, mostly poles
if (Zeros > (nEntries / 20)) return TRUE; // Degenerated, many zeros
if (Poles > (nEntries / 20)) return TRUE; // Degenerated, many poles
return FALSE;
}
@ -948,17 +1033,19 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
cmsColorSpaceSignature ColorSpace, OutputColorSpace;
cmsStage* OptimizedPrelinMpe;
cmsStage* mpe;
cmsToneCurve** OptimizedPrelinCurves;
_cmsStageCLutData* OptimizedPrelinCLUT;
cmsToneCurve** OptimizedPrelinCurves;
_cmsStageCLutData* OptimizedPrelinCLUT;
// This is a loosy optimization! does not apply in floating-point cases
if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
// Only on RGB
// Only on chunky RGB
if (T_COLORSPACE(*InputFormat) != PT_RGB) return FALSE;
if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE;
if (T_PLANAR(*InputFormat)) return FALSE;
if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE;
if (T_PLANAR(*OutputFormat)) return FALSE;
// On 16 bits, user has to specify the feature
if (!_cmsFormatterIs8bit(*InputFormat)) {
@ -982,6 +1069,22 @@ cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Inte
memset(Trans, 0, sizeof(Trans));
memset(TransReverse, 0, sizeof(TransReverse));
// If the last stage of the original lut are curves, and those curves are
// degenerated, it is likely the transform is squeezing and clipping
// the output from previous CLUT. We cannot optimize this case
{
cmsStage* last = cmsPipelineGetPtrToLastStage(OriginalLut);
if (cmsStageType(last) == cmsSigCurveSetElemType) {
_cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*)cmsStageData(last);
for (i = 0; i < Data->nCurves; i++) {
if (IsDegenerated(Data->TheCurves[i]))
goto Error;
}
}
}
for (t = 0; t < OriginalLut ->InputChannels; t++) {
Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL);
if (Trans[t] == NULL) goto Error;
@ -1151,15 +1254,15 @@ void CurvesFree(cmsContext ContextID, void* ptr)
static
void* CurvesDup(cmsContext ContextID, const void* ptr)
{
Curves16Data* Data = _cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
int i;
if (Data == NULL) return NULL;
Data ->Curves = _cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*));
Data->Curves = (cmsUInt16Number**) _cmsDupMem(ContextID, Data->Curves, Data->nCurves * sizeof(cmsUInt16Number*));
for (i=0; i < Data -> nCurves; i++) {
Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number));
Data->Curves[i] = (cmsUInt16Number*) _cmsDupMem(ContextID, Data->Curves[i], Data->nElements * sizeof(cmsUInt16Number));
}
return (void*) Data;
@ -1172,18 +1275,18 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsT
int i, j;
Curves16Data* c16;
c16 = _cmsMallocZero(ContextID, sizeof(Curves16Data));
c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data));
if (c16 == NULL) return NULL;
c16 ->nCurves = nCurves;
c16 ->nElements = nElements;
c16 ->Curves = _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
if (c16 ->Curves == NULL) return NULL;
for (i=0; i < nCurves; i++) {
c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
c16->Curves[i] = (cmsUInt16Number*) _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
if (c16->Curves[i] == NULL) {
@ -1315,7 +1418,10 @@ cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUI
GammaTables[i] = NULL;
}
if (GammaTables != NULL) _cmsFree(Src ->ContextID, GammaTables);
if (GammaTables != NULL) {
_cmsFree(Src->ContextID, GammaTables);
GammaTables = NULL;
}
// Maybe the curves are linear at the end
if (!AllCurvesAreLinear(ObtainedCurves)) {
@ -1531,49 +1637,83 @@ cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, c
}
// 8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast!
// TODO: Allow a third matrix for abs. colorimetric
static
cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
cmsStage* Curve1, *Curve2;
cmsStage* Matrix1, *Matrix2;
_cmsStageMatrixData* Data1;
_cmsStageMatrixData* Data2;
cmsMAT3 res;
cmsBool IdentityMat;
cmsPipeline* Dest, *Src;
cmsStage* Curve1, *Curve2;
cmsStage* Matrix1, *Matrix2;
cmsMAT3 res;
cmsBool IdentityMat;
cmsPipeline* Dest, *Src;
cmsFloat64Number* Offset;
// Only works on RGB to RGB
if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;
// Only works on RGB to RGB
if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;
// Only works on 8 bit input
if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE;
// Only works on 8 bit input
if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE;
// Seems suitable, proceed
Src = *Lut;
// Seems suitable, proceed
Src = *Lut;
// Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for
if (!cmsPipelineCheckAndRetreiveStages(Src, 4,
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
&Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE;
// Check for:
//
// shaper-matrix-matrix-shaper
// shaper-matrix-shaper
//
// Both of those constructs are possible (first because abs. colorimetric).
// additionally, In the first case, the input matrix offset should be zero.
// Get both matrices
Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1);
Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2);
IdentityMat = FALSE;
if (cmsPipelineCheckAndRetreiveStages(Src, 4,
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
&Curve1, &Matrix1, &Matrix2, &Curve2)) {
// Input offset should be zero
if (Data1 ->Offset != NULL) return FALSE;
// Get both matrices
_cmsStageMatrixData* Data1 = (_cmsStageMatrixData*)cmsStageData(Matrix1);
_cmsStageMatrixData* Data2 = (_cmsStageMatrixData*)cmsStageData(Matrix2);
// Multiply both matrices to get the result
_cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double);
// Input offset should be zero
if (Data1->Offset != NULL) return FALSE;
// Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
IdentityMat = FALSE;
if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) {
// Multiply both matrices to get the result
_cmsMAT3per(&res, (cmsMAT3*)Data2->Double, (cmsMAT3*)Data1->Double);
// We can get rid of full matrix
IdentityMat = TRUE;
}
// Only 2nd matrix has offset, or it is zero
Offset = Data2->Offset;
// Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
// We can get rid of full matrix
IdentityMat = TRUE;
}
}
else {
if (cmsPipelineCheckAndRetreiveStages(Src, 3,
cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
&Curve1, &Matrix1, &Curve2)) {
_cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1);
// Copy the matrix to our result
memcpy(&res, Data->Double, sizeof(res));
// Preserve the Odffset (may be NULL as a zero offset)
Offset = Data->Offset;
if (_cmsMAT3isIdentity(&res) && Offset == NULL) {
// We can get rid of full matrix
IdentityMat = TRUE;
}
}
else
return FALSE; // Not optimizeable this time
}
// Allocate an empty LUT
Dest = cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
@ -1583,9 +1723,12 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
goto Error;
if (!IdentityMat)
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset)))
goto Error;
if (!IdentityMat) {
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset)))
goto Error;
}
if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
goto Error;
@ -1603,7 +1746,7 @@ cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
*dwFlags |= cmsFLAGS_NOCACHE;
// Setup the optimizarion routines
SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat);
SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
}
cmsPipelineFree(Src);

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -2409,9 +2409,6 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
((cmsFloat64Number*) output)[i + start] = v;
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat64Number);
}
if (Extra == 0 && SwapFirst) {
@ -2422,7 +2419,7 @@ cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* info,
if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsFloat64Number);
else
return output + nChan * sizeof(cmsFloat64Number);
return output + (nChan + Extra) * sizeof(cmsFloat64Number);
}
@ -2433,50 +2430,47 @@ cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* info,
register cmsUInt8Number* output,
register cmsUInt32Number Stride)
{
int nChan = T_CHANNELS(info -> OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35 : 65535.0;
cmsFloat64Number v = 0;
cmsFloat32Number* swap1 = (cmsFloat32Number*) output;
int i, start = 0;
int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 655.35 : 65535.0;
cmsFloat64Number v = 0;
cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
int i, start = 0;
if (ExtraFirst)
start = Extra;
if (ExtraFirst)
start = Extra;
for (i=0; i < nChan; i++) {
for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i;
int index = DoSwap ? (nChan - i - 1) : i;
v = (cmsFloat64Number) wOut[index] / maximum;
v = (cmsFloat64Number)wOut[index] / maximum;
if (Reverse)
v = maximum - v;
if (Reverse)
v = maximum - v;
if (Planar)
((cmsFloat32Number*) output)[(i + start ) * Stride]= (cmsFloat32Number) v;
else
((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v;
}
if (Planar)
((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
else
((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat32Number);
}
if (Extra == 0 && SwapFirst) {
if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
*swap1 = (cmsFloat32Number)v;
}
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number));
*swap1 = (cmsFloat32Number) v;
}
if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsFloat32Number);
else
return output + nChan * sizeof(cmsFloat32Number);
if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsFloat32Number);
else
return output + (nChan + Extra) * sizeof(cmsFloat32Number);
}
@ -2489,50 +2483,47 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
cmsUInt8Number* output,
cmsUInt32Number Stride)
{
int nChan = T_CHANNELS(info -> OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
cmsFloat32Number* swap1 = (cmsFloat32Number*) output;
cmsFloat64Number v = 0;
int i, start = 0;
int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
cmsFloat32Number* swap1 = (cmsFloat32Number*)output;
cmsFloat64Number v = 0;
int i, start = 0;
if (ExtraFirst)
start = Extra;
if (ExtraFirst)
start = Extra;
for (i=0; i < nChan; i++) {
for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i;
int index = DoSwap ? (nChan - i - 1) : i;
v = wOut[index] * maximum;
v = wOut[index] * maximum;
if (Reverse)
v = maximum - v;
if (Reverse)
v = maximum - v;
if (Planar)
((cmsFloat32Number*) output)[(i + start)* Stride]= (cmsFloat32Number) v;
else
((cmsFloat32Number*) output)[i + start] = (cmsFloat32Number) v;
}
if (Planar)
((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
else
((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat32Number);
}
if (Extra == 0 && SwapFirst) {
if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number));
*swap1 = (cmsFloat32Number) v;
}
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat32Number));
*swap1 = (cmsFloat32Number)v;
}
if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsFloat32Number);
else
return output + nChan * sizeof(cmsFloat32Number);
if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsFloat32Number);
else
return output + (nChan + Extra) * sizeof(cmsFloat32Number);
}
static
@ -2541,51 +2532,47 @@ cmsUInt8Number* PackDoublesFromFloat(_cmsTRANSFORM* info,
cmsUInt8Number* output,
cmsUInt32Number Stride)
{
int nChan = T_CHANNELS(info -> OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
cmsFloat64Number v = 0;
cmsFloat64Number* swap1 = (cmsFloat64Number*) output;
int i, start = 0;
int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat64Number maximum = IsInkSpace(info->OutputFormat) ? 100.0 : 1.0;
cmsFloat64Number v = 0;
cmsFloat64Number* swap1 = (cmsFloat64Number*)output;
int i, start = 0;
if (ExtraFirst)
start = Extra;
if (ExtraFirst)
start = Extra;
for (i=0; i < nChan; i++) {
for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i;
int index = DoSwap ? (nChan - i - 1) : i;
v = wOut[index] * maximum;
v = wOut[index] * maximum;
if (Reverse)
v = maximum - v;
if (Reverse)
v = maximum - v;
if (Planar)
((cmsFloat64Number*) output)[(i + start) * Stride] = v;
else
((cmsFloat64Number*) output)[i + start] = v;
}
if (Planar)
((cmsFloat64Number*)output)[(i + start) * Stride] = v;
else
((cmsFloat64Number*)output)[i + start] = v;
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsFloat64Number);
}
if (Extra == 0 && SwapFirst) {
if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));
*swap1 = v;
}
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsFloat64Number));
*swap1 = v;
}
if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsFloat64Number);
else
return output + nChan * sizeof(cmsFloat64Number);
if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsFloat64Number);
else
return output + (nChan + Extra) * sizeof(cmsFloat64Number);
}
@ -2821,50 +2808,47 @@ cmsUInt8Number* PackHalfFrom16(register _cmsTRANSFORM* info,
register cmsUInt8Number* output,
register cmsUInt32Number Stride)
{
int nChan = T_CHANNELS(info -> OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 655.35F : 65535.0F;
cmsFloat32Number v = 0;
cmsUInt16Number* swap1 = (cmsUInt16Number*) output;
int i, start = 0;
int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 655.35F : 65535.0F;
cmsFloat32Number v = 0;
cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
int i, start = 0;
if (ExtraFirst)
start = Extra;
if (ExtraFirst)
start = Extra;
for (i=0; i < nChan; i++) {
for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i;
int index = DoSwap ? (nChan - i - 1) : i;
v = (cmsFloat32Number) wOut[index] / maximum;
v = (cmsFloat32Number)wOut[index] / maximum;
if (Reverse)
v = maximum - v;
if (Reverse)
v = maximum - v;
if (Planar)
((cmsUInt16Number*) output)[(i + start ) * Stride]= _cmsFloat2Half(v);
else
((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half(v);
}
if (Planar)
((cmsUInt16Number*)output)[(i + start) * Stride] = _cmsFloat2Half(v);
else
((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsUInt16Number);
}
if (Extra == 0 && SwapFirst) {
if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
*swap1 = _cmsFloat2Half(v);
}
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
*swap1 = _cmsFloat2Half(v);
}
if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsUInt16Number);
else
return output + nChan * sizeof(cmsUInt16Number);
if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsUInt16Number);
else
return output + (nChan + Extra) * sizeof(cmsUInt16Number);
}
@ -2875,50 +2859,47 @@ cmsUInt8Number* PackHalfFromFloat(_cmsTRANSFORM* info,
cmsUInt8Number* output,
cmsUInt32Number Stride)
{
int nChan = T_CHANNELS(info -> OutputFormat);
int DoSwap = T_DOSWAP(info ->OutputFormat);
int Reverse = T_FLAVOR(info ->OutputFormat);
int Extra = T_EXTRA(info -> OutputFormat);
int SwapFirst = T_SWAPFIRST(info -> OutputFormat);
int Planar = T_PLANAR(info -> OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat32Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0F : 1.0F;
cmsUInt16Number* swap1 = (cmsUInt16Number*) output;
cmsFloat32Number v = 0;
int i, start = 0;
int nChan = T_CHANNELS(info->OutputFormat);
int DoSwap = T_DOSWAP(info->OutputFormat);
int Reverse = T_FLAVOR(info->OutputFormat);
int Extra = T_EXTRA(info->OutputFormat);
int SwapFirst = T_SWAPFIRST(info->OutputFormat);
int Planar = T_PLANAR(info->OutputFormat);
int ExtraFirst = DoSwap ^ SwapFirst;
cmsFloat32Number maximum = IsInkSpace(info->OutputFormat) ? 100.0F : 1.0F;
cmsUInt16Number* swap1 = (cmsUInt16Number*)output;
cmsFloat32Number v = 0;
int i, start = 0;
if (ExtraFirst)
start = Extra;
if (ExtraFirst)
start = Extra;
for (i=0; i < nChan; i++) {
for (i = 0; i < nChan; i++) {
int index = DoSwap ? (nChan - i - 1) : i;
int index = DoSwap ? (nChan - i - 1) : i;
v = wOut[index] * maximum;
v = wOut[index] * maximum;
if (Reverse)
v = maximum - v;
if (Reverse)
v = maximum - v;
if (Planar)
((cmsUInt16Number*) output)[(i + start)* Stride]= _cmsFloat2Half( v );
else
((cmsUInt16Number*) output)[i + start] = _cmsFloat2Half( v );
}
if (Planar)
((cmsUInt16Number*)output)[(i + start)* Stride] = _cmsFloat2Half(v);
else
((cmsUInt16Number*)output)[i + start] = _cmsFloat2Half(v);
}
if (!ExtraFirst) {
output += Extra * sizeof(cmsUInt16Number);
}
if (Extra == 0 && SwapFirst) {
if (Extra == 0 && SwapFirst) {
memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
*swap1 = (cmsUInt16Number) _cmsFloat2Half( v );
}
memmove(swap1 + 1, swap1, (nChan - 1)* sizeof(cmsUInt16Number));
*swap1 = (cmsUInt16Number)_cmsFloat2Half(v);
}
if (T_PLANAR(info -> OutputFormat))
return output + sizeof(cmsUInt16Number);
else
return output + nChan * sizeof(cmsUInt16Number);
if (T_PLANAR(info->OutputFormat))
return output + sizeof(cmsUInt16Number);
else
return output + (nChan + Extra)* sizeof(cmsUInt16Number);
}
#endif
@ -3178,6 +3159,8 @@ cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Numbe
cmsUInt32Number i;
cmsFormatter fr;
// Optimization is only a hint
dwInput &= ~OPTIMIZED_SH(1);
switch (dwFlags)
{

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -106,6 +106,15 @@ void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source)
Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y;
}
/*
The break point (24/116)^3 = (6/29)^3 is a very small amount of tristimulus
primary (0.008856). Generally, this only happens for
nearly ideal blacks and for some orange / amber colors in transmission mode.
For example, the Z value of the orange turn indicator lamp lens on an
automobile will often be below this value. But the Z does not
contribute to the perceived color directly.
*/
static
cmsFloat64Number f(cmsFloat64Number t)
{

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -215,22 +215,6 @@ cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n
}
// Jun-21-2000: Some profiles (those that comes with W2K) comes
// with the media white (media black?) x 100. Add a sanity check
static
void NormalizeXYZ(cmsCIEXYZ* Dest)
{
while (Dest -> X > 2. &&
Dest -> Y > 2. &&
Dest -> Z > 2.) {
Dest -> X /= 10.;
Dest -> Y /= 10.;
Dest -> Z /= 10.;
}
}
cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ)
{
cmsEncodedXYZNumber xyz;
@ -244,8 +228,6 @@ cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ)
XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X));
XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y));
XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z));
NormalizeXYZ(XYZ);
}
return TRUE;
}
@ -525,6 +507,7 @@ void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size)
if (ContextID == NULL) {
ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024);
if (ctx->MemPool == NULL) return NULL;
}
else {
cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context");
@ -683,15 +666,21 @@ struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
// Internal: get the memory area associanted with each context client
// Returns the block assigned to the specific zone.
// Returns the block assigned to the specific zone. Never return NULL.
void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
{
struct _cmsContext_struct* ctx;
void *ptr;
if (mc < 0 || mc >= MemoryClientMax) {
cmsSignalError(ContextID, cmsERROR_RANGE, "Bad context client");
return NULL;
if ((int) mc < 0 || mc >= MemoryClientMax) {
cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption");
// This is catastrophic. Should never reach here
_cmsAssert(0);
// Reverts to global context
return globalContext.chunks[UserPtr];
}
ctx = _cmsGetContext(ContextID);
@ -880,7 +869,7 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
}
/*
static
struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
{
@ -897,6 +886,7 @@ struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
return NULL; // List is empty or only one element!
}
*/
// Frees any resources associated with the given context,
// and destroys the context placeholder.
@ -932,8 +922,8 @@ void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
// Search for previous
for (prev = _cmsContextPoolHead;
prev != NULL;
prev = prev ->Next)
prev != NULL;
prev = prev ->Next)
{
if (prev -> Next == ctx) {
prev -> Next = ctx ->Next;

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -1393,14 +1393,15 @@ void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[])
if (nColorant > cmsMAXCHANNELS)
nColorant = cmsMAXCHANNELS;
for (j=0; j < nColorant; j++) {
for (j = 0; j < nColorant; j++) {
sprintf(Buff, "%.3f", Out[j] / 65535.0);
strcat(Colorant, Buff);
if (j < nColorant -1)
strcat(Colorant, " ");
snprintf(Buff, 31, "%.3f", Out[j] / 65535.0);
Buff[31] = 0;
strcat(Colorant, Buff);
if (j < nColorant - 1)
strcat(Colorant, " ");
}
}
}

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2010 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -340,28 +340,7 @@ cmsFloat64Number RootOfLeastSquaresFitQuadraticCurve(int n, cmsFloat64Number x[]
}
/*
static
cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
{
int i;
cmsFloat64Number last;
last = Table[n-1];
for (i = n-2; i >= 0; --i) {
if (Table[i] > last)
return FALSE;
else
last = Table[i];
}
return TRUE;
}
*/
// Calculates the black point of a destination profile.
// This algorithm comes from the Adobe paper disclosing its black point compensation method.
@ -486,7 +465,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
// Test for mid range straight (only on relative colorimetric)
NearlyStraightMidrange = TRUE;
MinL = outRamp[0]; MaxL = outRamp[255];
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
@ -502,7 +480,6 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
// DestinationBlackPoint shall be the same as initialLab.
// Otherwise, the DestinationBlackPoint shall be determined
// using curve fitting.
if (NearlyStraightMidrange) {
cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
@ -513,15 +490,13 @@ cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROF
// curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
// with a corner and a nearly straight line to the white point.
// with a corner and a nearly straight line to the white point.
for (l=0; l < 256; l++) {
yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
}
// find the black point using the least squares error quadratic curve fitting
if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
lo = 0.1;
hi = 0.5;

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2011 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -218,7 +218,8 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2
{
cmsFloat64Number a, b, c, d, e, D;
cmsFloat64Number sc, sN, sD;
cmsFloat64Number tc, tN, tD;
//cmsFloat64Number tc; // left for future use
cmsFloat64Number tN, tD;
cmsVEC3 w0;
_cmsVEC3minus(&w0, &line1 ->a, &line2 ->a);
@ -286,7 +287,7 @@ cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2
}
// finally do the division to get sc and tc
sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD);
tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD);
//tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); // left for future use.
GetPointOfLine(r, line1, sc);
return TRUE;

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2014 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -951,7 +951,7 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
cmsMLU* mlu = (cmsMLU*) Ptr;
char *Text = NULL;
wchar_t *Wide = NULL;
cmsUInt32Number len, len_aligned, len_filler_alignment;
cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
cmsBool rc = FALSE;
char Filler[68];
@ -961,17 +961,18 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
// Get the len of string
len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
// From ICC3.4: It has been found that textDescriptionType can contain misaligned data
// Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data
//(see clause 4.1 for the definition of “aligned”). Because the Unicode language
// code and Unicode count immediately follow the ASCII description, their
// alignment is not correct if the ASCII count is not a multiple of four. The
// ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
// writing software must be written carefully in order to handle these alignment
// problems.
// Compute an aligned size
len_aligned = _cmsALIGNLONG(len);
len_filler_alignment = len_aligned - len;
//
// The above last sentence suggest to handle alignment issues in the
// parser. The provided example (Table 69 on Page 60) makes this clear.
// The padding only in the ASCII count is not sufficient for a aligned tag
// size, with the same text size in ASCII and Unicode.
// Null strings
if (len <= 0) {
@ -992,6 +993,12 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
cmsMLUgetWide(mlu, cmsNoLanguage, cmsNoCountry, Wide, len * sizeof(wchar_t));
}
// Tell the real text len including the null terminator and padding
len_text = strlen(Text) + 1;
// Compute an total tag size requirement
len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67);
len_aligned = _cmsALIGNLONG(len_tag_requirement);
// * cmsUInt32Number count; * Description length
// * cmsInt8Number desc[count] * NULL terminated ascii string
// * cmsUInt32Number ucLangCode; * UniCode language code
@ -1001,20 +1008,14 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
// * cmsUInt8Number scCount; * ScriptCode count
// * cmsInt8Number scDesc[67]; * ScriptCode Description
if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error;
if (!io ->Write(io, len, Text)) goto Error;
if (!io ->Write(io, len_filler_alignment, Filler)) goto Error;
if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
if (!io ->Write(io, len_text, Text)) goto Error;
if (!_cmsWriteUInt32Number(io, 0)) goto Error; // ucLanguageCode
// This part is tricky: we need an aligned tag size, and the ScriptCode part
// takes 70 bytes, so we need 2 extra bytes to do the alignment
if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error;
if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
// Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
if (!_cmsWriteWCharArray(io, len, Wide)) goto Error;
if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error;
if (!_cmsWriteWCharArray(io, len_text, Wide)) goto Error;
// ScriptCode Code & count (unused)
if (!_cmsWriteUInt16Number(io, 0)) goto Error;
@ -1022,6 +1023,10 @@ cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
if (!io ->Write(io, 67, Filler)) goto Error;
// possibly add pad at the end of tag
if(len_aligned - len_tag_requirement > 0)
if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error;
rc = TRUE;
Error:
@ -1503,7 +1508,7 @@ cmsBool Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
cmsMLU* mlu =(cmsMLU*) Ptr;
cmsUInt32Number HeaderSize;
cmsUInt32Number Len, Offset;
int i;
cmsUInt32Number i;
if (Ptr == NULL) {
@ -1689,10 +1694,7 @@ cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number
else
for (j=0; j < 256; j++) {
if (Tables != NULL)
val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
else
val = (cmsUInt8Number) j;
val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
if (!_cmsWriteUInt8Number(io, val)) return FALSE;
}
@ -3107,6 +3109,8 @@ void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* i
memset(Colorant, 0, sizeof(Colorant));
if (io -> Read(io, Root, 32, 1) != 1) return NULL;
Root[32] = 0; // To prevent exploits
if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
@ -3129,8 +3133,8 @@ static
cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
char prefix[32]; // Prefix for each color name
char suffix[32]; // Suffix for each color name
char prefix[33]; // Prefix for each color name
char suffix[33]; // Suffix for each color name
int i, nColors;
nColors = cmsNamedColorCount(NamedColorList);
@ -3142,7 +3146,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER
strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
suffix[31] = prefix[31] = 0;
suffix[32] = prefix[32] = 0;
if (!io ->Write(io, 32, prefix)) return FALSE;
if (!io ->Write(io, 32, suffix)) return FALSE;
@ -3154,6 +3158,7 @@ cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER
char Root[33];
if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
Root[32] = 0;
if (!io ->Write(io, 32 , Root)) return FALSE;
if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
@ -3853,7 +3858,7 @@ cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIO
static
void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsICCViewingConditions));
cmsUNUSED_PARAMETER(n);
}
@ -5451,8 +5456,9 @@ static _cmsTagLinkedList SupportedTags[] = {
{ cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL }, &SupportedTags[59]},
{ cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL }, &SupportedTags[60]},
{ cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL }, &SupportedTags[61]},
{ cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]},
{ cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL}
{ cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL }, &SupportedTags[62]},
{ cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]},
{ cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL}, NULL}
};

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2014 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -642,7 +642,7 @@ cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
// Create the ICC virtual profile for sRGB space
cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
{
cmsCIExyY D65;
cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 };
cmsCIExyYTRIPLE Rec709Primaries = {
{0.6400, 0.3300, 1.0},
{0.3000, 0.6000, 1.0},
@ -651,7 +651,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
cmsToneCurve* Gamma22[3];
cmsHPROFILE hsRGB;
cmsWhitePointFromTemp(&D65, 6504);
// cmsWhitePointFromTemp(&D65, 6504);
Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
if (Gamma22[0] == NULL) return NULL;
@ -679,6 +679,7 @@ typedef struct {
cmsFloat64Number Contrast;
cmsFloat64Number Hue;
cmsFloat64Number Saturation;
cmsBool lAdjustWP;
cmsCIEXYZ WPsrc, WPdest;
} BCHSWADJUSTS, *LPBCHSWADJUSTS;
@ -708,9 +709,10 @@ int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number O
cmsLCh2Lab(&LabOut, &LChOut);
// Move white point in Lab
cmsLab2XYZ(&bchsw ->WPsrc, &XYZ, &LabOut);
cmsXYZ2Lab(&bchsw ->WPdest, &LabOut, &XYZ);
if (bchsw->lAdjustWP) {
cmsLab2XYZ(&bchsw->WPsrc, &XYZ, &LabOut);
cmsXYZ2Lab(&bchsw->WPdest, &LabOut, &XYZ);
}
// Back to encoded
@ -744,18 +746,23 @@ cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
bchsw.Contrast = Contrast;
bchsw.Hue = Hue;
bchsw.Saturation = Saturation;
if (TempSrc == TempDest) {
cmsWhitePointFromTemp(&WhitePnt, TempSrc );
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
cmsWhitePointFromTemp(&WhitePnt, TempDest);
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
bchsw.lAdjustWP = FALSE;
}
else {
bchsw.lAdjustWP = TRUE;
cmsWhitePointFromTemp(&WhitePnt, TempSrc);
cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
cmsWhitePointFromTemp(&WhitePnt, TempDest);
cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
}
hICC = cmsCreateProfilePlaceholder(ContextID);
if (!hICC) // can't allocate
return NULL;
cmsSetDeviceClass(hICC, cmsSigAbstractClass);
cmsSetColorSpace(hICC, cmsSigLabData);
cmsSetPCS(hICC, cmsSigLabData);
@ -988,12 +995,14 @@ typedef struct {
} cmsAllowedLUT;
#define cmsSig0 ((cmsTagSignature) 0)
static const cmsAllowedLUT AllowedLUTTypes[] = {
{ FALSE, 0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
{ FALSE, 0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType}},
{ TRUE , 0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType }},
{ FALSE, cmsSig0, cmsSigLut16Type, 4, { cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
{ FALSE, cmsSig0, cmsSigLut16Type, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
{ FALSE, cmsSig0, cmsSigLut16Type, 2, { cmsSigCurveSetElemType, cmsSigCLutElemType } },
{ TRUE, cmsSig0, cmsSigLutAtoBType, 1, { cmsSigCurveSetElemType } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 3, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType } },
{ TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType, 5, { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2014 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),

View File

@ -1,7 +1,7 @@
//---------------------------------------------------------------------------------
//
// Little Color Management System
// Copyright (c) 1998-2014 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -179,12 +179,18 @@ void CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
{
_cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
cmsStride stride;
p -> xform(p, InputBuffer, OutputBuffer, Size, Size);
stride.BytesPerLineIn = 0; // Not used
stride.BytesPerLineOut = 0;
stride.BytesPerPlaneIn = Size;
stride.BytesPerPlaneOut = Size;
p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
}
// Apply transform.
// This is a legacy stride for planar
void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform,
const void* InputBuffer,
void* OutputBuffer,
@ -192,10 +198,40 @@ void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform,
{
_cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
cmsStride stride;
p -> xform(p, InputBuffer, OutputBuffer, Size, Stride);
stride.BytesPerLineIn = 0;
stride.BytesPerLineOut = 0;
stride.BytesPerPlaneIn = Stride;
stride.BytesPerPlaneOut = Stride;
p -> xform(p, InputBuffer, OutputBuffer, Size, 1, &stride);
}
// This is the "fast" function for plugins
void CMSEXPORT cmsDoTransformLineStride(cmsHTRANSFORM Transform,
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
cmsUInt32Number BytesPerLineIn,
cmsUInt32Number BytesPerLineOut,
cmsUInt32Number BytesPerPlaneIn,
cmsUInt32Number BytesPerPlaneOut)
{
_cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
cmsStride stride;
stride.BytesPerLineIn = BytesPerLineIn;
stride.BytesPerLineOut = BytesPerLineOut;
stride.BytesPerPlaneIn = BytesPerPlaneIn;
stride.BytesPerPlaneOut = BytesPerPlaneOut;
p->xform(p, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, &stride);
}
// Transform routines ----------------------------------------------------------------------------------------------------------
@ -204,49 +240,64 @@ void CMSEXPORT cmsDoTransformStride(cmsHTRANSFORM Transform,
static
void FloatXFORM(_cmsTRANSFORM* p,
const void* in,
void* out, cmsUInt32Number Size, cmsUInt32Number Stride)
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
cmsFloat32Number OutOfGamut;
cmsUInt32Number i, j;
cmsUInt32Number i, j, c, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
for (i=0; i < Size; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInputFloat(p, fIn, accum, Stride);
for (i = 0; i < LineCount; i++) {
// Any gamut chack to do?
if (p ->GamutCheck != NULL) {
accum = (cmsUInt8Number*)in + strideIn;
output = (cmsUInt8Number*)out + strideOut;
// Evaluate gamut marker.
cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck);
for (j = 0; j < PixelsPerLine; j++) {
// Is current color out of gamut?
if (OutOfGamut > 0.0) {
accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn);
// Certainly, out of gamut
for (j=0; j < cmsMAXCHANNELS; j++)
fOut[j] = -1.0;
// Any gamut chack to do?
if (p->GamutCheck != NULL) {
// Evaluate gamut marker.
cmsPipelineEvalFloat(fIn, &OutOfGamut, p->GamutCheck);
// Is current color out of gamut?
if (OutOfGamut > 0.0) {
// Certainly, out of gamut
for (c = 0; c < cmsMAXCHANNELS; c++)
fOut[c] = -1.0;
}
else {
// No, proceed normally
cmsPipelineEvalFloat(fIn, fOut, p->Lut);
}
}
else {
// No, proceed normally
cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
// No gamut check at all
cmsPipelineEvalFloat(fIn, fOut, p->Lut);
}
}
else {
// No gamut check at all
cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
output = p->ToOutputFloat(p, fOut, output, Stride->BytesPerPlaneOut);
}
// Back to asked representation
output = p -> ToOutputFloat(p, fOut, output, Stride);
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
@ -254,22 +305,34 @@ static
void NullFloatXFORM(_cmsTRANSFORM* p,
const void* in,
void* out,
cmsUInt32Number Size,
cmsUInt32Number Stride)
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsFloat32Number fIn[cmsMAXCHANNELS];
cmsUInt32Number i, n;
cmsUInt32Number i, j, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
n = Size;
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
for (i=0; i < n; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInputFloat(p, fIn, accum, Stride);
output = p -> ToOutputFloat(p, fIn, output, Stride);
for (i = 0; i < LineCount; i++) {
accum = (cmsUInt8Number*) in + strideIn;
output = (cmsUInt8Number*) out + strideOut;
for (j = 0; j < PixelsPerLine; j++) {
accum = p->FromInputFloat(p, fIn, accum, Stride ->BytesPerPlaneIn);
output = p->ToOutputFloat(p, fIn, output, Stride->BytesPerPlaneOut);
}
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
@ -279,23 +342,36 @@ void NullFloatXFORM(_cmsTRANSFORM* p,
static
void NullXFORM(_cmsTRANSFORM* p,
const void* in,
void* out, cmsUInt32Number Size,
cmsUInt32Number Stride)
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsUInt16Number wIn[cmsMAXCHANNELS];
cmsUInt32Number i, n;
cmsUInt32Number i, j, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
n = Size; // Buffer len
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
for (i=0; i < n; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInput(p, wIn, accum, Stride);
output = p -> ToOutput(p, wIn, output, Stride);
for (i = 0; i < LineCount; i++) {
accum = (cmsUInt8Number*)in + strideIn;
output = (cmsUInt8Number*)out + strideOut;
for (j = 0; j < PixelsPerLine; j++) {
accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
}
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
@ -303,23 +379,37 @@ void NullXFORM(_cmsTRANSFORM* p,
static
void PrecalculatedXFORM(_cmsTRANSFORM* p,
const void* in,
void* out, cmsUInt32Number Size, cmsUInt32Number Stride)
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
register cmsUInt8Number* accum;
register cmsUInt8Number* output;
cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
cmsUInt32Number i, n;
cmsUInt32Number i, j, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
n = Size;
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
for (i=0; i < n; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInput(p, wIn, accum, Stride);
p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
output = p -> ToOutput(p, wOut, output, Stride);
for (i = 0; i < LineCount; i++) {
accum = (cmsUInt8Number*)in + strideIn;
output = (cmsUInt8Number*)out + strideOut;
for (j = 0; j < PixelsPerLine; j++) {
accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
}
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
@ -350,22 +440,35 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
static
void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
const void* in,
void* out, cmsUInt32Number Size, cmsUInt32Number Stride)
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
cmsUInt32Number i, n;
cmsUInt32Number i, j, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
n = Size; // Buffer len
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
for (i=0; i < n; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInput(p, wIn, accum, Stride);
TransformOnePixelWithGamutCheck(p, wIn, wOut);
output = p -> ToOutput(p, wOut, output, Stride);
for (i = 0; i < LineCount; i++) {
accum = (cmsUInt8Number*)in + strideIn;
output = (cmsUInt8Number*)out + strideOut;
for (j = 0; j < PixelsPerLine; j++) {
accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
TransformOnePixelWithGamutCheck(p, wIn, wOut);
output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
}
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
@ -374,94 +477,120 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
static
void CachedXFORM(_cmsTRANSFORM* p,
const void* in,
void* out, cmsUInt32Number Size, cmsUInt32Number Stride)
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
cmsUInt32Number i, n;
_cmsCACHE Cache;
cmsUInt32Number i, j, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
n = Size; // Buffer len
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
// Empty buffers for quick memcmp
memset(wIn, 0, sizeof(wIn));
memset(wIn, 0, sizeof(wIn));
memset(wOut, 0, sizeof(wOut));
// Get copy of zero cache
memcpy(&Cache, &p ->Cache, sizeof(Cache));
memcpy(&Cache, &p->Cache, sizeof(Cache));
for (i=0; i < n; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInput(p, wIn, accum, Stride);
for (i = 0; i < LineCount; i++) {
if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
accum = (cmsUInt8Number*)in + strideIn;
output = (cmsUInt8Number*)out + strideOut;
memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
}
else {
for (j = 0; j < PixelsPerLine; j++) {
p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
}
else {
p->Lut->Eval16Fn(wIn, wOut, p->Lut->Data);
memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
}
output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
}
output = p -> ToOutput(p, wOut, output, Stride);
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
// All those nice features together
static
void CachedXFORMGamutCheck(_cmsTRANSFORM* p,
const void* in,
void* out, cmsUInt32Number Size, cmsUInt32Number Stride)
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
cmsUInt32Number i, n;
_cmsCACHE Cache;
cmsUInt8Number* accum;
cmsUInt8Number* output;
cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
_cmsCACHE Cache;
cmsUInt32Number i, j, strideIn, strideOut;
accum = (cmsUInt8Number*) in;
output = (cmsUInt8Number*) out;
n = Size; // Buffer len
_cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
// Empty buffers for quick memcmp
memset(wIn, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
// Empty buffers for quick memcmp
memset(wIn, 0, sizeof(wIn));
memset(wOut, 0, sizeof(wOut));
// Get copy of zero cache
memcpy(&Cache, &p ->Cache, sizeof(Cache));
// Get copy of zero cache
memcpy(&Cache, &p->Cache, sizeof(Cache));
for (i=0; i < n; i++) {
strideIn = 0;
strideOut = 0;
accum = p -> FromInput(p, wIn, accum, Stride);
for (i = 0; i < LineCount; i++) {
accum = (cmsUInt8Number*)in + strideIn;
output = (cmsUInt8Number*)out + strideOut;
for (j = 0; j < PixelsPerLine; j++) {
accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
if (memcmp(wIn, Cache.CacheIn, sizeof(Cache.CacheIn)) == 0) {
memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
memcpy(wOut, Cache.CacheOut, sizeof(Cache.CacheOut));
}
else {
TransformOnePixelWithGamutCheck(p, wIn, wOut);
memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
TransformOnePixelWithGamutCheck(p, wIn, wOut);
memcpy(Cache.CacheIn, wIn, sizeof(Cache.CacheIn));
memcpy(Cache.CacheOut, wOut, sizeof(Cache.CacheOut));
}
output = p -> ToOutput(p, wOut, output, Stride);
}
output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
}
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
// -------------------------------------------------------------------------------------------------------------
// Transform plug-ins ----------------------------------------------------------------------------------------------------
// List of used-defined transform factories
typedef struct _cmsTransformCollection_st {
_cmsTransformFactory Factory;
_cmsTransform2Factory Factory;
cmsBool OldXform; // Factory returns xform function in the old style
struct _cmsTransformCollection_st *Next;
} _cmsTransformCollection;
@ -504,6 +633,7 @@ void DupPluginTransformList(struct _cmsContext_struct* ctx,
ctx ->chunks[TransformPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTransformPluginChunkType));
}
// Allocates memory for transform plugin factory
void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
const struct _cmsContext_struct* src)
{
@ -518,6 +648,35 @@ void _cmsAllocTransformPluginChunk(struct _cmsContext_struct* ctx,
}
}
// Adaptor for old versions of plug-in
static
void _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo,
const void* InputBuffer,
void* OutputBuffer,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride)
{
cmsUInt32Number i, strideIn, strideOut;
_cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
strideIn = 0;
strideOut = 0;
for (i = 0; i < LineCount; i++) {
void *accum = (cmsUInt8Number*)InputBuffer + strideIn;
void *output = (cmsUInt8Number*)OutputBuffer + strideOut;
CMMcargo->OldXform(CMMcargo, accum, output, PixelsPerLine, Stride->BytesPerPlaneIn);
strideIn += Stride->BytesPerLineIn;
strideOut += Stride->BytesPerLineOut;
}
}
// Register new ways to transform
@ -535,14 +694,22 @@ cmsBool _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Data)
}
// Factory callback is required
if (Plugin ->Factory == NULL) return FALSE;
if (Plugin->factories.xform == NULL) return FALSE;
fl = (_cmsTransformCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsTransformCollection));
if (fl == NULL) return FALSE;
// Check for full xform plug-ins previous to 2.8, we would need an adapter in that case
if (Plugin->base.ExpectedVersion < 2080) {
fl->OldXform = TRUE;
}
else
fl->OldXform = FALSE;
// Copy the parameters
fl ->Factory = Plugin ->Factory;
fl->Factory = Plugin->factories.xform;
// Keep linked list
fl ->Next = ctx->TransformCollection;
@ -592,46 +759,54 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
_cmsTransformPluginChunkType* ctx = ( _cmsTransformPluginChunkType*) _cmsContextGetClientChunk(ContextID, TransformPlugin);
_cmsTransformCollection* Plugin;
// Allocate needed memory
_cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
if (!p) return NULL;
// Allocate needed memory
_cmsTRANSFORM* p = (_cmsTRANSFORM*)_cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
if (!p) return NULL;
// Store the proposed pipeline
p ->Lut = lut;
// Store the proposed pipeline
p->Lut = lut;
// Let's see if any plug-in want to do the transform by itself
for (Plugin = ctx ->TransformCollection;
Plugin != NULL;
Plugin = Plugin ->Next) {
// Let's see if any plug-in want to do the transform by itself
if (p->Lut != NULL) {
if (Plugin ->Factory(&p->xform, &p->UserData, &p ->FreeUserData, &p ->Lut, InputFormat, OutputFormat, dwFlags)) {
// Last plugin in the declaration order takes control. We just keep
// the original parameters as a logging.
// Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
// an optimized transform is not reusable. The plug-in can, however, change
// the flags and make it suitable.
for (Plugin = ctx->TransformCollection;
Plugin != NULL;
Plugin = Plugin->Next) {
p ->ContextID = ContextID;
p ->InputFormat = *InputFormat;
p ->OutputFormat = *OutputFormat;
p ->dwOriginalFlags = *dwFlags;
// Fill the formatters just in case the optimized routine is interested.
// No error is thrown if the formatter doesn't exist. It is up to the optimization
// factory to decide what to do in those cases.
p ->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
p ->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
p ->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
p ->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
if (Plugin->Factory(&p->xform, &p->UserData, &p->FreeUserData, &p->Lut, InputFormat, OutputFormat, dwFlags)) {
return p;
}
}
// Last plugin in the declaration order takes control. We just keep
// the original parameters as a logging.
// Note that cmsFLAGS_CAN_CHANGE_FORMATTER is not set, so by default
// an optimized transform is not reusable. The plug-in can, however, change
// the flags and make it suitable.
// Not suitable for the transform plug-in, let's check the pipeline plug-in
if (p ->Lut != NULL)
_cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
p->ContextID = ContextID;
p->InputFormat = *InputFormat;
p->OutputFormat = *OutputFormat;
p->dwOriginalFlags = *dwFlags;
// Fill the formatters just in case the optimized routine is interested.
// No error is thrown if the formatter doesn't exist. It is up to the optimization
// factory to decide what to do in those cases.
p->FromInput = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
p->ToOutput = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
p->FromInputFloat = _cmsGetFormatter(ContextID, *InputFormat, cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
p->ToOutputFloat = _cmsGetFormatter(ContextID, *OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
// Save the day?
if (Plugin->OldXform) {
p->OldXform = (_cmsTransformFn) p->xform;
p->xform = _cmsTransform2toTransformAdaptor;
}
return p;
}
}
// Not suitable for the transform plug-in, let's check the pipeline plug-in
_cmsOptimizePipeline(ContextID, &p->Lut, Intent, InputFormat, OutputFormat, dwFlags);
}
// Check whatever this is a true floating point transform
if (_cmsFormatterIsFloat(*InputFormat) && _cmsFormatterIsFloat(*OutputFormat)) {
@ -785,6 +960,22 @@ cmsBool IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwForm
// ----------------------------------------------------------------------------------------------------------------
// Jun-21-2000: Some profiles (those that comes with W2K) comes
// with the media white (media black?) x 100. Add a sanity check
static
void NormalizeXYZ(cmsCIEXYZ* Dest)
{
while (Dest -> X > 2. &&
Dest -> Y > 2. &&
Dest -> Z > 2.) {
Dest -> X /= 10.;
Dest -> Y /= 10.;
Dest -> Z /= 10.;
}
}
static
void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
{
@ -797,6 +988,8 @@ void SetWhitePoint(cmsCIEXYZ* wtPt, const cmsCIEXYZ* src)
wtPt ->X = src->X;
wtPt ->Y = src->Y;
wtPt ->Z = src->Z;
NormalizeXYZ(wtPt);
}
}
@ -1107,7 +1300,6 @@ cmsBool CMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
cmsUInt32Number InputFormat,
cmsUInt32Number OutputFormat)
{
_cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
cmsFormatter16 FromInput, ToOutput;

View File

@ -1,341 +0,0 @@
LIBRARY LCMS2.DLL
EXPORTS
_cms15Fixed16toDouble = _cms15Fixed16toDouble
_cms8Fixed8toDouble = _cms8Fixed8toDouble
cmsAdaptToIlluminant = cmsAdaptToIlluminant
_cmsAdjustEndianess16 = _cmsAdjustEndianess16
_cmsAdjustEndianess32 = _cmsAdjustEndianess32
_cmsAdjustEndianess64 = _cmsAdjustEndianess64
cmsAllocNamedColorList = cmsAllocNamedColorList
cmsAllocProfileSequenceDescription = cmsAllocProfileSequenceDescription
cmsAppendNamedColor = cmsAppendNamedColor
cmsBFDdeltaE = cmsBFDdeltaE
cmsBuildGamma = cmsBuildGamma
cmsBuildParametricToneCurve = cmsBuildParametricToneCurve
cmsBuildSegmentedToneCurve = cmsBuildSegmentedToneCurve
cmsBuildTabulatedToneCurve16 = cmsBuildTabulatedToneCurve16
cmsBuildTabulatedToneCurveFloat = cmsBuildTabulatedToneCurveFloat
_cmsCalloc = _cmsCalloc
cmsChannelsOf = cmsChannelsOf
cmsCIE2000DeltaE = cmsCIE2000DeltaE
cmsCIE94DeltaE = cmsCIE94DeltaE
cmsCIECAM02Done = cmsCIECAM02Done
cmsCIECAM02Forward = cmsCIECAM02Forward
cmsCIECAM02Init = cmsCIECAM02Init
cmsCIECAM02Reverse = cmsCIECAM02Reverse
cmsCloseIOhandler = cmsCloseIOhandler
cmsCloseProfile = cmsCloseProfile
cmsCMCdeltaE = cmsCMCdeltaE
cmsCreate_sRGBProfile = cmsCreate_sRGBProfile
cmsCreate_sRGBProfileTHR = cmsCreate_sRGBProfileTHR
cmsCreateBCHSWabstractProfile = cmsCreateBCHSWabstractProfile
cmsCreateBCHSWabstractProfileTHR = cmsCreateBCHSWabstractProfileTHR
cmsCreateExtendedTransform = cmsCreateExtendedTransform
cmsCreateGrayProfile = cmsCreateGrayProfile
cmsCreateGrayProfileTHR = cmsCreateGrayProfileTHR
cmsCreateInkLimitingDeviceLink = cmsCreateInkLimitingDeviceLink
cmsCreateInkLimitingDeviceLinkTHR = cmsCreateInkLimitingDeviceLinkTHR
cmsCreateLab2Profile = cmsCreateLab2Profile
cmsCreateLab2ProfileTHR = cmsCreateLab2ProfileTHR
cmsCreateLab4Profile = cmsCreateLab4Profile
cmsCreateLab4ProfileTHR = cmsCreateLab4ProfileTHR
cmsCreateLinearizationDeviceLink = cmsCreateLinearizationDeviceLink
cmsCreateLinearizationDeviceLinkTHR = cmsCreateLinearizationDeviceLinkTHR
cmsCreateMultiprofileTransform = cmsCreateMultiprofileTransform
cmsCreateMultiprofileTransformTHR = cmsCreateMultiprofileTransformTHR
cmsCreateNULLProfile = cmsCreateNULLProfile
cmsCreateNULLProfileTHR = cmsCreateNULLProfileTHR
cmsCreateProfilePlaceholder = cmsCreateProfilePlaceholder
cmsCreateProofingTransform = cmsCreateProofingTransform
cmsCreateProofingTransformTHR = cmsCreateProofingTransformTHR
cmsCreateRGBProfile = cmsCreateRGBProfile
cmsCreateRGBProfileTHR = cmsCreateRGBProfileTHR
cmsCreateTransform = cmsCreateTransform
cmsCreateTransformTHR = cmsCreateTransformTHR
cmsCreateXYZProfile = cmsCreateXYZProfile
cmsCreateXYZProfileTHR = cmsCreateXYZProfileTHR
cmsD50_xyY = cmsD50_xyY
cmsD50_XYZ = cmsD50_XYZ
_cmsDecodeDateTimeNumber = _cmsDecodeDateTimeNumber
_cmsDefaultICCintents = _cmsDefaultICCintents
cmsDeleteTransform = cmsDeleteTransform
cmsDeltaE = cmsDeltaE
cmsDetectBlackPoint = cmsDetectBlackPoint
cmsDetectDestinationBlackPoint = cmsDetectDestinationBlackPoint
cmsDetectTAC = cmsDetectTAC
cmsDesaturateLab = cmsDesaturateLab
cmsDoTransform = cmsDoTransform
cmsDoTransformStride = cmsDoTransformStride
_cmsDoubleTo15Fixed16 = _cmsDoubleTo15Fixed16
_cmsDoubleTo8Fixed8 = _cmsDoubleTo8Fixed8
_cmsDupMem = _cmsDupMem
cmsDupNamedColorList = cmsDupNamedColorList
cmsDupProfileSequenceDescription = cmsDupProfileSequenceDescription
cmsDupToneCurve = cmsDupToneCurve
_cmsEncodeDateTimeNumber = _cmsEncodeDateTimeNumber
cmsEstimateGamma = cmsEstimateGamma
cmsGetToneCurveEstimatedTableEntries = cmsGetToneCurveEstimatedTableEntries
cmsGetToneCurveEstimatedTable = cmsGetToneCurveEstimatedTable
cmsEvalToneCurve16 = cmsEvalToneCurve16
cmsEvalToneCurveFloat = cmsEvalToneCurveFloat
cmsfilelength = cmsfilelength
cmsFloat2LabEncoded = cmsFloat2LabEncoded
cmsFloat2LabEncodedV2 = cmsFloat2LabEncodedV2
cmsFloat2XYZEncoded = cmsFloat2XYZEncoded
cmsFormatterForColorspaceOfProfile = cmsFormatterForColorspaceOfProfile
cmsFormatterForPCSOfProfile = cmsFormatterForPCSOfProfile
_cmsFree = _cmsFree
cmsFreeNamedColorList = cmsFreeNamedColorList
cmsFreeProfileSequenceDescription = cmsFreeProfileSequenceDescription
cmsFreeToneCurve = cmsFreeToneCurve
cmsFreeToneCurveTriple = cmsFreeToneCurveTriple
cmsGBDAlloc = cmsGBDAlloc
cmsGBDFree = cmsGBDFree
cmsGDBAddPoint = cmsGDBAddPoint
cmsGDBCheckPoint = cmsGDBCheckPoint
cmsGDBCompute = cmsGDBCompute
cmsGetAlarmCodes = cmsGetAlarmCodes
cmsGetColorSpace = cmsGetColorSpace
cmsGetDeviceClass = cmsGetDeviceClass
cmsGetEncodedICCversion = cmsGetEncodedICCversion
cmsGetHeaderAttributes = cmsGetHeaderAttributes
cmsGetHeaderCreationDateTime = cmsGetHeaderCreationDateTime
cmsGetHeaderFlags = cmsGetHeaderFlags
cmsGetHeaderManufacturer = cmsGetHeaderManufacturer
cmsGetHeaderModel = cmsGetHeaderModel
cmsGetHeaderProfileID = cmsGetHeaderProfileID
cmsGetHeaderRenderingIntent = cmsGetHeaderRenderingIntent
cmsGetNamedColorList = cmsGetNamedColorList
cmsGetPCS = cmsGetPCS
cmsGetPostScriptColorResource = cmsGetPostScriptColorResource
cmsGetPostScriptCRD = cmsGetPostScriptCRD
cmsGetPostScriptCSA = cmsGetPostScriptCSA
cmsGetProfileInfo = cmsGetProfileInfo
cmsGetProfileInfoASCII = cmsGetProfileInfoASCII
cmsGetProfileContextID = cmsGetProfileContextID
cmsGetProfileVersion = cmsGetProfileVersion
cmsGetSupportedIntents = cmsGetSupportedIntents
cmsGetTagCount = cmsGetTagCount
cmsGetTagSignature = cmsGetTagSignature
cmsGetTransformContextID = cmsGetTransformContextID
_cmsICCcolorSpace = _cmsICCcolorSpace
_cmsIOPrintf = _cmsIOPrintf
cmsIsCLUT = cmsIsCLUT
cmsIsIntentSupported = cmsIsIntentSupported
cmsIsMatrixShaper = cmsIsMatrixShaper
cmsIsTag = cmsIsTag
cmsIsToneCurveDescending = cmsIsToneCurveDescending
cmsIsToneCurveLinear = cmsIsToneCurveLinear
cmsIsToneCurveMonotonic = cmsIsToneCurveMonotonic
cmsIsToneCurveMultisegment = cmsIsToneCurveMultisegment
cmsGetToneCurveParametricType = cmsGetToneCurveParametricType
cmsIT8Alloc = cmsIT8Alloc
cmsIT8DefineDblFormat = cmsIT8DefineDblFormat
cmsIT8EnumDataFormat = cmsIT8EnumDataFormat
cmsIT8EnumProperties = cmsIT8EnumProperties
cmsIT8EnumPropertyMulti = cmsIT8EnumPropertyMulti
cmsIT8Free = cmsIT8Free
cmsIT8GetData = cmsIT8GetData
cmsIT8GetDataDbl = cmsIT8GetDataDbl
cmsIT8FindDataFormat = cmsIT8FindDataFormat
cmsIT8GetDataRowCol = cmsIT8GetDataRowCol
cmsIT8GetDataRowColDbl = cmsIT8GetDataRowColDbl
cmsIT8GetPatchName = cmsIT8GetPatchName
cmsIT8GetPatchByName = cmsIT8GetPatchByName
cmsIT8GetProperty = cmsIT8GetProperty
cmsIT8GetPropertyDbl = cmsIT8GetPropertyDbl
cmsIT8GetPropertyMulti = cmsIT8GetPropertyMulti
cmsIT8GetSheetType = cmsIT8GetSheetType
cmsIT8LoadFromFile = cmsIT8LoadFromFile
cmsIT8LoadFromMem = cmsIT8LoadFromMem
cmsIT8SaveToFile = cmsIT8SaveToFile
cmsIT8SaveToMem = cmsIT8SaveToMem
cmsIT8SetComment = cmsIT8SetComment
cmsIT8SetData = cmsIT8SetData
cmsIT8SetDataDbl = cmsIT8SetDataDbl
cmsIT8SetDataFormat = cmsIT8SetDataFormat
cmsIT8SetDataRowCol = cmsIT8SetDataRowCol
cmsIT8SetDataRowColDbl = cmsIT8SetDataRowColDbl
cmsIT8SetPropertyDbl = cmsIT8SetPropertyDbl
cmsIT8SetPropertyHex = cmsIT8SetPropertyHex
cmsIT8SetPropertyStr = cmsIT8SetPropertyStr
cmsIT8SetPropertyMulti = cmsIT8SetPropertyMulti
cmsIT8SetPropertyUncooked = cmsIT8SetPropertyUncooked
cmsIT8SetSheetType = cmsIT8SetSheetType
cmsIT8SetTable = cmsIT8SetTable
cmsIT8SetTableByLabel = cmsIT8SetTableByLabel
cmsIT8SetIndexColumn = cmsIT8SetIndexColumn
cmsIT8TableCount = cmsIT8TableCount
cmsJoinToneCurve = cmsJoinToneCurve
cmsLab2LCh = cmsLab2LCh
cmsLab2XYZ = cmsLab2XYZ
cmsLabEncoded2Float = cmsLabEncoded2Float
cmsLabEncoded2FloatV2 = cmsLabEncoded2FloatV2
cmsLCh2Lab = cmsLCh2Lab
_cmsLCMScolorSpace = _cmsLCMScolorSpace
cmsLinkTag = cmsLinkTag
cmsTagLinkedTo = cmsTagLinkedTo
cmsPipelineAlloc = cmsPipelineAlloc
cmsPipelineCat = cmsPipelineCat
cmsPipelineCheckAndRetreiveStages = cmsPipelineCheckAndRetreiveStages
cmsPipelineDup = cmsPipelineDup
cmsPipelineStageCount = cmsPipelineStageCount
cmsPipelineEval16 = cmsPipelineEval16
cmsPipelineEvalFloat = cmsPipelineEvalFloat
cmsPipelineEvalReverseFloat = cmsPipelineEvalReverseFloat
cmsPipelineFree = cmsPipelineFree
cmsPipelineGetPtrToFirstStage = cmsPipelineGetPtrToFirstStage
cmsPipelineGetPtrToLastStage = cmsPipelineGetPtrToLastStage
cmsPipelineInputChannels = cmsPipelineInputChannels
cmsPipelineInsertStage = cmsPipelineInsertStage
cmsPipelineOutputChannels = cmsPipelineOutputChannels
cmsPipelineSetSaveAs8bitsFlag = cmsPipelineSetSaveAs8bitsFlag
_cmsPipelineSetOptimizationParameters = _cmsPipelineSetOptimizationParameters
cmsPipelineUnlinkStage = cmsPipelineUnlinkStage
_cmsMalloc = _cmsMalloc
_cmsMallocZero = _cmsMallocZero
_cmsMAT3eval = _cmsMAT3eval
_cmsMAT3identity = _cmsMAT3identity
_cmsMAT3inverse = _cmsMAT3inverse
_cmsMAT3isIdentity = _cmsMAT3isIdentity
_cmsMAT3per = _cmsMAT3per
_cmsMAT3solve = _cmsMAT3solve
cmsMD5computeID = cmsMD5computeID
cmsMLUalloc = cmsMLUalloc
cmsMLUdup = cmsMLUdup
cmsMLUfree = cmsMLUfree
cmsMLUgetASCII = cmsMLUgetASCII
cmsMLUgetTranslation = cmsMLUgetTranslation
cmsMLUgetWide = cmsMLUgetWide
cmsMLUsetASCII = cmsMLUsetASCII
cmsMLUsetWide = cmsMLUsetWide
cmsStageAllocCLut16bit = cmsStageAllocCLut16bit
cmsStageAllocCLut16bitGranular = cmsStageAllocCLut16bitGranular
cmsStageAllocCLutFloat = cmsStageAllocCLutFloat
cmsStageAllocCLutFloatGranular = cmsStageAllocCLutFloatGranular
cmsStageAllocToneCurves = cmsStageAllocToneCurves
cmsStageAllocIdentity = cmsStageAllocIdentity
cmsStageAllocMatrix = cmsStageAllocMatrix
_cmsStageAllocPlaceholder = _cmsStageAllocPlaceholder
cmsStageDup = cmsStageDup
cmsStageFree = cmsStageFree
cmsStageNext = cmsStageNext
cmsStageInputChannels = cmsStageInputChannels
cmsStageOutputChannels = cmsStageOutputChannels
cmsStageSampleCLut16bit = cmsStageSampleCLut16bit
cmsStageSampleCLutFloat = cmsStageSampleCLutFloat
cmsStageType = cmsStageType
cmsStageData = cmsStageData
cmsNamedColorCount = cmsNamedColorCount
cmsNamedColorIndex = cmsNamedColorIndex
cmsNamedColorInfo = cmsNamedColorInfo
cmsOpenIOhandlerFromFile = cmsOpenIOhandlerFromFile
cmsOpenIOhandlerFromMem = cmsOpenIOhandlerFromMem
cmsOpenIOhandlerFromNULL = cmsOpenIOhandlerFromNULL
cmsOpenIOhandlerFromStream = cmsOpenIOhandlerFromStream
cmsOpenProfileFromFile = cmsOpenProfileFromFile
cmsOpenProfileFromFileTHR = cmsOpenProfileFromFileTHR
cmsOpenProfileFromIOhandlerTHR = cmsOpenProfileFromIOhandlerTHR
cmsOpenProfileFromMem = cmsOpenProfileFromMem
cmsOpenProfileFromMemTHR = cmsOpenProfileFromMemTHR
cmsOpenProfileFromStream = cmsOpenProfileFromStream
cmsOpenProfileFromStreamTHR = cmsOpenProfileFromStreamTHR
cmsPlugin = cmsPlugin
_cmsRead15Fixed16Number = _cmsRead15Fixed16Number
_cmsReadAlignment = _cmsReadAlignment
_cmsReadFloat32Number = _cmsReadFloat32Number
cmsReadRawTag = cmsReadRawTag
cmsReadTag = cmsReadTag
_cmsReadTypeBase = _cmsReadTypeBase
_cmsReadUInt16Array = _cmsReadUInt16Array
_cmsReadUInt16Number = _cmsReadUInt16Number
_cmsReadUInt32Number = _cmsReadUInt32Number
_cmsReadUInt64Number = _cmsReadUInt64Number
_cmsReadUInt8Number = _cmsReadUInt8Number
_cmsReadXYZNumber = _cmsReadXYZNumber
_cmsRealloc = _cmsRealloc
cmsReverseToneCurve = cmsReverseToneCurve
cmsReverseToneCurveEx = cmsReverseToneCurveEx
cmsSaveProfileToFile = cmsSaveProfileToFile
cmsSaveProfileToIOhandler = cmsSaveProfileToIOhandler
cmsSaveProfileToMem = cmsSaveProfileToMem
cmsSaveProfileToStream = cmsSaveProfileToStream
cmsSetAdaptationState = cmsSetAdaptationState
cmsSetAlarmCodes = cmsSetAlarmCodes
cmsSetColorSpace = cmsSetColorSpace
cmsSetDeviceClass = cmsSetDeviceClass
cmsSetEncodedICCversion = cmsSetEncodedICCversion
cmsSetHeaderAttributes = cmsSetHeaderAttributes
cmsSetHeaderFlags = cmsSetHeaderFlags
cmsSetHeaderManufacturer = cmsSetHeaderManufacturer
cmsSetHeaderModel = cmsSetHeaderModel
cmsSetHeaderProfileID = cmsSetHeaderProfileID
cmsSetHeaderRenderingIntent = cmsSetHeaderRenderingIntent
cmsSetLogErrorHandler = cmsSetLogErrorHandler
cmsSetPCS = cmsSetPCS
cmsSetProfileVersion = cmsSetProfileVersion
cmsSignalError = cmsSignalError
cmsSmoothToneCurve = cmsSmoothToneCurve
cmsstrcasecmp = cmsstrcasecmp
cmsTempFromWhitePoint = cmsTempFromWhitePoint
cmsTransform2DeviceLink = cmsTransform2DeviceLink
cmsUnregisterPlugins = cmsUnregisterPlugins
_cmsVEC3cross = _cmsVEC3cross
_cmsVEC3distance = _cmsVEC3distance
_cmsVEC3dot = _cmsVEC3dot
_cmsVEC3init = _cmsVEC3init
_cmsVEC3length = _cmsVEC3length
_cmsVEC3minus = _cmsVEC3minus
cmsWhitePointFromTemp = cmsWhitePointFromTemp
_cmsWrite15Fixed16Number = _cmsWrite15Fixed16Number
_cmsWriteAlignment = _cmsWriteAlignment
_cmsWriteFloat32Number = _cmsWriteFloat32Number
cmsWriteRawTag = cmsWriteRawTag
cmsWriteTag = cmsWriteTag
_cmsWriteTypeBase = _cmsWriteTypeBase
_cmsWriteUInt16Array = _cmsWriteUInt16Array
_cmsWriteUInt16Number = _cmsWriteUInt16Number
_cmsWriteUInt32Number = _cmsWriteUInt32Number
_cmsWriteUInt64Number = _cmsWriteUInt64Number
_cmsWriteUInt8Number = _cmsWriteUInt8Number
_cmsWriteXYZNumber = _cmsWriteXYZNumber
cmsxyY2XYZ = cmsxyY2XYZ
cmsXYZ2Lab = cmsXYZ2Lab
cmsXYZ2xyY = cmsXYZ2xyY
cmsXYZEncoded2Float = cmsXYZEncoded2Float
cmsSliceSpace16 = cmsSliceSpace16
cmsSliceSpaceFloat = cmsSliceSpaceFloat
cmsChangeBuffersFormat = cmsChangeBuffersFormat
cmsDictAlloc = cmsDictAlloc
cmsDictFree = cmsDictFree
cmsDictDup = cmsDictDup
cmsDictAddEntry = cmsDictAddEntry
cmsDictGetEntryList = cmsDictGetEntryList
cmsDictNextEntry = cmsDictNextEntry
_cmsGetTransformUserData = _cmsGetTransformUserData
_cmsSetTransformUserData = _cmsSetTransformUserData
_cmsGetTransformFormatters16 = _cmsGetTransformFormatters16
_cmsGetTransformFormattersFloat = _cmsGetTransformFormattersFloat
cmsGetHeaderCreator = cmsGetHeaderCreator
cmsPluginTHR = cmsPluginTHR
cmsGetPipelineContextID = cmsGetPipelineContextID
cmsGetTransformInputFormat = cmsGetTransformInputFormat
cmsGetTransformOutputFormat = cmsGetTransformOutputFormat
cmsCreateContext = cmsCreateContext
cmsDupContext = cmsDupContext
cmsDeleteContext = cmsDeleteContext
cmsGetContextUserData = cmsGetContextUserData
cmsUnregisterPluginsTHR = cmsUnregisterPluginsTHR
cmsSetAlarmCodesTHR = cmsSetAlarmCodesTHR
cmsGetAlarmCodesTHR = cmsGetAlarmCodesTHR
cmsSetAdaptationStateTHR = cmsSetAdaptationStateTHR
cmsSetLogErrorHandlerTHR = cmsSetLogErrorHandlerTHR
cmsGetSupportedIntentsTHR = cmsGetSupportedIntentsTHR
cmsMLUtranslationsCount = cmsMLUtranslationsCount
cmsMLUtranslationsCodes = cmsMLUtranslationsCodes
_cmsCreateMutex = _cmsCreateMutex
_cmsDestroyMutex = _cmsDestroyMutex
_cmsLockMutex = _cmsLockMutex
_cmsUnlockMutex = _cmsUnlockMutex

View File

@ -1,7 +1,7 @@
//
// Little Color Management System
// Copyright (c) 1998-2014 Marti Maria Saguer
// Copyright (c) 1998-2016 Marti Maria Saguer
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
@ -57,7 +57,15 @@
#define _cmsALIGNLONG(x) (((x)+(sizeof(cmsUInt32Number)-1)) & ~(sizeof(cmsUInt32Number)-1))
// Alignment to memory pointer
#define _cmsALIGNMEM(x) (((x)+(sizeof(void *) - 1)) & ~(sizeof(void *) - 1))
// (Ultra)SPARC with gcc requires ptr alignment of 8 bytes
// even though sizeof(void *) is only four: for greatest flexibility
// allow the build to specify ptr alignment.
#ifndef CMS_PTR_ALIGNMENT
# define CMS_PTR_ALIGNMENT sizeof(void *)
#endif
#define _cmsALIGNMEM(x) (((x)+(CMS_PTR_ALIGNMENT - 1)) & ~(CMS_PTR_ALIGNMENT - 1))
// Maximum encodeable values in floating point
#define MAX_ENCODEABLE_XYZ (1.0 + 32767.0/32768.0)
@ -194,11 +202,17 @@ cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d)
// Microsoft felt that it was necessary to keep it set at -1 for an unlocked critical
// section, even when they changed the underlying algorithm to be more scalable.
// The final parts of the critical section object are unimportant, and can be set
// to zero for their defaults. This yields an initialization macro:
// to zero for their defaults. This yields to an initialization macro:
typedef CRITICAL_SECTION _cmsMutex;
#define CMS_MUTEX_INITIALIZER {(void*) -1,-1,0,0,0,0}
#define CMS_MUTEX_INITIALIZER {(PRTL_CRITICAL_SECTION_DEBUG) -1,-1,0,0,0,0}
#ifdef _MSC_VER
# if (_MSC_VER >= 1800)
# pragma warning(disable : 26135)
# endif
#endif
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{
@ -284,38 +298,38 @@ typedef int _cmsMutex;
cmsINLINE int _cmsLockPrimitive(_cmsMutex *m)
{
return 0;
cmsUNUSED_PARAMETER(m);
return 0;
}
cmsINLINE int _cmsUnlockPrimitive(_cmsMutex *m)
{
return 0;
cmsUNUSED_PARAMETER(m);
return 0;
}
cmsINLINE int _cmsInitMutexPrimitive(_cmsMutex *m)
{
return 0;
cmsUNUSED_PARAMETER(m);
return 0;
}
cmsINLINE int _cmsDestroyMutexPrimitive(_cmsMutex *m)
{
return 0;
cmsUNUSED_PARAMETER(m);
return 0;
}
cmsINLINE int _cmsEnterCriticalSectionPrimitive(_cmsMutex *m)
{
return 0;
cmsUNUSED_PARAMETER(m);
return 0;
}
cmsINLINE int _cmsLeaveCriticalSectionPrimitive(_cmsMutex *m)
{
return 0;
cmsUNUSED_PARAMETER(m);
return 0;
}
#endif
@ -656,8 +670,8 @@ struct _cms_MLU_struct {
cmsContext ContextID;
// The directory
int AllocatedEntries;
int UsedEntries;
cmsUInt32Number AllocatedEntries;
cmsUInt32Number UsedEntries;
_cmsMLUentry* Entries; // Array of pointers to strings allocated in MemPool
// The Pool
@ -823,6 +837,8 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID);
cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID);
cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID);
cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID);
cmsStage* _cmsStageClipNegatives(cmsContext ContextID, int nChannels);
// For curve set only
cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
@ -951,7 +967,7 @@ typedef struct _cmstransform_struct {
cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference
// Points to transform code
_cmsTransformFn xform;
_cmsTransform2Fn xform;
// Formatters, cannot be embedded into LUT because cache
cmsFormatter16 FromInput;
@ -997,9 +1013,20 @@ typedef struct _cmstransform_struct {
void* UserData;
_cmsFreeUserDataFn FreeUserData;
// A way to provide backwards compatibility with full xform plugins
_cmsTransformFn OldXform;
} _cmsTRANSFORM;
// --------------------------------------------------------------------------------------------------
// Copies extra channels from input to output if the original flags in the transform structure
// instructs to do so. This function is called on all standard transform functions.
void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
void* out,
cmsUInt32Number PixelsPerLine,
cmsUInt32Number LineCount,
const cmsStride* Stride);
// -----------------------------------------------------------------------------------------------------------------------
cmsHTRANSFORM _cmsChain2Lab(cmsContext ContextID,
cmsUInt32Number nProfiles,