/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// This file is available under and governed by the GNU General Public
// License version 2 only, as published by the Free Software Foundation.
// However, the following notice accompanied the original version of this
// file:
//
//---------------------------------------------------------------------------------
//
// Little Color Management System
// 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,
// 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"
// Tag Serialization -----------------------------------------------------------------------------
// This file implements every single tag and tag type as described in the ICC spec. Some types
// have been deprecated, like ncl and Data. There is no implementation for those types as there
// are no profiles holding them. The programmer can also extend this list by defining his own types
// by using the appropiate plug-in. There are three types of plug ins regarding that. First type
// allows to define new tags using any existing type. Next plug-in type allows to define new types
// and the third one is very specific: allows to extend the number of elements in the multiprofile
// elements special type.
//--------------------------------------------------------------------------------------------------
// Some broken types
// This is the linked list that keeps track of the defined types
typedef struct _cmsTagTypeLinkedList_st {
// Some macros to define callbacks.
// Helper macro to define a handler. Callbacks do have a fixed naming convention.
// Helper macro to define a MPE handler. Callbacks do have a fixed naming convention
#define TYPE_MPE_HANDLER(t, x) { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 }
// Register a new type handler. This routine is shared between normal types and MPE
static
cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
{
// Calling the function with NULL as plug-in would unregister the plug in.
return TRUE;
}
// Note that since no memory is allocated, unregister does not
// reset this action.
return TRUE;
}
}
// Registering happens in plug-in memory pool
if (Anterior)
return TRUE;
}
// Return handler for a given type or NULL if not found. Shared between normal types and MPE
static
{
for (pt = LinkedList;
}
return NULL;
}
// Auxiliar to convert UTF-32 to UTF-16 in some cases
static
{
for (i=0; i < n; i++) {
}
return TRUE;
}
static
{
for (i=0; i < n; i++) {
}
else {
}
}
return TRUE;
}
// To deal with position tables
void* Cargo,
// Helper function to deal with position tables as decribed in ICC spec 4.3
// A table of n elements is readed, where first comes n records containing offsets and sizes and
// then a block containing the data itself. This allows to reuse same data in more than one entry
static
void *Cargo,
{
// Let's take the offsets to each element
for (i=0; i < Count; i++) {
ElementOffsets[i] += BaseOffset;
}
// Seek to each element and read it
for (i=0; i < Count; i++) {
// This is the reader callback
}
// Success
return TRUE;
return FALSE;
}
// Same as anterior, but for write position tables
static
void *Cargo,
{
// Create table
// Keep starting position of curve offsets
// Write a fake directory to be filled latter on
for (i=0; i < Count; i++) {
}
// Write each element. Keep track of the size as well.
for (i=0; i < Count; i++) {
// Callback to write...
// Now the size
}
// Write the directory
for (i=0; i < Count; i++) {
}
return TRUE;
return FALSE;
}
// ********************************************************************************
// Type XYZ. Only one value is allowed
// ********************************************************************************
//The XYZType contains an array of three encoded values for the XYZ tristimulus
//values. Tristimulus values must be non-negative. The signed encoding allows for
//implementation optimizations by minimizing the number of fixed formats.
static
void *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
return NULL;
}
*nItems = 1;
return (void*) xyz;
}
static
cmsBool Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
}
static
{
}
static
{
}
static
{
return cmsSigXYZType;
}
// ********************************************************************************
// Type chromaticity. Only one value is allowed
// ********************************************************************************
// The chromaticity tag type provides basic chromaticity data and type of
// phosphors or colorants of a monitor to applications and utilities.
static
void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
// Let's recover from a bug introduced in early versions of lcms1
}
*nItems = 1;
return (void*) chrm;
return NULL;
}
static
{
return TRUE;
}
static
cmsBool Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
return TRUE;
}
static
void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
}
static
{
}
// ********************************************************************************
// Type cmsSigColorantOrderType
// ********************************************************************************
// This is an optional tag which specifies the laydown order in which colorants will
// be printed on an n-colorant device. The laydown order may be the same as the
// channel generation order listed in the colorantTableTag or the channel order of a
// colour space such as CMYK, in which case this tag is not needed. When this is not
// the case (for example, ink-towers sometimes use the order KCMY), this tag may be
// used to specify the laydown order of the colorants.
static
void *Type_ColorantOrderType_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number));
// We use FF as end marker
return NULL;
}
*nItems = 1;
return (void*) ColorantOrder;
}
static
cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Get the length
for (Count=i=0; i < cmsMAXCHANNELS; i++) {
}
return TRUE;
}
static
void* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
}
static
{
}
// ********************************************************************************
// Type cmsSigS15Fixed16ArrayType
// ********************************************************************************
// This type represents an array of generic 4-byte/32-bit fixed point quantity.
// The number of values is determined from the size of the tag.
static
void *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
cmsUInt32Number i, n;
*nItems = 0;
n = SizeOfTag / sizeof(cmsUInt32Number);
for (i=0; i < n; i++) {
return NULL;
}
}
*nItems = n;
return (void*) array_double;
}
static
cmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
for (i=0; i < nItems; i++) {
}
return TRUE;
}
static
{
}
static
{
}
// ********************************************************************************
// Type cmsSigU16Fixed16ArrayType
// ********************************************************************************
// This type represents an array of generic 4-byte/32-bit quantity.
// The number of values is determined from the size of the tag.
static
void *Type_U16Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
cmsUInt32Number i, n;
*nItems = 0;
n = SizeOfTag / sizeof(cmsUInt32Number);
for (i=0; i < n; i++) {
if (!_cmsReadUInt32Number(io, &v)) {
return NULL;
}
// Convert to cmsFloat64Number
}
*nItems = n;
return (void*) array_double;
}
static
cmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
for (i=0; i < nItems; i++) {
}
return TRUE;
}
static
{
}
static
{
}
// ********************************************************************************
// Type cmsSigSignatureType
// ********************************************************************************
//
// The signatureType contains a four-byte sequence, Sequences of less than four
// characters are padded at the end with spaces, 20h.
// Typically this type is used for registered tags that can be displayed on many
// development systems as a sequence of four characters.
static
void *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 1;
return SigPtr;
}
static
cmsBool Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
}
static
{
}
static
{
}
// ********************************************************************************
// Type cmsSigTextType
// ********************************************************************************
//
// The textType is a simple text structure that contains a 7-bit ASCII text string.
// The length of the string is obtained by subtracting 8 from the element size portion
// of the tag itself. This string must be terminated with a 00h byte.
static
void *Type_Text_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
// Create a container
*nItems = 0;
// We need to store the "\0" at the end, so +1
// Make sure text is properly ended
*nItems = 1;
// Keep the result
return (void*) mlu;
return NULL;
}
// The conversion implies to choose a language. So, we choose the actual language.
static
cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
char* Text;
// Get the size of the string. Note there is an extra "\0" at the end
// Create memory
// Write it, including separator
return rc;
}
static
{
}
static
{
return;
}
static
{
if (ICCVersion >= 4.0)
return cmsSigMultiLocalizedUnicodeType;
return cmsSigTextType;
}
// ********************************************************************************
// Type cmsSigDataType
// ********************************************************************************
// General purpose data type
static
void *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
return NULL;
}
return NULL;
}
*nItems = 1;
return (void*) BinData;
}
static
cmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
}
static
{
}
static
{
}
// ********************************************************************************
// Type cmsSigTextDescriptionType
// ********************************************************************************
static
void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
// One dword should be there
// Read len of ASCII
SizeOfTag -= sizeof(cmsUInt32Number);
// Check for size
// All seems Ok, allocate the container
// As many memory as size of tag
// Read it
SizeOfTag -= AsciiCount;
// Make sure there is a terminator
Text[AsciiCount] = 0;
// Set the MLU entry. From here we can be tolerant to wrong types
// Skip Unicode code
for (i=0; i < UnicodeCount; i++) {
}
// Skip ScriptCode code if present. Some buggy profiles does have less
// data that stricttly required. We need to skip it as this type may come
// embedded in other types.
// Skip rest of tag
for (i=0; i < 67; i++) {
}
}
Done:
*nItems = 1;
return mlu;
return NULL;
}
// This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
static
cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Used below for writting zeroes
// Get the len of string
// From ICC3.4: 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
// Null strings
if (len <= 0) {
}
else {
// Create independent buffers
// Get both representations.
}
// * cmsUInt32Number count; * Description length
// * cmsInt8Number desc[count] * NULL terminated ascii string
// * cmsUInt32Number ucLangCode; * UniCode language code
// * cmsUInt32Number ucCount; * UniCode description length
// * cmsInt16Number ucDesc[ucCount];* The UniCode description
// * cmsUInt16Number scCode; * ScriptCode code
// * cmsUInt8Number scCount; * ScriptCode count
// * cmsInt8Number scDesc[67]; * ScriptCode Description
// 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
// Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
// ScriptCode Code & count (unused)
return rc;
}
static
void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
}
static
{
return;
}
static
{
if (ICCVersion >= 4.0)
return cmsSigMultiLocalizedUnicodeType;
return cmsSigTextDescriptionType;
}
// ********************************************************************************
// Type cmsSigCurveType
// ********************************************************************************
static
void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
switch (Count) {
case 0: // Linear.
*nItems = 1;
return NewGamma;
case 1: // Specified as the exponent of gamma function
{
*nItems = 1;
}
default: // Curve
if (Count > 0x7FFF)
return NULL; // This is to prevent bad guys for doing bad things
*nItems = 1;
return NewGamma;
}
}
static
cmsBool Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Single gamma, preserve number
return TRUE;
}
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigParametricCurveType
// ********************************************************************************
// Decide which curve type to use on writting
static
{
if (Curve ->nSegments != 1) return cmsSigCurveType; // Only 1-segment curves can be saved as parametric
return cmsSigParametricCurveType;
}
static
void *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
int i, n;
if (Type > 4) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown parametric curve type '%d'", Type);
return NULL;
}
n = ParamsByType[Type];
for (i=0; i < n; i++) {
}
*nItems = 1;
return NewGamma;
}
static
cmsBool Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Multisegment or Inverted parametric curves cannot be written");
return FALSE;
}
if (typen > 5) {
return FALSE;
}
for (i=0; i < nParams; i++) {
}
return TRUE;
}
static
void* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigDateTimeType
// ********************************************************************************
// A 12-byte value representation of the time and date, where the byte usage is assigned
// as specified in table 1. The actual values are encoded as 16-bit unsigned integers
// (uInt16Number - see 5.1.6).
//
// All the dateTimeNumber values in a profile shall be in Coordinated Universal Time
// (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local
// time to UTC when setting these values. Programmes that display these values may show
// the dateTimeNumber as UTC, show the equivalent local time (at current locale), or
// display both UTC and local versions of the dateTimeNumber.
static
void *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
*nItems = 1;
return NewDateTime;
}
static
cmsBool Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
return TRUE;
}
static
{
}
static
{
}
// ********************************************************************************
// Type icMeasurementType
// ********************************************************************************
/*
The measurementType information refers only to the internal profile data and is
meant to provide profile makers an alternative to the default measurement
specifications.
*/
static
void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 1;
}
static
cmsBool Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
return TRUE;
}
static
void* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
}
static
{
}
// ********************************************************************************
// Type cmsSigMultiLocalizedUnicodeType
// ********************************************************************************
//
// Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from
// Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be
// taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance)
//
static
void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
if (RecLen != 12) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "multiLocalizedUnicodeType of len != 12 is not supported.");
return NULL;
}
LargestPosition = 0;
for (i=0; i < Count; i++) {
// Now deal with Len and offset.
// Check for overflow
// True begin of the string
// Ajust to wchar_t elements
// To guess maximum size, add offset + len
if (EndOfThisString > LargestPosition)
}
// Now read the remaining of tag and fill all strings. Substract the directory
if (SizeOfTag == 0)
{
NumOfWchar = 0;
}
else
{
}
*nItems = 1;
return (void*) mlu;
return NULL;
}
static
cmsBool Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
int i;
// Empty placeholder
return TRUE;
}
for (i=0; i < mlu ->UsedEntries; i++) {
}
if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*) mlu ->MemPool)) return FALSE;
return TRUE;
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigLut8Type
// ********************************************************************************
// Decide which LUT type to use on writting
static
{
if (ICCVersion < 4.0) {
return cmsSigLut16Type;
}
else {
return cmsSigLutAtoBType;
}
}
static
{
if (ICCVersion < 4.0) {
return cmsSigLut16Type;
}
else {
return cmsSigLutBtoAType;
}
}
/*
This structure represents a colour transform using tables of 8-bit precision.
This type contains four processing elements: a 3 by 3 matrix (which shall be
the identity matrix unless the input colour space is XYZ), a set of one dimensional
input tables, a multidimensional lookup table, and a set of one dimensional output
tables. Data is processed using these elements via the following sequence:
(matrix) -> (1d input tables) -> (multidimensional lookup table - CLUT) -> (1d output tables)
Byte Position Field Length (bytes) Content Encoded as...
8 1 Number of Input Channels (i) uInt8Number
9 1 Number of Output Channels (o) uInt8Number
10 1 Number of CLUT grid points (identical for each side) (g) uInt8Number
11 1 Reserved for padding (fill with 00h)
12..15 4 Encoded e00 parameter s15Fixed16Number
*/
// Read 8 bit tables as gamma functions
static
{
int i, j;
for (i=0; i < nChannels; i++) {
}
for (i=0; i < nChannels; i++) {
for (j=0; j < 256; j++)
}
for (i=0; i < nChannels; i++)
cmsFreeToneCurve(Tables[i]);
return TRUE;
for (i=0; i < nChannels; i++) {
}
return FALSE;
}
static
cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number n, _cmsStageToneCurvesData* Tables)
{
int j;
for (i=0; i < n; i++) {
if (Tables) {
return FALSE;
}
}
for (j=0; j < 256; j++) {
else
val = (cmsUInt8Number) j;
}
}
return TRUE;
}
// Check overflow
static
{
if (a == 0) return 0;
if (n == 0) return 0;
for (; b > 0; b--) {
rv *= a;
// Check for overflow
}
return rc;
}
// That will create a MPE LUT with Matrix, pre tables, CLUT and post tables.
// 8 bit lut may be scaled easely to v4 PCS, but we need also to properly adjust
// PCS on BToAxx tags and AtoB if abstract. We need to fix input direction.
static
void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
// Padding
// Do some checking
// Allocates an empty Pipeline
// Read the Matrix
// Only operates if not identity...
}
// Get input tables
// Get 3D CLUT. Check the overflow....
if (nTabSize > 0) {
for (i = 0; i < nTabSize; i++) {
}
}
// Get output tables
*nItems = 1;
return NewLUT;
return NULL;
}
// We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
static
cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
int clutPoints;
// Disassemble the LUT into components.
}
}
}
}
// That should be all
cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
return FALSE;
}
clutPoints = 0;
else
}
else {
}
// The prelinearization table
if (nTabSize > 0) {
// The 3D CLUT.
for (j=0; j < nTabSize; j++) {
}
}
}
// The postlinearization table
return TRUE;
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigLut16Type
// ********************************************************************************
// Read 16 bit tables as gamma functions
static
cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
{
int i;
// Maybe an empty table? (this is a lcms extension)
// Check for malicious profiles
// Init table to zero
for (i=0; i < nChannels; i++) {
}
// Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
for (i=0; i < nChannels; i++)
cmsFreeToneCurve(Tables[i]);
return TRUE;
for (i=0; i < nChannels; i++) {
}
return FALSE;
}
static
{
int j;
for (j=0; j < nEntries; j++) {
else
}
}
return TRUE;
}
static
void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
// Padding
// Do some checking
// Allocates an empty LUT
// Read the Matrix
// Only operates on 3 channels
}
// Get input tables
// Get 3D CLUT
if (nTabSize > 0) {
cmsUInt16Number *T;
goto Error;
}
goto Error;
}
}
// Get output tables
*nItems = 1;
return NewLUT;
return NULL;
}
// We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
// Some empty defaults are created for missing parts
static
cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Disassemble the LUT into components.
}
}
}
}
// That should be all
cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
return FALSE;
}
clutPoints = 0;
else
}
else {
}
} else {
}
} else {
}
// The prelinearization table
}
if (nTabSize > 0) {
// The 3D CLUT.
}
}
// The postlinearization table
}
return TRUE;
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigLutAToBType
// ********************************************************************************
// V4 stuff. Read matrix for LutAtoB and LutBtoA
static
cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset)
{
// Go to address
// Read the Matrix
return Mat;
}
// V4 stuff. Read CLUT part for LutAtoB and LutBtoA
static
cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels)
{
for (i=0; i < cmsMAXCHANNELS; i++) {
GridPoints[i] = gridPoints8[i];
}
CLUT = cmsStageAllocCLut16bitGranular(self ->ContextID, GridPoints, InputChannels, OutputChannels, NULL);
// Precision can be 1 or 2 bytes
if (Precision == 1) {
}
}
else
if (Precision == 2) {
}
else {
cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
return NULL;
}
return CLUT;
}
static
{
switch (BaseType) {
case cmsSigCurveType:
default:
{
}
return NULL;
}
}
// Read a set of curves from specific offset
static
cmsStage* ReadSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, cmsUInt32Number nCurves)
{
for (i=0; i < nCurves; i++)
for (i=0; i < nCurves; i++) {
}
for (i=0; i < nCurves; i++)
cmsFreeToneCurve(Curves[i]);
return Lin;
}
// LutAtoB type
// This structure represents a colour transform. The type contains up to five processing
// elements which are stored in the AtoBTag tag in the following order: a set of one
// dimensional curves, a 3 by 3 matrix with offset terms, a set of one dimensional curves,
// a multidimensional lookup table, and a set of one dimensional output curves.
// Data are processed using these elements via the following sequence:
//
//("A" curves) -> (multidimensional lookup table - CLUT) -> ("M" curves) -> (matrix) -> ("B" curves).
//
/*
It is possible to use any or all of these processing elements. At least one processing element
must be included.Only the following combinations are allowed:
B
M - Matrix - B
A - CLUT - B
A - CLUT - M - Matrix - B
*/
static
void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
// Allocates an empty LUT
if (offsetA!= 0) {
}
if (offsetC != 0) {
}
if (offsetM != 0) {
}
if (offsetMat != 0) {
}
if (offsetB != 0) {
}
*nItems = 1;
return NewLUT;
}
// Write a set of curves
static
{
// Write the Matrix
}
else {
}
return TRUE;
}
// Write a set of curves
static
cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
{
cmsUInt32Number i, n;
n = cmsStageOutputChannels(mpe);
for (i=0; i < n; i++) {
// If this is a table-based curve, use curve type even on V4
CurrentType = Type;
else
switch (CurrentType) {
case cmsSigCurveType:
break;
break;
default:
{
}
return FALSE;
}
}
return TRUE;
}
static
cmsBool WriteCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt8Number Precision, cmsStage* mpe)
{
if (CLUT ->HasFloatValues) {
cmsSignalError(self ->ContextID, cmsERROR_NOT_SUITABLE, "Cannot save floating point data, CLUT are 8 or 16 bit only");
return FALSE;
}
// Precision can be 1 or 2 bytes
if (Precision == 1) {
}
}
else
if (Precision == 2) {
}
else {
cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
return FALSE;
}
return TRUE;
}
static
cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Get the base for all offsets
if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &M, &Matrix, &B))
if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &A, &CLUT, &B))
if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType,
cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutAToB");
return FALSE;
}
// Get input, output channels
// Write channel count
// Keep directory to be filled latter
// Write the directory
if (A != NULL) {
}
}
if (M != NULL) {
}
}
if (B != NULL) {
}
return TRUE;
}
static
{
}
static
{
return;
}
// LutBToA type
static
void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
// Padding
// Allocates an empty LUT
if (offsetB != 0) {
}
if (offsetMat != 0) {
}
if (offsetM != 0) {
}
if (offsetC != 0) {
}
if (offsetA!= 0) {
}
*nItems = 1;
return NewLUT;
}
/*
B
B - Matrix - M
B - CLUT - A
B - Matrix - M - CLUT - A
*/
static
cmsBool Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &B, &Matrix, &M))
if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &CLUT, &A))
if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutBToA");
return FALSE;
}
if (A != NULL) {
}
}
if (M != NULL) {
}
}
if (B != NULL) {
}
return TRUE;
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigColorantTableType
// ********************************************************************************
/*
The purpose of this tag is to identify the colorants used in the profile by a
unique name and set of XYZ or L*a*b* values to give the colorant an unambiguous
value. The first colorant listed is the colorant of the first device channel of
a lut tag. The second colorant listed is the colorant of the second device channel
of a lut tag, and so on.
*/
static
void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
if (Count > cmsMAXCHANNELS) {
return NULL;
}
for (i=0; i < Count; i++) {
Name[33] = 0;
}
*nItems = 1;
return List;
*nItems = 0;
return NULL;
}
// Saves a colorant table. It is using the named color structure for simplicity sake
static
cmsBool Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
int i, nColors;
for (i=0; i < nColors; i++) {
root[32] = 0;
}
return TRUE;
}
static
void* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
{
return (void*) cmsDupNamedColorList(nc);
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigNamedColor2Type
// ********************************************************************************
//
//The namedColor2Type is a count value and array of structures that provide color
//coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
//device representation of the color are given. Both representations are 16-bit values.
//The device representation corresponds to the header�s �color space of data� field.
//This representation should be consistent with the �number of device components�
//field in the namedColor2Type. If this field is 0, device coordinates are not provided.
//The PCS representation corresponds to the header�s PCS field. The PCS representation
//is always provided. Color names are fixed-length, 32-byte fields including null
//termination. In order to maintain maximum portability, it is strongly recommended
//that special characters of the 7-bit ASCII set not be used.
static
void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
if (v == NULL) {
return NULL;
}
if (nDeviceCoords > cmsMAXCHANNELS) {
return 0;
}
for (i=0; i < count; i++) {
}
*nItems = 1;
return (void*) v ;
return NULL;
}
// Saves a named color list into a named color profile
static
cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
int i, nColors;
for (i=0; i < nColors; i++) {
}
return TRUE;
}
static
{
return (void*) cmsDupNamedColorList(nc);
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigProfileSequenceDescType
// ********************************************************************************
// This type is an array of structures, each of which contains information from the
// header fields and tags from the original profiles which were combined to create
// the final profile. The order of the structures is the order in which the profiles
// were combined and includes a structure for the final profile. This provides a
// description of the profile sequence from source to destination,
// typically used with the DeviceLink profile.
static
cmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag)
{
switch (BaseType) {
case cmsSigTextType:
/*
TBD: Size is needed for MLU, and we have no idea on which is the available size
*/
default: return FALSE;
}
}
static
void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
SizeOfTag -= sizeof(cmsUInt32Number);
// Get structures as well
for (i=0; i < Count; i++) {
SizeOfTag -= sizeof(cmsUInt32Number);
SizeOfTag -= sizeof(cmsUInt32Number);
SizeOfTag -= sizeof(cmsUInt64Number);
SizeOfTag -= sizeof(cmsUInt32Number);
}
*nItems = 1;
return OutSeq;
return NULL;
}
// Aux--Embed a text description type. It can be of type text description or multilocalized unicode
// and it depends of the version number passed on cmsTagDescriptor structure instead of stack
static
{
}
else {
}
}
static
cmsBool Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
for (i=0; i < Seq ->n; i++) {
}
return TRUE;
}
static
void* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigProfileSequenceIdType
// ********************************************************************************
/*
In certain workflows using ICC Device Link Profiles, it is necessary to identify the
original profiles that were combined to create the Device Link Profile.
This type is an array of structures, each of which contains information for
identification of a profile used in a sequence
*/
static
void* Cargo,
{
return TRUE;
}
static
void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
// Get actual position as a basis for element offsets
// Get table count
SizeOfTag -= sizeof(cmsUInt32Number);
// Allocate an empty structure
// Read the position table
return NULL;
}
// Success
*nItems = 1;
return OutSeq;
}
static
void* Cargo,
{
// Store here the MLU
return TRUE;
}
static
cmsBool Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Keep the base offset
// This is the table count
// This is the position table and content
return TRUE;
}
static
void* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigUcrBgType
// ********************************************************************************
/*
This type contains curves representing the under color removal and black
generation and a text string which is a general description of the method used
*/
static
void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
char* ASCIIString;
*nItems = 0;
// First curve is Under color removal
SizeOfTag -= sizeof(cmsUInt32Number);
// Second curve is Black generation
SizeOfTag -= sizeof(cmsUInt32Number);
// Now comes the text. The length is specified by the tag size
ASCIIString[SizeOfTag] = 0;
*nItems = 1;
return (void*) n;
}
static
cmsBool Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
char* Text;
// First curve is Under color removal
// Then black generation
// Now comes the text. The length is specified by the tag size
if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;
return TRUE;
}
static
{
return (void*) NewUcrBg;
}
static
{
}
// ********************************************************************************
// Type cmsSigCrdInfoType
// ********************************************************************************
/*
This type contains the PostScript product name to which this profile corresponds
and the names of the companion CRDs. Recall that a single profile can generate
multiple CRDs. It is implemented as a MLU being the language code "PS" and then
country varies for each element:
nm: PostScript product name
#0: Rendering intent 0 CRD name
#1: Rendering intent 1 CRD name
#2: Rendering intent 2 CRD name
#3: Rendering intent 3 CRD name
*/
// Auxiliar, read an string specified as count + string
static
cmsBool ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
{
char* Text;
return FALSE;
}
return TRUE;
}
static
cmsBool WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section)
{
char* Text;
return TRUE;
}
static
void *Type_CrdInfo_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
*nItems = 1;
return (void*) mlu;
return NULL;
}
static
cmsBool Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
return TRUE;
return FALSE;
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigScreeningType
// ********************************************************************************
//
//The screeningType describes various screening parameters including screen
//frequency, screening angle, and spot shape.
static
void *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
}
*nItems = 1;
return (void*) sc;
return NULL;
}
static
cmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
}
return TRUE;
}
static
{
}
static
{
}
// ********************************************************************************
// Type cmsSigViewingConditionsType
// ********************************************************************************
//
//This type represents a set of viewing condition parameters including:
//CIE �absolute� illuminant white point tristimulus values and CIE �absolute�
//surround tristimulus values.
static
void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
*nItems = 1;
return (void*) vc;
return NULL;
}
static
cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
return TRUE;
}
static
void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
}
static
{
}
// ********************************************************************************
// Type cmsSigMultiProcessElementType
// ********************************************************************************
static
{
}
static
{
return;
}
// Each curve is stored in one or more curve segments, with break-points specified between curve segments.
// The first curve segment always starts at �Infinity, and the last curve segment always ends at +Infinity. The
// first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
// specified either in terms of a formula, or by a sampled curve.
// Read an embedded segmented curve
static
{
cmsUInt32Number i, j;
// Take signature and channels for each element.
// That should be a segmented curve
// Read breakpoints
}
// Read segments
for (i=0; i < nSegments; i++) {
switch (ElementSig) {
case cmsSigFormulaCurveSeg: {
for (j=0; j < ParamsByType[Type]; j++) {
}
}
break;
case cmsSigSampledCurveSeg: {
Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number));
for (j=0; j < Count; j++) {
}
}
break;
default:
{
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String);
}
return NULL;
}
}
for (i=0; i < nSegments; i++) {
}
return Curve;
return NULL;
}
static
void* Cargo,
{
return (GammaTables[n] != NULL);
}
static
void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
*nItems = 0;
// Get actual position as a basis for element offsets
}
else {
}
for (i=0; i < InputChans; i++) {
}
return mpe;
}
// Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY
static
{
cmsUInt32Number i, j;
// Write the break-points
for (i=0; i < nSegments - 1; i++) {
}
// Write the segments
for (i=0; i < g ->nSegments; i++) {
// This is a sampled curve
for (j=0; j < g ->Segments[i].nGridPoints; j++) {
}
}
else {
int Type;
// This is a formula-based
// We only allow 1, 2 and 3 as types
for (j=0; j < ParamsByType[Type]; j++) {
}
}
// It seems there is no need to align. Code is here, and for safety commented out
// if (!_cmsWriteAlignment(io)) goto Error;
}
return TRUE;
return FALSE;
}
static
void* Cargo,
{
}
// Write a curve, checking first for validity
static
cmsBool Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Write the header. Since those are curves, input and output channels are same
return TRUE;
}
// The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
// matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
// is organized as follows:
// array = [e11, e12, �, e1P, e21, e22, �, e2P, �, eQ1, eQ2, �, eQP, e1, e2, �, eQ]
static
void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
// Input and output chans may be ANY (up to 0xffff)
return NULL;
}
for (i=0; i < nElems; i++) {
Matrix[i] = v;
}
for (i=0; i < OutputChans; i++) {
Offsets[i] = v;
}
*nItems = 1;
return mpe;
}
static
cmsBool Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
for (i=0; i < nElems; i++) {
}
for (i=0; i < mpe ->OutputChannels; i++) {
}
else {
}
}
return TRUE;
}
static
void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
goto Error;
// Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
// Allocate the true CLUT
// Read the data
}
*nItems = 1;
return mpe;
*nItems = 0;
return NULL;
}
// Write a CLUT in floating point
static
cmsBool Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
// Check for maximum number of channels
// Only floats are supported in MPE
for (i=0; i < mpe ->InputChannels; i++)
}
return TRUE;
}
// This is the list of built-in MPE types
{{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[1] }, // Ignore those elements for now
{{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[2] }, // (That's what the spec says)
};
static
void* Cargo,
{
// Take signature and channels for each element.
// The reserved placeholder
// Read diverse MPE types
if (TypeHandler == NULL) {
// An unknown element was found.
cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String);
return FALSE;
}
// If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType)
// Read the MPE. No size is given
// This is a real element which should be read and processed
// All seems ok, insert element
}
return TRUE;
}
// This is the main dispatcher for MPE
static
void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
// Get actual position as a basis for element offsets
// Read channels and element count
// Allocates an empty LUT
*nItems = 0;
return NULL;
}
// Success
*nItems = 1;
return NewLUT;
}
// This one is a liitle bit more complex, so we don't use position tables this time.
static
cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
// Write the head
// Write a fake directory to be filled latter on
for (i=0; i < ElemCount; i++) {
}
// Write each single tag. Keep track of the size as well.
for (i=0; i < ElemCount; i++) {
if (TypeHandler == NULL) {
// An unknow element was found.
goto Error;
}
}
// Write the directory
for (i=0; i < ElemCount; i++) {
}
return TRUE;
return FALSE;
}
static
{
}
static
{
return;
}
// ********************************************************************************
// Type cmsSigVcgtType
// ********************************************************************************
#define cmsVideoCardGammaTableType 0
// Used internally
typedef struct {
double Gamma;
double Min;
double Max;
static
{
*nItems = 0;
// Read tag type
// Allocate space for the array
// There are two possible flavors
switch (TagType) {
// Gamma is stored as a table
{
// Check channel count, which should be 3 (we don't support monochrome this time)
if (nChannels != 3) {
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported number of channels for VCGT '%d'", nChannels);
goto Error;
}
// Get Table element count and bytes per element
// Adobe's quirk fixup. Fixing broken profiles...
nBytes = 2;
// Populate tone curves
for (n=0; n < 3; n++) {
// On depending on byte depth
switch (nBytes) {
// One byte, 0..255
case 1:
for (i=0; i < nElems; i++) {
}
break;
// One word 0..65535
case 2:
break;
// Unsupported
default:
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported bit depth for VCGT '%d'", nBytes * 8);
goto Error;
}
} // For all 3 channels
}
break;
// In this case, gamma is stored as a formula
{
// Populate tone curves
for (n=0; n < 3; n++) {
// Parametric curve type 5 is:
// Y = (aX + b)^Gamma + e | X >= d
// Y = cX + f | X < d
// vcgt formula is:
// Y = (Max � Min) * (X ^ Gamma) + Min
// So, the translation is
// a = (Max � Min) ^ ( 1 / Gamma)
// e = Min
// b=c=d=f=0
Params[2] = 0;
Params[3] = 0;
Params[4] = 0;
Params[6] = 0;
}
}
break;
// Unsupported
default:
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);
goto Error;
}
*nItems = 1;
return (void*) Curves;
// Regret, free all resources
return NULL;
}
// We don't support all flavors, only 16bits tables and formula
static
cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
cmsUInt32Number i, j;
// Save parameters
for (i=0; i < 3; i++) {
}
}
else {
// Always store as a table of 256 words
for (i=0; i < 3; i++) {
for (j=0; j < 256; j++) {
}
}
}
return TRUE;
}
static
{
return (void*) NewCurves;
}
static
{
}
// ********************************************************************************
// Type cmsSigDictType
// ********************************************************************************
// Single column of the table can point to wchar or MLUC elements. Holds arrays of data
typedef struct {
} _cmsDICelem;
typedef struct {
} _cmsDICarray;
// Allocate an empty array element
static
{
return FALSE;
}
return TRUE;
}
// Free an array element
static
{
}
// Get rid of whole array
static
{
}
// Allocate whole array
static
cmsBool AllocArray(cmsContext ContextID, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
{
// Empty values
memset(a, 0, sizeof(_cmsDICarray));
// On depending on record size, create column arrays
if (Length > 16) {
}
if (Length > 24) {
}
return TRUE;
FreeArray(a);
return FALSE;
}
// Read one element
static
cmsBool ReadOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsUInt32Number BaseOffset)
{
// An offset of zero has special meaning and shal be preserved
if (e ->Offsets[i] > 0)
e ->Offsets[i] += BaseOffset;
return TRUE;
}
static
cmsBool ReadOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset)
{
// Read column arrays
for (i=0; i < Count; i++) {
if (Length > 16) {
}
if (Length > 24) {
}
}
return TRUE;
}
// Write one element
static
{
return TRUE;
}
static
cmsBool WriteOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
{
for (i=0; i < Count; i++) {
if (Length > 16) {
}
if (Length > 24) {
}
}
return TRUE;
}
static
{
// Special case for undefined strings (see ICC Votable
// Proposal Submission, Dictionary Type and Metadata TAG Definition)
if (e -> Offsets[i] == 0) {
return TRUE;
}
return FALSE;
}
// End of string marker
return TRUE;
}
static
{
const wchar_t *p;
p = s;
while (*p)
p++;
return (cmsUInt32Number)(p - s);
}
static
cmsBool WriteOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const wchar_t * wcstr, cmsUInt32Number BaseOffset)
{
e ->Sizes[i] = 0;
e ->Offsets[i] = 0;
return TRUE;
}
return TRUE;
}
static
cmsBool ReadOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsMLU** mlu)
{
// A way to get null MLUCs
return TRUE;
}
}
static
cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset)
{
// Special case for undefined strings (see ICC Votable
// Proposal Submission, Dictionary Type and Metadata TAG Definition)
e ->Sizes[i] = 0;
e ->Offsets[i] = 0;
return TRUE;
}
return TRUE;
}
static
void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
_cmsDICarray a;
*nItems = 0;
// Get actual position as a basis for element offsets
// Get name-value record count
SizeOfTag -= sizeof(cmsUInt32Number);
// Get rec lenghth
SizeOfTag -= sizeof(cmsUInt32Number);
// Check for valid lengths
cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown record length in dictionary '%d'", Length);
return NULL;
}
// Creates an empty dictionary
// On depending on record size, create column arrays
// Read column arrays
// Seek to each element and read it
for (i=0; i < Count; i++) {
if (Length > 16) {
}
if (Length > 24) {
}
}
FreeArray(&a);
*nItems = 1;
return (void*) hDict;
FreeArray(&a);
return NULL;
}
static
cmsBool Type_Dictionary_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
const cmsDICTentry* p;
_cmsDICarray a;
// Let's inspect the dictionary
Count++;
}
Length = 16;
// Keep starting position of offsets table
// Allocate offsets array
// Write a fake directory to be filled latter on
// Write each element. Keep track of the size as well.
p = cmsDictGetEntryList(hDict);
for (i=0; i < Count; i++) {
if (p ->DisplayName != NULL) {
}
if (p ->DisplayValue != NULL) {
}
p = cmsDictNextEntry(p);
}
// Write the directory
FreeArray(&a);
return TRUE;
FreeArray(&a);
return FALSE;
}
static
{
}
static
{
}
// ********************************************************************************
// Type support main routines
// ********************************************************************************
// This is the list of built-in types
};
// Both kind of plug-ins share same structure
{
}
{
}
// Wrapper for tag types
{
}
// ********************************************************************************
// Tag support main routines
// ********************************************************************************
typedef struct _cmsTagLinkedList_st {
// This is the list of built-in tags
{ cmsSigAToB0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]},
{ cmsSigAToB1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[2]},
{ cmsSigAToB2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[3]},
{ cmsSigBToA0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[4]},
{ cmsSigBToA1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[5]},
{ cmsSigBToA2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[6]},
// Allow corbis and its broken XYZ type
{ cmsSigRedColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[7]},
{ cmsSigGreenColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[8]},
{ cmsSigBlueColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[9]},
{ cmsSigRedTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[10]},
{ cmsSigGreenTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[11]},
{ cmsSigBlueTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[12]},
{ cmsSigCopyrightTag, { 1, 3, { cmsSigTextType, cmsSigMultiLocalizedUnicodeType, cmsSigTextDescriptionType}, DecideTextType}, &SupportedTags[20]},
{ cmsSigDeviceMfgDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[22]},
{ cmsSigDeviceModelDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[23]},
{ cmsSigGamutTag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[24]},
{ cmsSigGrayTRCTag, { 1, 2, { cmsSigCurveType, cmsSigParametricCurveType }, DecideCurveType}, &SupportedTags[25]},
{ cmsSigMediaBlackPointTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[27]},
{ cmsSigMediaWhitePointTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[28]},
{ cmsSigPreview0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[30]},
{ cmsSigPreview1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[31]},
{ cmsSigPreview2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]},
{ cmsSigProfileDescriptionTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]},
{ cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]},
{ cmsSigColorimetricIntentImageStateTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[36]},
{ cmsSigPerceptualRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[37]},
{ cmsSigSaturationRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[38]},
{ cmsSigViewingCondDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[46]},
};
/*
Not supported Why
======================= =========================================
cmsSigOutputResponseTag ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
cmsSigNamedColorTag ==> Deprecated
cmsSigDataTag ==> Ancient, unused
cmsSigDeviceSettingsTag ==> Deprecated, useless
*/
{
return TRUE;
}
return TRUE;
}
}
return TRUE;
}
// Return a descriptor for a given tag or NULL
{
for (pt = SupportedTags;
}
return NULL;
}