cmsio0.c revision d904c1ec7e8d1d86ed56f0dd252435d12cd345ae
1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------- 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Little Color Management System 4d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Copyright (c) 1998-2016 Marti Maria Saguer 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission is hereby granted, free of charge, to any person obtaining 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of this software and associated documentation files (the "Software"), 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to deal in the Software without restriction, including without limitation 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the rights to use, copy, modify, merge, publish, distribute, sublicense, 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and/or sell copies of the Software, and to permit persons to whom the Software 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is furnished to do so, subject to the following conditions: 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The above copyright notice and this permission notice shall be included in 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// all copies or substantial portions of the Software. 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------- 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 26d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "lcms2_internal.h" 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Generic I/O, tag dictionary management, profile struct 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// IOhandlers are abstractions used by littleCMS to read from whatever file, stream, 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// memory block or any storage. Each IOhandler provides implementations for read, 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// write, seek and tell functions. LittleCMS code deals with IO across those objects. 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// In this way, is easier to add support for new storage media. 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NULL stream, for taking care of used space ------------------------------------- 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NULL IOhandler basically does nothing but keep track on how many bytes have been 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// written. This is handy when creating profiles, where the file size is needed in the 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// header. Then, whole profile is serialized across NULL IOhandler and a second pass 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// writes the bytes to the pertinent IOhandler. 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct { 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Pointer; // Points to current location 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} FILENULL; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number NULLRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count) 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILENULL* ResData = (FILENULL*) iohandler ->stream; 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number len = size * count; 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ResData -> Pointer += len; 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return count; 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUNUSED_PARAMETER(Buffer); 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool NULLSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILENULL* ResData = (FILENULL*) iohandler ->stream; 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ResData ->Pointer = offset; 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number NULLTell(cmsIOHANDLER* iohandler) 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILENULL* ResData = (FILENULL*) iohandler ->stream; 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ResData -> Pointer; 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool NULLWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void *Ptr) 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILENULL* ResData = (FILENULL*) iohandler ->stream; 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ResData ->Pointer += size; 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData ->Pointer > iohandler->UsedSpace) 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler->UsedSpace = ResData ->Pointer; 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUNUSED_PARAMETER(Ptr); 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool NULLClose(cmsIOHANDLER* iohandler) 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILENULL* ResData = (FILENULL*) iohandler ->stream; 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(iohandler ->ContextID, ResData); 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(iohandler ->ContextID, iohandler); 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The NULL IOhandler creator 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID) 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov struct _cms_io_handler* iohandler = NULL; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILENULL* fm = NULL; 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler = (struct _cms_io_handler*) _cmsMallocZero(ContextID, sizeof(struct _cms_io_handler)); 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (iohandler == NULL) return NULL; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm = (FILENULL*) _cmsMallocZero(ContextID, sizeof(FILENULL)); 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm == NULL) goto Error; 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Pointer = 0; 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->ContextID = ContextID; 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->stream = (void*) fm; 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->UsedSpace = 0; 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->ReportedSize = 0; 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->PhysicalFile[0] = 0; 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Read = NULLRead; 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Seek = NULLSeek; 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Close = NULLClose; 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Tell = NULLTell; 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Write = NULLWrite; 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return iohandler; 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (iohandler) _cmsFree(ContextID, iohandler); 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Memory-based stream -------------------------------------------------------------- 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Those functions implements an iohandler which takes a block of memory as storage medium. 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct { 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* Block; // Points to allocated memory 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Size; // Size of allocated memory 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Pointer; // Points to current location 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int FreeBlockOnClose; // As title 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} FILEMEM; 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number MemoryRead(struct _cms_io_handler* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count) 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILEMEM* ResData = (FILEMEM*) iohandler ->stream; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* Ptr; 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number len = size * count; 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData -> Pointer + len > ResData -> Size){ 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov len = (ResData -> Size - ResData -> Pointer); 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(iohandler ->ContextID, cmsERROR_READ, "Read from memory error. Got %d bytes, block should be of %d bytes", len, count * size); 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Ptr = ResData -> Block; 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Ptr += ResData -> Pointer; 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(Buffer, Ptr, len); 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ResData -> Pointer += len; 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return count; 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// SEEK_CUR is assumed 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool MemorySeek(struct _cms_io_handler* iohandler, cmsUInt32Number offset) 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILEMEM* ResData = (FILEMEM*) iohandler ->stream; 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (offset > ResData ->Size) { 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(iohandler ->ContextID, cmsERROR_SEEK, "Too few data; probably corrupted profile"); 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ResData ->Pointer = offset; 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Tell for memory 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number MemoryTell(struct _cms_io_handler* iohandler) 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILEMEM* ResData = (FILEMEM*) iohandler ->stream; 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData == NULL) return 0; 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ResData -> Pointer; 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Writes data to memory, also keeps used space for further reference. 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr) 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILEMEM* ResData = (FILEMEM*) iohandler ->stream; 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData == NULL) return FALSE; // Housekeeping 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Check for available space. Clip. 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData->Pointer + size > ResData->Size) { 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov size = ResData ->Size - ResData->Pointer; 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (size == 0) return TRUE; // Write zero bytes is ok, but does nothing 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(ResData ->Block + ResData ->Pointer, Ptr, size); 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ResData ->Pointer += size; 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData ->Pointer > iohandler->UsedSpace) 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler->UsedSpace = ResData ->Pointer; 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool MemoryClose(struct _cms_io_handler* iohandler) 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILEMEM* ResData = (FILEMEM*) iohandler ->stream; 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData ->FreeBlockOnClose) { 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ResData ->Block) _cmsFree(iohandler ->ContextID, ResData ->Block); 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(iohandler ->ContextID, ResData); 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(iohandler ->ContextID, iohandler); 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Create a iohandler for memory block. AccessMode=='r' assumes the iohandler is going to read, and makes 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of the memory block for letting user to free the memory after invoking open profile. In write 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// mode ("w"), Buffere points to the begin of memory block to be written. 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode) 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* iohandler = NULL; 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILEMEM* fm = NULL; 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(AccessMode != NULL); 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (iohandler == NULL) return NULL; 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (*AccessMode) { 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 'r': 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM)); 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm == NULL) goto Error; 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Buffer == NULL) { 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_READ, "Couldn't read profile from NULL pointer"); 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, size); 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm ->Block == NULL) { 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, fm); 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, iohandler); 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", size); 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(fm->Block, Buffer, size); 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->FreeBlockOnClose = TRUE; 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Size = size; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Pointer = 0; 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> ReportedSize = size; 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 'w': 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM)); 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm == NULL) goto Error; 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Block = (cmsUInt8Number*) Buffer; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->FreeBlockOnClose = FALSE; 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Size = size; 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm ->Pointer = 0; 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> ReportedSize = 0; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown access mode '%c'", *AccessMode); 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->ContextID = ContextID; 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->stream = (void*) fm; 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->UsedSpace = 0; 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->PhysicalFile[0] = 0; 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Read = MemoryRead; 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Seek = MemorySeek; 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Close = MemoryClose; 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Tell = MemoryTell; 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Write = MemoryWrite; 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return iohandler; 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm) _cmsFree(ContextID, fm); 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (iohandler) _cmsFree(ContextID, iohandler); 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// File-based stream ------------------------------------------------------- 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read count elements of size bytes each. Return number of elements read 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number FileRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count) 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number nReaded = (cmsUInt32Number) fread(Buffer, size, count, (FILE*) iohandler->stream); 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (nReaded != count) { 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(iohandler ->ContextID, cmsERROR_FILE, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size); 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return nReaded; 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 327d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Position file pointer in the file 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset) 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fseek((FILE*) iohandler ->stream, (long) offset, SEEK_SET) != 0) { 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(iohandler ->ContextID, cmsERROR_FILE, "Seek error; probably corrupted file"); 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Returns file pointer position 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number FileTell(cmsIOHANDLER* iohandler) 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (cmsUInt32Number) ftell((FILE*)iohandler ->stream); 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool FileWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void* Buffer) 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (size == 0) return TRUE; // We allow to write 0 bytes, but nothing is written 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler->UsedSpace += size; 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (fwrite(Buffer, size, 1, (FILE*) iohandler->stream) == 1); 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Closes the file 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool FileClose(cmsIOHANDLER* iohandler) 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fclose((FILE*) iohandler ->stream) != 0) return FALSE; 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(iohandler ->ContextID, iohandler); 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Create a iohandler for disk based files. 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode) 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* iohandler = NULL; 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FILE* fm = NULL; 371d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsInt32Number fileLen; 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(FileName != NULL); 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(AccessMode != NULL); 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (iohandler == NULL) return NULL; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch (*AccessMode) { 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 'r': 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm = fopen(FileName, "rb"); 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm == NULL) { 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, iohandler); 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName); 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 387d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 388d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann fileLen = cmsfilelength(fm); 389d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (fileLen < 0) 390d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann { 391d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann fclose(fm); 392d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann _cmsFree(ContextID, iohandler); 393d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsSignalError(ContextID, cmsERROR_FILE, "Cannot get size of file '%s'", FileName); 394d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return NULL; 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 396d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 397d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann iohandler -> ReportedSize = (cmsUInt32Number) fileLen; 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 'w': 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fm = fopen(FileName, "wb"); 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (fm == NULL) { 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, iohandler); 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_FILE, "Couldn't create '%s'", FileName); 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> ReportedSize = 0; 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(ContextID, iohandler); 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(ContextID, cmsERROR_FILE, "Unknown access mode '%c'", *AccessMode); 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->ContextID = ContextID; 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->stream = (void*) fm; 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->UsedSpace = 0; 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Keep track of the original file 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1); 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0; 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Read = FileRead; 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Seek = FileSeek; 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Close = FileClose; 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Tell = FileTell; 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Write = FileWrite; 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return iohandler; 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Create a iohandler for stream based files 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream) 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* iohandler = NULL; 437d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsInt32Number fileSize; 438d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 439d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann fileSize = cmsfilelength(Stream); 440d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (fileSize < 0) 441d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann { 442d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsSignalError(ContextID, cmsERROR_FILE, "Cannot get size of stream"); 443d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return NULL; 444d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER)); 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (iohandler == NULL) return NULL; 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> ContextID = ContextID; 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> stream = (void*) Stream; 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> UsedSpace = 0; 452d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann iohandler -> ReportedSize = (cmsUInt32Number) fileSize; 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler -> PhysicalFile[0] = 0; 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Read = FileRead; 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Seek = FileSeek; 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Close = FileClose; 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Tell = FileTell; 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov iohandler ->Write = FileWrite; 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return iohandler; 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Close an open IO handler 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io) 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return io -> Close(io); 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ------------------------------------------------------------------------------------------------------- 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 474d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmanncmsIOHANDLER* CMSEXPORT cmsGetProfileIOhandler(cmsHPROFILE hProfile) 475d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann{ 476d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann _cmsICCPROFILE* Icc = (_cmsICCPROFILE*)hProfile; 477d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 478d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (Icc == NULL) return NULL; 479d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return Icc->IOhandler; 480d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 481d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef _WIN32_WCE 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtime_t wceex_time(time_t *timer); 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstruct tm * wceex_gmtime(const time_t *timer); 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define time wceex_time 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define gmtime wceex_gmtime 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Creates an empty structure holding all required parameters 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID) 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov time_t now = time(NULL); 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) _cmsMallocZero(ContextID, sizeof(_cmsICCPROFILE)); 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc == NULL) return NULL; 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->ContextID = ContextID; 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Set it to empty 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagCount = 0; 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Set default version 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->Version = 0x02100000; 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Set creation date/time 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created)); 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Create a mutex if the user provided proper plugin. NULL otherwise 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->UsrMutex = _cmsCreateMutex(ContextID); 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Return the handle 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (cmsHPROFILE) Icc; 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsContext CMSEXPORT cmsGetProfileContextID(cmsHPROFILE hProfile) 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc == NULL) return NULL; 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> ContextID; 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Return the number of tags 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsInt32Number CMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile) 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc == NULL) return -1; 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc->TagCount; 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Return the tag signature of a given tag number 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagSignature CMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, cmsUInt32Number n) 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (n > Icc->TagCount) return (cmsTagSignature) 0; // Mark as not available 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (n >= MAX_TABLE_TAG) return (cmsTagSignature) 0; // As double check 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc ->TagNames[n]; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint SearchOneTag(_cmsICCPROFILE* Profile, cmsTagSignature sig) 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Profile -> TagCount; i++) { 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (sig == Profile -> TagNames[i]) 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return i; 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Search for a specific tag in tag dictionary. Returns position or -1 if tag not found. 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// If followlinks is turned on, then the position of the linked tag is returned 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks) 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int n; 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagSignature LinkedSig; 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do { 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for given tag in ICC profile directory 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = SearchOneTag(Icc, sig); 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (n < 0) 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return -1; // Not found 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!lFollowLinks) 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return n; // Found, don't follow links 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Is this a linked tag? 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LinkedSig = Icc ->TagLinked[n]; 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Yes, follow link 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (LinkedSig != (cmsTagSignature) 0) { 581d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // fix bug mantis id#0055942 582d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // assume that TRCTag and ColorantTag can't be linked. 583d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // Xiaochuan Liu 2014-04-23 584d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if ((sig == cmsSigRedTRCTag || sig == cmsSigGreenTRCTag || sig == cmsSigBlueTRCTag) && 585d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann (LinkedSig == cmsSigRedColorantTag || LinkedSig == cmsSigGreenColorantTag || LinkedSig == cmsSigBlueColorantTag)) 586d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann { 587d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return n; 588d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sig = LinkedSig; 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while (LinkedSig != (cmsTagSignature) 0); 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return n; 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Deletes a tag entry 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsDeleteTagByPos(_cmsICCPROFILE* Icc, int i) 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(Icc != NULL); 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(i >= 0); 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc -> TagPtrs[i] != NULL) { 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Free previous version 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->TagSaveAsRaw[i]) { 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i]; 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TypeHandler != NULL) { 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler LocalTypeHandler = *TypeHandler; 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameter 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ICCVersion = Icc ->Version; 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagPtrs[i] = NULL; 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Creates a new tag entry 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos) 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for the tag 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = _cmsSearchTag(Icc, sig, FALSE); 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i >= 0) { 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Already exists? delete it 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsDeleteTagByPos(Icc, i); 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *NewPos = i; 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // No, make a new one 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc -> TagCount >= MAX_TABLE_TAG) { 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG); 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *NewPos = Icc ->TagCount; 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagCount++; 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 660d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Check existence 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig) 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) (void*) hProfile; 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return _cmsSearchTag(Icc, sig, FALSE) >= 0; 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 668d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 669d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Enforces that the profile version is per. spec. 670d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Operates on the big endian bytes from the profile. 671d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Called before converting to platform endianness. 672d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Byte 0 is BCD major version, so max 9. 673d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Byte 1 is 2 BCD digits, one per nibble. 674d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Reserved bytes 2 & 3 must be 0. 675d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannstatic 676d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmanncmsUInt32Number _validatedVersion(cmsUInt32Number DWord) 677d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann{ 678d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord; 679d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsUInt8Number temp1; 680d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann cmsUInt8Number temp2; 681d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 682d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (*pByte > 0x09) *pByte = (cmsUInt8Number) 0x09; 683d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann temp1 = *(pByte+1) & 0xf0; 684d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann temp2 = *(pByte+1) & 0x0f; 685d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (temp1 > 0x90) temp1 = 0x90; 686d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (temp2 > 0x09) temp2 = 0x09; 687d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann *(pByte+1) = (cmsUInt8Number)(temp1 | temp2); 688d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann *(pByte+2) = (cmsUInt8Number)0; 689d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann *(pByte+3) = (cmsUInt8Number)0; 690d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 691d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return DWord; 692d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 693d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read profile header and validate it 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsReadHeader(_cmsICCPROFILE* Icc) 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagEntry Tag; 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsICCHeader Header; 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, j; 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number HeaderSize; 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io = Icc ->IOhandler; 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number TagCount; 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Read the header 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (io -> Read(io, &Header, sizeof(cmsICCHeader), 1) != 1) { 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Validate file as an ICC profile 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (_cmsAdjustEndianess32(Header.magic) != cmsMagicNumber) { 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_BAD_SIGNATURE, "not an ICC profile, invalid signature"); 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 716d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // Adjust endianness of the used parameters 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> DeviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass); 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> ColorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.colorSpace); 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> PCS = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Header.pcs); 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent); 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> flags = _cmsAdjustEndianess32(Header.flags); 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> manufacturer = _cmsAdjustEndianess32(Header.manufacturer); 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> model = _cmsAdjustEndianess32(Header.model); 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> creator = _cmsAdjustEndianess32(Header.creator); 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAdjustEndianess64(&Icc -> attributes, &Header.attributes); 728d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann Icc -> Version = _cmsAdjustEndianess32(_validatedVersion(Header.version)); 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get size as reported in header 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov HeaderSize = _cmsAdjustEndianess32(Header.size); 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Make sure HeaderSize is lower than profile size 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (HeaderSize >= Icc ->IOhandler ->ReportedSize) 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov HeaderSize = Icc ->IOhandler ->ReportedSize; 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get creation date/time 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsDecodeDateTimeNumber(&Header.date, &Icc ->Created); 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // The profile ID are 32 raw bytes 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(Icc ->ProfileID.ID32, Header.profileID.ID32, 16); 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Read tag directory 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadUInt32Number(io, &TagCount)) return FALSE; 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagCount > MAX_TABLE_TAG) { 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", TagCount); 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Read tag directory 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagCount = 0; 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < TagCount; i++) { 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadUInt32Number(io, (cmsUInt32Number *) &Tag.sig)) return FALSE; 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadUInt32Number(io, &Tag.offset)) return FALSE; 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadUInt32Number(io, &Tag.size)) return FALSE; 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Perform some sanity check. Offset + size should fall inside file. 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Tag.offset + Tag.size > HeaderSize || 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Tag.offset + Tag.size < Tag.offset) 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagNames[Icc ->TagCount] = Tag.sig; 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagOffsets[Icc ->TagCount] = Tag.offset; 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagSizes[Icc ->TagCount] = Tag.size; 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for links 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (j=0; j < Icc ->TagCount; j++) { 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ((Icc ->TagOffsets[j] == Tag.offset) && 7754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann (Icc ->TagSizes[j] == Tag.size) && 7764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann (Icc ->TagNames[j] == Tag.sig)) { 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagLinked[Icc ->TagCount] = Icc ->TagNames[j]; 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagCount++; 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Saves profile header 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace) 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsICCHeader Header; 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagEntry Tag; 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsInt32Number Count = 0; 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.size = _cmsAdjustEndianess32(UsedSpace); 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.cmmId = _cmsAdjustEndianess32(lcmsSignature); 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.version = _cmsAdjustEndianess32(Icc ->Version); 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.deviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Icc -> DeviceClass); 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.colorSpace = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Icc -> ColorSpace); 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.pcs = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Icc -> PCS); 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // NOTE: in v4 Timestamp must be in UTC rather than in local time 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsEncodeDateTimeNumber(&Header.date, &Icc ->Created); 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.magic = _cmsAdjustEndianess32(cmsMagicNumber); 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef CMS_IS_WINDOWS_ 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMicrosoft); 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.platform = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMacintosh); 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.flags = _cmsAdjustEndianess32(Icc -> flags); 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.manufacturer = _cmsAdjustEndianess32(Icc -> manufacturer); 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.model = _cmsAdjustEndianess32(Icc -> model); 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAdjustEndianess64(&Header.attributes, &Icc -> attributes); 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Rendering intent in the header (for embedded profiles) 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.renderingIntent = _cmsAdjustEndianess32(Icc -> RenderingIntent); 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Illuminant is always D50 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.illuminant.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->X)); 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.illuminant.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y)); 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.illuminant.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z)); 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Created by LittleCMS (that's me!) 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Header.creator = _cmsAdjustEndianess32(lcmsSignature); 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memset(&Header.reserved, 0, sizeof(Header.reserved)); 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 835d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // Set profile ID. Endianness is always big endian 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(&Header.profileID, &Icc ->ProfileID, 16); 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Dump the header 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!Icc -> IOhandler->Write(Icc->IOhandler, sizeof(cmsICCHeader), &Header)) return FALSE; 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Saves Tag directory 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get true count 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Icc -> TagCount; i++) { 845d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (Icc ->TagNames[i] != (cmsTagSignature) 0) 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Count++; 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Store number of tags 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsWriteUInt32Number(Icc ->IOhandler, Count)) return FALSE; 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Icc -> TagCount; i++) { 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 854d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; // It is just a placeholder 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Tag.sig = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]); 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]); 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Tag.size = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagSizes[i]); 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!Icc ->IOhandler -> Write(Icc-> IOhandler, sizeof(cmsTagEntry), &Tag)) return FALSE; 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ----------------------------------------------------------------------- Set/Get several struct members 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProfile) 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> RenderingIntent; 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetHeaderRenderingIntent(cmsHPROFILE hProfile, cmsUInt32Number RenderingIntent) 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> RenderingIntent = RenderingIntent; 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetHeaderFlags(cmsHPROFILE hProfile) 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (cmsUInt32Number) Icc -> flags; 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags) 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> flags = (cmsUInt32Number) Flags; 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile) 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc ->manufacturer; 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer) 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> manufacturer = manufacturer; 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetHeaderCreator(cmsHPROFILE hProfile) 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc ->creator; 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile) 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc ->model; 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model) 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> model = model; 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags) 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(Flags, &Icc -> attributes, sizeof(cmsUInt64Number)); 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags) 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(&Icc -> attributes, &Flags, sizeof(cmsUInt64Number)); 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsGetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID) 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(ProfileID, Icc ->ProfileID.ID8, 16); 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID) 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(&Icc -> ProfileID, ProfileID, 16); 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsGetHeaderCreationDateTime(cmsHPROFILE hProfile, struct tm *Dest) 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(Dest, &Icc ->Created, sizeof(struct tm)); 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsColorSpaceSignature CMSEXPORT cmsGetPCS(cmsHPROFILE hProfile) 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> PCS; 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, cmsColorSpaceSignature pcs) 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> PCS = pcs; 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsColorSpaceSignature CMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile) 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> ColorSpace; 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, cmsColorSpaceSignature sig) 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> ColorSpace = sig; 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsProfileClassSignature CMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile) 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> DeviceClass; 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, cmsProfileClassSignature sig) 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> DeviceClass = sig; 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsGetEncodedICCversion(cmsHPROFILE hProfile) 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> Version; 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetEncodedICCversion(cmsHPROFILE hProfile, cmsUInt32Number Version) 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> Version = Version; 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Get an hexadecimal number with same digits as v 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number BaseToBase(cmsUInt32Number in, int BaseIn, int BaseOut) 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char Buff[100]; 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i, len; 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number out; 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (len=0; in > 0 && len < 100; len++) { 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Buff[len] = (char) (in % BaseIn); 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov in /= BaseIn; 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=len-1, out=0; i >= 0; --i) { 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov out = out * BaseOut + Buff[i]; 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return out; 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Version) 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // 4.2 -> 0x4200000 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0 + 0.5), 10, 16) << 16; 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile) 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number n = Icc -> Version >> 16; 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return BaseToBase(n, 16, 10) / 100.0; 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// -------------------------------------------------------------------------------------------------------------- 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Create profile from IOhandler 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io) 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* NewIcc; 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hEmpty == NULL) return NULL; 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc = (_cmsICCPROFILE*) hEmpty; 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc ->IOhandler = io; 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadHeader(NewIcc)) goto Error; 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hEmpty); 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Create profile from IOhandler 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandler2THR(cmsContext ContextID, cmsIOHANDLER* io, cmsBool write) 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* NewIcc; 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hEmpty == NULL) return NULL; 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc = (_cmsICCPROFILE*) hEmpty; 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc ->IOhandler = io; 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (write) { 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc -> IsWrite = TRUE; 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadHeader(NewIcc)) goto Error; 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hEmpty); 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Create profile from disk file 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *lpFileName, const char *sAccess) 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* NewIcc; 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hEmpty == NULL) return NULL; 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc = (_cmsICCPROFILE*) hEmpty; 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc ->IOhandler = cmsOpenIOhandlerFromFile(ContextID, lpFileName, sAccess); 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (NewIcc ->IOhandler == NULL) goto Error; 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*sAccess == 'W' || *sAccess == 'w') { 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc -> IsWrite = TRUE; 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadHeader(NewIcc)) goto Error; 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hEmpty); 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess) 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsOpenProfileFromFileTHR(NULL, ICCProfile, sAccess); 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext ContextID, FILE* ICCProfile, const char *sAccess) 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* NewIcc; 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID); 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hEmpty == NULL) return NULL; 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc = (_cmsICCPROFILE*) hEmpty; 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc ->IOhandler = cmsOpenIOhandlerFromStream(ContextID, ICCProfile); 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (NewIcc ->IOhandler == NULL) goto Error; 1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (*sAccess == 'w') { 1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc -> IsWrite = TRUE; 1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadHeader(NewIcc)) goto Error; 1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hEmpty); 1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char *sAccess) 1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsOpenProfileFromStreamTHR(NULL, ICCProfile, sAccess); 1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Open from memory block 1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void* MemPtr, cmsUInt32Number dwSize) 1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* NewIcc; 1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsHPROFILE hEmpty; 1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hEmpty = cmsCreateProfilePlaceholder(ContextID); 1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (hEmpty == NULL) return NULL; 1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc = (_cmsICCPROFILE*) hEmpty; 1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Ok, in this case const void* is casted to void* just because open IO handler 1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // shares read and writting modes. Don't abuse this feature! 1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov NewIcc ->IOhandler = cmsOpenIOhandlerFromMem(ContextID, (void*) MemPtr, dwSize, "r"); 1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (NewIcc ->IOhandler == NULL) goto Error; 1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsReadHeader(NewIcc)) goto Error; 1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return hEmpty; 1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseProfile(hEmpty); 1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number dwSize) 1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize); 1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig 1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) 1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt8Number* Data; 1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Begin; 1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io = Icc ->IOhandler; 1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagDescriptor* TagDescriptor; 1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeSignature TypeBase; 1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeSignature Type; 1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler; 1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number Version = cmsGetProfileVersion((cmsHPROFILE) Icc); 1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler LocalTypeHandler; 1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Icc -> TagCount; i++) { 1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1204d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (Icc ->TagNames[i] == (cmsTagSignature) 0) continue; 1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Linked tags are not written 1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->TagLinked[i] != (cmsTagSignature) 0) continue; 1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagOffsets[i] = Begin = io ->UsedSpace; 1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Data = (cmsUInt8Number*) Icc -> TagPtrs[i]; 1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!Data) { 1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user. 1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // In this case a blind copy of the block data is performed 1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (FileOrig != NULL && Icc -> TagOffsets[i]) { 1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number TagSize = FileOrig -> TagSizes[i]; 1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i]; 1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* Mem; 1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!FileOrig ->IOhandler->Seek(FileOrig ->IOhandler, TagOffset)) return FALSE; 1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Mem = _cmsMalloc(Icc ->ContextID, TagSize); 1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Mem == NULL) return FALSE; 1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (FileOrig ->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE; 1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!io ->Write(io, TagSize, Mem)) return FALSE; 1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(Icc ->ContextID, Mem); 1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagSizes[i] = (io ->UsedSpace - Begin); 1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Align to 32 bit boundary. 1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (! _cmsWriteAlignment(io)) 1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Should this tag be saved as RAW? If so, tagsizes should be specified in advance (no further cooking is done) 1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->TagSaveAsRaw[i]) { 1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (io -> Write(io, Icc ->TagSizes[i], Data) != 1) return FALSE; 1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for support on this tag 1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, Icc -> TagNames[i]); 1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagDescriptor == NULL) continue; // Unsupported, ignore it 1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagDescriptor ->DecideType != NULL) { 1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Type = TagDescriptor ->DecideType(Version, Data); 1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Type = TagDescriptor ->SupportedTypes[0]; 1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type); 1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TypeHandler == NULL) { 1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]); 1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TypeBase = TypeHandler ->Signature; 1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsWriteTypeBase(io, TypeBase)) 1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler = *TypeHandler; 1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ContextID = Icc ->ContextID; 1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ICCVersion = Icc ->Version; 1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, io, Data, TagDescriptor ->ElemCount)) { 1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char String[5]; 1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(String, (cmsTagSignature) TypeBase); 1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_WRITE, "Couldn't write type '%s'", String); 1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagSizes[i] = (io ->UsedSpace - Begin); 1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Align to 32 bit boundary. 1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (! _cmsWriteAlignment(io)) 1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Fill the offset and size fields for all linked tags 1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool SetLinks( _cmsICCPROFILE* Icc) 1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Icc -> TagCount; i++) { 1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagSignature lnk = Icc ->TagLinked[i]; 1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (lnk != (cmsTagSignature) 0) { 1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int j = _cmsSearchTag(Icc, lnk, FALSE); 1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (j >= 0) { 1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagOffsets[i] = Icc ->TagOffsets[j]; 1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSizes[i] = Icc ->TagSizes[j]; 1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Low-level save to IOHANDLER. It returns the number of bytes used to 1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// store the profile, or zero on error. io may be NULL and in this case 1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// no data is written--only sizes are calculated 1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOHANDLER* io) 1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE Keep; 1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* PrevIO = NULL; 1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number UsedSpace; 1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsContext ContextID; 1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(hProfile != NULL); 1337d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 1338d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!_cmsLockMutex(Icc->ContextID, Icc->UsrMutex)) return 0; 1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(&Keep, Icc, sizeof(_cmsICCPROFILE)); 1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ContextID = cmsGetProfileContextID(hProfile); 1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PrevIO = Icc ->IOhandler = cmsOpenIOhandlerFromNULL(ContextID); 1343d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (PrevIO == NULL) { 1344d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); 1345d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return 0; 1346d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Pass #1 does compute offsets 1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsWriteHeader(Icc, 0)) goto Error; 1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!SaveTags(Icc, &Keep)) goto Error; 1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov UsedSpace = PrevIO ->UsedSpace; 1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Pass #2 does save to iohandler 1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (io != NULL) { 1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->IOhandler = io; 1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!SetLinks(Icc)) goto Error; 1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsWriteHeader(Icc, UsedSpace)) goto Error; 1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!SaveTags(Icc, &Keep)) goto Error; 1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); 1366d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!cmsCloseIOhandler(PrevIO)) 1367d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann UsedSpace = 0; // As a error marker 1368d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 1369d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); 1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return UsedSpace; 1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(PrevIO); 1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(Icc, &Keep, sizeof(_cmsICCPROFILE)); 1377d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann _cmsUnlockMutex(Icc->ContextID, Icc->UsrMutex); 1378d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef _WIN32_WCE 1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovint wceex_unlink(const char *filename); 1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef remove 1385d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann# define remove wceex_unlink 1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Low-level save to disk. 1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName) 1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsContext ContextID = cmsGetProfileContextID(hProfile); 1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io = cmsOpenIOhandlerFromFile(ContextID, FileName, "w"); 1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool rc; 1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (io == NULL) return FALSE; 1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0); 1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc &= cmsCloseIOhandler(io); 1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (rc == FALSE) { // remove() is C99 per 7.19.4.1 1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov remove(FileName); // We have to IGNORE return value in this case 1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Same as anterior, but for streams 1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsSaveProfileToStream(cmsHPROFILE hProfile, FILE* Stream) 1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool rc; 1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsContext ContextID = cmsGetProfileContextID(hProfile); 1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io = cmsOpenIOhandlerFromStream(ContextID, Stream); 1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (io == NULL) return FALSE; 1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0); 1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc &= cmsCloseIOhandler(io); 1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Same as anterior, but for memory blocks. In this case, a NULL as MemPtr means calculate needed space only 1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUInt32Number* BytesNeeded) 1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool rc; 1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io; 1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsContext ContextID = cmsGetProfileContextID(hProfile); 1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsAssert(BytesNeeded != NULL); 1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Should we just calculate the needed space? 1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (MemPtr == NULL) { 1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL); 1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (*BytesNeeded == 0) ? FALSE : TRUE; 1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // That is a real write operation 1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov io = cmsOpenIOhandlerFromMem(ContextID, MemPtr, *BytesNeeded, "w"); 1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (io == NULL) return FALSE; 1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0); 1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc &= cmsCloseIOhandler(io); 1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Closes a profile freeing any involved resources 1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile) 1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsBool rc = TRUE; 1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i; 1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!Icc) return FALSE; 1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Was open in write mode? 1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->IsWrite) { 1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->IsWrite = FALSE; // Assure no further writting 1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc &= cmsSaveProfileToFile(hProfile, Icc ->IOhandler->PhysicalFile); 1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < Icc -> TagCount; i++) { 1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc -> TagPtrs[i]) { 1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i]; 1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TypeHandler != NULL) { 1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler LocalTypeHandler = *TypeHandler; 1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ContextID = Icc ->ContextID; // As an additional parameters 1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ICCVersion = Icc ->Version; 1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.FreePtr(&LocalTypeHandler, Icc -> TagPtrs[i]); 1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]); 1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->IOhandler != NULL) { 1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc &= cmsCloseIOhandler(Icc->IOhandler); 1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsDestroyMutex(Icc->ContextID, Icc->UsrMutex); 1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsFree(Icc ->ContextID, Icc); // Free placeholder memory 1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ------------------------------------------------------------------------------------------------------------------- 1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Returns TRUE if a given tag is supported by a plug-in 1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic 1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool IsTypeSupported(cmsTagDescriptor* TagDescriptor, cmsTagTypeSignature Type) 1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number i, nMaxTypes; 1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nMaxTypes = TagDescriptor->nSupportedTypes; 1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (nMaxTypes >= MAX_TYPES_IN_LCMS_PLUGIN) 1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov nMaxTypes = MAX_TYPES_IN_LCMS_PLUGIN; 1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (i=0; i < nMaxTypes; i++) { 1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Type == TagDescriptor ->SupportedTypes[i]) return TRUE; 1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// That's the main read function 1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig) 1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* io = Icc ->IOhandler; 1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler; 1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler LocalTypeHandler; 1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagDescriptor* TagDescriptor; 1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeSignature BaseType; 1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Offset, TagSize; 1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number ElemCount; 1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int n; 1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return NULL; 1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = _cmsSearchTag(Icc, sig, TRUE); 1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (n < 0) goto Error; // Not found, return NULL 1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // If the element is already in memory, return the pointer 1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc -> TagPtrs[n]) { 1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 15404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (Icc->TagTypeHandlers[n] == NULL) goto Error; 15414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 15424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann // Sanity check 15434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann BaseType = Icc->TagTypeHandlers[n]->Signature; 15444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (BaseType == 0) goto Error; 15454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 15464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann TagDescriptor = _cmsGetTagDescriptor(Icc->ContextID, sig); 15474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (TagDescriptor == NULL) goto Error; 15484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 15494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; 15504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->TagSaveAsRaw[n]) goto Error; // We don't support read raw tags as cooked 1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> TagPtrs[n]; 1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // We need to read it. Get the offset and size to the file 1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Offset = Icc -> TagOffsets[n]; 1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagSize = Icc -> TagSizes[n]; 1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Seek to its location 1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!io -> Seek(io, Offset)) 1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for support on this tag 1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); 1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagDescriptor == NULL) { 1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char String[5]; 1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(String, sig); 1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // An unknown element was found. 1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown tag type '%s' found.", String); 1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; // Unsupported. 1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // if supported, get type and check if in list 1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov BaseType = _cmsReadTypeBase(io); 1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BaseType == 0) goto Error; 1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!IsTypeSupported(TagDescriptor, BaseType)) goto Error; 1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagSize -= 8; // Alredy read by the type base logic 1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get type handler 1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TypeHandler = _cmsGetTagTypeHandler(Icc ->ContextID, BaseType); 1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TypeHandler == NULL) goto Error; 1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler = *TypeHandler; 1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Read the tag 1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagTypeHandlers[n] = TypeHandler; 1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ContextID = Icc ->ContextID; 1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ICCVersion = Icc ->Version; 1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc -> TagPtrs[n] = LocalTypeHandler.ReadPtr(&LocalTypeHandler, io, &ElemCount, TagSize); 1598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1599d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // The tag type is supported, but something wrong happened and we cannot read the tag. 1600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // let know the user about this (although it is just a warning) 1601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc -> TagPtrs[n] == NULL) { 1602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char String[5]; 1604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(String, sig); 1606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String); 1607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // This is a weird error that may be a symptom of something more serious, the number of 1611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // stored item is actually less than the number of required elements. 1612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (ElemCount < TagDescriptor ->ElemCount) { 1613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char String[5]; 1615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(String, sig); 1617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d", 1618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov String, TagDescriptor ->ElemCount, ElemCount); 1619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Return the data 1623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> TagPtrs[n]; 1625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Return error and unlock tha data 1628ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return NULL; 1631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Get true type of data 1635ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig) 1636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler; 1639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int n; 1640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for given tag in ICC profile directory 1642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov n = _cmsSearchTag(Icc, sig, TRUE); 1643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (n < 0) return (cmsTagTypeSignature) 0; // Not found, return NULL 1644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get the handler. The true type is there 1646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TypeHandler = Icc -> TagTypeHandlers[n]; 1647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TypeHandler ->Signature; 1648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a single tag. This just keeps track of the tak into a list of "to be written". If the tag is already 1652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// in that list, the previous version is deleted. 1653ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data) 1654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler = NULL; 1657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler LocalTypeHandler; 1658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagDescriptor* TagDescriptor = NULL; 1659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeSignature Type; 1660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 1661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsFloat64Number Version; 1662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char TypeString[5], SigString[5]; 1663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE; 1665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // To delete tags. 1667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (data == NULL) { 1668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Delete the tag 1670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = _cmsSearchTag(Icc, sig, FALSE); 1671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i >= 0) { 1672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Use zero as a mark of deleted 1674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsDeleteTagByPos(Icc, i); 1675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagNames[i] = (cmsTagSignature) 0; 1676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Didn't find the tag 1680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsNewTag(Icc, sig, &i)) goto Error; 1684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // This is not raw 1686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSaveAsRaw[i] = FALSE; 1687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // This is not a link 1689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagLinked[i] = (cmsTagSignature) 0; 1690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get information about the TAG. 1692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); 1693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagDescriptor == NULL){ 1694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig); 1695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Now we need to know which type to use. It depends on the version. 1700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Version = cmsGetProfileVersion(hProfile); 1701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagDescriptor ->DecideType != NULL) { 1703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Let the tag descriptor to decide the type base on depending on 1705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // the data. This is useful for example on parametric curves, where 1706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // curves specified by a table cannot be saved as parametric and needs 1707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // to be casted to single v2-curves, even on v4 profiles. 1708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Type = TagDescriptor ->DecideType(Version, data); 1710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else { 1712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Type = TagDescriptor ->SupportedTypes[0]; 1714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Does the tag support this type? 1717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!IsTypeSupported(TagDescriptor, Type)) { 1718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); 1720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(SigString, sig); 1721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); 1723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Does we have a handler for this type? 1727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TypeHandler = _cmsGetTagTypeHandler(Icc->ContextID, Type); 1728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TypeHandler == NULL) { 1729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); 1731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(SigString, sig); 1732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%s' for tag '%s'", TypeString, SigString); 1734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; // Should never happen 1735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Fill fields on icc structure 1739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagTypeHandlers[i] = TypeHandler; 1740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagNames[i] = sig; 1741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSizes[i] = 0; 1742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagOffsets[i] = 0; 1743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler = *TypeHandler; 1745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ContextID = Icc ->ContextID; 1746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ICCVersion = Icc ->Version; 1747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagPtrs[i] = LocalTypeHandler.DupPtr(&LocalTypeHandler, data, TagDescriptor ->ElemCount); 1748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->TagPtrs[i] == NULL) { 1750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(TypeString, (cmsTagSignature) Type); 1752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsTagSignature2String(SigString, sig); 1753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%s' for tag '%s'", TypeString, SigString); 1754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1761ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read and write raw data. The only way those function would work and keep consistence with normal read and write 1768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is to do an additional step of serialization. That means, readRaw would issue a normal read and then convert the obtained 1769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// data to raw bytes by using the "write" serialization logic. And vice-versa. I know this may end in situations where 1770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// raw data written does not exactly correspond with the raw data proposed to cmsWriteRaw data, but this approach allows 1771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to write a tag as raw data and the read it as handled. 1772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1773ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize) 1774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void *Object; 1777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 1778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsIOHANDLER* MemIO; 1779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler* TypeHandler = NULL; 1780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagTypeHandler LocalTypeHandler; 1781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsTagDescriptor* TagDescriptor = NULL; 1782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number rc; 1783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number Offset, TagSize; 1784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; 1786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for given tag in ICC profile directory 1788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = _cmsSearchTag(Icc, sig, TRUE); 1789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i < 0) goto Error; // Not found, 1790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // It is already read? 1792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc -> TagPtrs[i] == NULL) { 1793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // No yet, get original position 1795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Offset = Icc ->TagOffsets[i]; 1796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagSize = Icc ->TagSizes[i]; 1797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // read the data directly, don't keep copy 1799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (data != NULL) { 1800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BufferSize < TagSize) 1802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagSize = BufferSize; 1803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) goto Error; 1805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) goto Error; 1806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TagSize; 1809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc ->TagSizes[i]; 1813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // The data has been already read, or written. But wait!, maybe the user choosed to save as 1816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // raw data. In this case, return the raw data directly 1817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Icc ->TagSaveAsRaw[i]) { 1818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (data != NULL) { 1820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagSize = Icc ->TagSizes[i]; 1822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (BufferSize < TagSize) 1823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagSize = BufferSize; 1824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov memmove(data, Icc ->TagPtrs[i], TagSize); 1826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TagSize; 1829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc ->TagSizes[i]; 1833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Already readed, or previously set by cmsWriteTag(). We need to serialize that 1836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // data to raw in order to maintain consistency. 1837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Object = cmsReadTag(hProfile, sig); 1840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; 1841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (Object == NULL) goto Error; 1843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Now we need to serialize to a memory block: just use a memory iohandler 1845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (data == NULL) { 1847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov MemIO = cmsOpenIOhandlerFromNULL(cmsGetProfileContextID(hProfile)); 1848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } else{ 1849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w"); 1850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (MemIO == NULL) goto Error; 1852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Obtain type handling for the tag 1854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TypeHandler = Icc ->TagTypeHandlers[i]; 1855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TagDescriptor = _cmsGetTagDescriptor(Icc-> ContextID, sig); 1856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TagDescriptor == NULL) { 1857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(MemIO); 1858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (TypeHandler == NULL) goto Error; 1862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Serialize 1864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler = *TypeHandler; 1865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ContextID = Icc ->ContextID; 1866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov LocalTypeHandler.ICCVersion = Icc ->Version; 1867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) { 1869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(MemIO); 1870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!LocalTypeHandler.WritePtr(&LocalTypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) { 1874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(MemIO); 1875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Error; 1876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Get Size and close 1879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rc = MemIO ->Tell(MemIO); 1880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsCloseIOhandler(MemIO); // Ignore return code this time 1881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return rc; 1884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1885ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError: 1886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Similar to the anterior. This function allows to write directly to the ICC profile any data, without 1891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading 1892d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// it as cooked without serializing does result into an error. If that is what you want, you will need to dump 1893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the profile to memry or disk and then reopen it. 1894ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size) 1895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 1898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return 0; 1900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsNewTag(Icc, sig, &i)) { 1902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Mark the tag as being written as RAW 1907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSaveAsRaw[i] = TRUE; 1908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagNames[i] = sig; 1909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagLinked[i] = (cmsTagSignature) 0; 1910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Keep a copy of the block 1912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagPtrs[i] = _cmsDupMem(Icc ->ContextID, data, Size); 1913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSizes[i] = Size; 1914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1916d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 1917d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (Icc->TagPtrs[i] == NULL) { 1918d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann Icc->TagNames[i] = (cmsTagSignature) 0; 1919d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return FALSE; 1920d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 1921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Using this function you can collapse several tag entries to the same block in the profile 1925ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest) 1926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 1929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsLockMutex(Icc->ContextID, Icc ->UsrMutex)) return FALSE; 1931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (!_cmsNewTag(Icc, sig, &i)) { 1933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FALSE; 1935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Keep necessary information 1938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSaveAsRaw[i] = FALSE; 1939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagNames[i] = sig; 1940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagLinked[i] = dest; 1941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagPtrs[i] = NULL; 1943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagSizes[i] = 0; 1944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Icc ->TagOffsets[i] = 0; 1945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsUnlockMutex(Icc->ContextID, Icc ->UsrMutex); 1947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return TRUE; 1948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Returns the tag linked to sig, in the case two tags are sharing same resource 1952ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagSignature CMSEXPORT cmsTagLinkedTo(cmsHPROFILE hProfile, cmsTagSignature sig) 1953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 1954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile; 1955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int i; 1956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Search for given tag in ICC profile directory 1958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov i = _cmsSearchTag(Icc, sig, FALSE); 1959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (i < 0) return (cmsTagSignature) 0; // Not found, return 0 1960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return Icc -> TagLinked[i]; 1962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} 1963