File: | jdk/src/java.desktop/share/native/liblcms/cmstypes.c |
Warning: | line 5127, column 20 Array access (via field 'Offsets') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |||
3 | * | |||
4 | * This code is free software; you can redistribute it and/or modify it | |||
5 | * under the terms of the GNU General Public License version 2 only, as | |||
6 | * published by the Free Software Foundation. Oracle designates this | |||
7 | * particular file as subject to the "Classpath" exception as provided | |||
8 | * by Oracle in the LICENSE file that accompanied this code. | |||
9 | * | |||
10 | * This code is distributed in the hope that it will be useful, but WITHOUT | |||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
13 | * version 2 for more details (a copy is included in the LICENSE file that | |||
14 | * accompanied this code). | |||
15 | * | |||
16 | * You should have received a copy of the GNU General Public License version | |||
17 | * 2 along with this work; if not, write to the Free Software Foundation, | |||
18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |||
19 | * | |||
20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |||
21 | * or visit www.oracle.com if you need additional information or have any | |||
22 | * questions. | |||
23 | */ | |||
24 | ||||
25 | // This file is available under and governed by the GNU General Public | |||
26 | // License version 2 only, as published by the Free Software Foundation. | |||
27 | // However, the following notice accompanied the original version of this | |||
28 | // file: | |||
29 | // | |||
30 | //--------------------------------------------------------------------------------- | |||
31 | // | |||
32 | // Little Color Management System | |||
33 | // Copyright (c) 1998-2020 Marti Maria Saguer | |||
34 | // | |||
35 | // Permission is hereby granted, free of charge, to any person obtaining | |||
36 | // a copy of this software and associated documentation files (the "Software"), | |||
37 | // to deal in the Software without restriction, including without limitation | |||
38 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
39 | // and/or sell copies of the Software, and to permit persons to whom the Software | |||
40 | // is furnished to do so, subject to the following conditions: | |||
41 | // | |||
42 | // The above copyright notice and this permission notice shall be included in | |||
43 | // all copies or substantial portions of the Software. | |||
44 | // | |||
45 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
46 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | |||
47 | // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
48 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |||
49 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
50 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
51 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
52 | // | |||
53 | //--------------------------------------------------------------------------------- | |||
54 | // | |||
55 | ||||
56 | #include "lcms2_internal.h" | |||
57 | ||||
58 | // Tag Serialization ----------------------------------------------------------------------------- | |||
59 | // This file implements every single tag and tag type as described in the ICC spec. Some types | |||
60 | // have been deprecated, like ncl and Data. There is no implementation for those types as there | |||
61 | // are no profiles holding them. The programmer can also extend this list by defining his own types | |||
62 | // by using the appropriate plug-in. There are three types of plug ins regarding that. First type | |||
63 | // allows to define new tags using any existing type. Next plug-in type allows to define new types | |||
64 | // and the third one is very specific: allows to extend the number of elements in the multiprocessing | |||
65 | // elements special type. | |||
66 | //-------------------------------------------------------------------------------------------------- | |||
67 | ||||
68 | // Some broken types | |||
69 | #define cmsCorbisBrokenXYZtype((cmsTagTypeSignature) 0x17A505B8) ((cmsTagTypeSignature) 0x17A505B8) | |||
70 | #define cmsMonacoBrokenCurveType((cmsTagTypeSignature) 0x9478ee00) ((cmsTagTypeSignature) 0x9478ee00) | |||
71 | ||||
72 | // This is the linked list that keeps track of the defined types | |||
73 | typedef struct _cmsTagTypeLinkedList_st { | |||
74 | ||||
75 | cmsTagTypeHandler Handler; | |||
76 | struct _cmsTagTypeLinkedList_st* Next; | |||
77 | ||||
78 | } _cmsTagTypeLinkedList; | |||
79 | ||||
80 | // Some macros to define callbacks. | |||
81 | #define READ_FN(x)Type_x_Read Type_##x##_Read | |||
82 | #define WRITE_FN(x)Type_x_Write Type_##x##_Write | |||
83 | #define FREE_FN(x)Type_x_Free Type_##x##_Free | |||
84 | #define DUP_FN(x)Type_x_Dup Type_##x##_Dup | |||
85 | ||||
86 | // Helper macro to define a handler. Callbacks do have a fixed naming convention. | |||
87 | #define TYPE_HANDLER(t, x){ (t), Type_x_Read, Type_x_Write, Type_x_Dup, Type_x_Free, (( void*)0), 0 } { (t), READ_FN(x)Type_x_Read, WRITE_FN(x)Type_x_Write, DUP_FN(x)Type_x_Dup, FREE_FN(x)Type_x_Free, NULL((void*)0), 0 } | |||
88 | ||||
89 | // Helper macro to define a MPE handler. Callbacks do have a fixed naming convention | |||
90 | #define TYPE_MPE_HANDLER(t, x){ (t), Type_x_Read, Type_x_Write, GenericMPEdup, GenericMPEfree , ((void*)0), 0 } { (t), READ_FN(x)Type_x_Read, WRITE_FN(x)Type_x_Write, GenericMPEdup, GenericMPEfree, NULL((void*)0), 0 } | |||
91 | ||||
92 | // Infinites | |||
93 | #define MINUS_INF(-1E22F) (-1E22F) | |||
94 | #define PLUS_INF(+1E22F) (+1E22F) | |||
95 | ||||
96 | ||||
97 | // Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head | |||
98 | static | |||
99 | cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos) | |||
100 | { | |||
101 | cmsPluginTagType* Plugin = (cmsPluginTagType*) Data; | |||
102 | _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos); | |||
103 | _cmsTagTypeLinkedList *pt; | |||
104 | ||||
105 | // Calling the function with NULL as plug-in would unregister the plug in. | |||
106 | if (Data == NULL((void*)0)) { | |||
107 | ||||
108 | // There is no need to set free the memory, as pool is destroyed as a whole. | |||
109 | ctx ->TagTypes = NULL((void*)0); | |||
110 | return TRUE1; | |||
111 | } | |||
112 | ||||
113 | // Registering happens in plug-in memory pool. | |||
114 | pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList)); | |||
115 | if (pt == NULL((void*)0)) return FALSE0; | |||
116 | ||||
117 | pt ->Handler = Plugin ->Handler; | |||
118 | pt ->Next = ctx ->TagTypes; | |||
119 | ||||
120 | ctx ->TagTypes = pt; | |||
121 | ||||
122 | return TRUE1; | |||
123 | } | |||
124 | ||||
125 | // Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons | |||
126 | // made by plug-ins and then the built-in defaults. | |||
127 | static | |||
128 | cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList) | |||
129 | { | |||
130 | _cmsTagTypeLinkedList* pt; | |||
131 | ||||
132 | for (pt = PluginLinkedList; | |||
133 | pt != NULL((void*)0); | |||
134 | pt = pt ->Next) { | |||
135 | ||||
136 | if (sig == pt -> Handler.Signature) return &pt ->Handler; | |||
137 | } | |||
138 | ||||
139 | for (pt = DefaultLinkedList; | |||
140 | pt != NULL((void*)0); | |||
141 | pt = pt ->Next) { | |||
142 | ||||
143 | if (sig == pt -> Handler.Signature) return &pt ->Handler; | |||
144 | } | |||
145 | ||||
146 | return NULL((void*)0); | |||
147 | } | |||
148 | ||||
149 | ||||
150 | // Auxiliary to convert UTF-32 to UTF-16 in some cases | |||
151 | static | |||
152 | cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array) | |||
153 | { | |||
154 | cmsUInt32Number i; | |||
155 | ||||
156 | _cmsAssert(io != NULL)(((io != ((void*)0))) ? (void) (0) : __assert_fail ("(io != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmstypes.c" , 156, __extension__ __PRETTY_FUNCTION__)); | |||
157 | _cmsAssert(!(Array == NULL && n > 0))(((!(Array == ((void*)0) && n > 0))) ? (void) (0) : __assert_fail ("(!(Array == ((void*)0) && n > 0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmstypes.c" , 157, __extension__ __PRETTY_FUNCTION__)); | |||
158 | ||||
159 | for (i=0; i < n; i++) { | |||
160 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Array[i])) return FALSE0; | |||
161 | } | |||
162 | ||||
163 | return TRUE1; | |||
164 | } | |||
165 | ||||
166 | // Auxiliary to read an array of wchar_t | |||
167 | static | |||
168 | cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array) | |||
169 | { | |||
170 | cmsUInt32Number i; | |||
171 | cmsUInt16Number tmp; | |||
172 | ||||
173 | _cmsAssert(io != NULL)(((io != ((void*)0))) ? (void) (0) : __assert_fail ("(io != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmstypes.c" , 173, __extension__ __PRETTY_FUNCTION__)); | |||
174 | ||||
175 | for (i=0; i < n; i++) { | |||
176 | ||||
177 | if (Array != NULL((void*)0)) { | |||
178 | ||||
179 | if (!_cmsReadUInt16Number(io, &tmp)) return FALSE0; | |||
180 | Array[i] = (wchar_t) tmp; | |||
181 | } | |||
182 | else { | |||
183 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) return FALSE0; | |||
184 | } | |||
185 | ||||
186 | } | |||
187 | return TRUE1; | |||
188 | } | |||
189 | ||||
190 | // To deal with position tables | |||
191 | typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self, | |||
192 | cmsIOHANDLER* io, | |||
193 | void* Cargo, | |||
194 | cmsUInt32Number n, | |||
195 | cmsUInt32Number SizeOfTag); | |||
196 | ||||
197 | // Helper function to deal with position tables as described in ICC spec 4.3 | |||
198 | // A table of n elements is read, where first comes n records containing offsets and sizes and | |||
199 | // then a block containing the data itself. This allows to reuse same data in more than one entry | |||
200 | static | |||
201 | cmsBool ReadPositionTable(struct _cms_typehandler_struct* self, | |||
202 | cmsIOHANDLER* io, | |||
203 | cmsUInt32Number Count, | |||
204 | cmsUInt32Number BaseOffset, | |||
205 | void *Cargo, | |||
206 | PositionTableEntryFn ElementFn) | |||
207 | { | |||
208 | cmsUInt32Number i; | |||
209 | cmsUInt32Number *ElementOffsets = NULL((void*)0), *ElementSizes = NULL((void*)0); | |||
210 | cmsUInt32Number currentPosition; | |||
211 | ||||
212 | currentPosition = io->Tell(io); | |||
213 | ||||
214 | // Verify there is enough space left to read at least two cmsUInt32Number items for Count items. | |||
215 | if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count) | |||
216 | return FALSE0; | |||
217 | ||||
218 | // Let's take the offsets to each element | |||
219 | ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); | |||
220 | if (ElementOffsets == NULL((void*)0)) goto Error; | |||
221 | ||||
222 | ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); | |||
223 | if (ElementSizes == NULL((void*)0)) goto Error; | |||
224 | ||||
225 | for (i=0; i < Count; i++) { | |||
226 | ||||
227 | if (!_cmsReadUInt32Number(io, &ElementOffsets[i])) goto Error; | |||
228 | if (!_cmsReadUInt32Number(io, &ElementSizes[i])) goto Error; | |||
229 | ||||
230 | ElementOffsets[i] += BaseOffset; | |||
231 | } | |||
232 | ||||
233 | // Seek to each element and read it | |||
234 | for (i=0; i < Count; i++) { | |||
235 | ||||
236 | if (!io -> Seek(io, ElementOffsets[i])) goto Error; | |||
237 | ||||
238 | // This is the reader callback | |||
239 | if (!ElementFn(self, io, Cargo, i, ElementSizes[i])) goto Error; | |||
240 | } | |||
241 | ||||
242 | // Success | |||
243 | if (ElementOffsets != NULL((void*)0)) _cmsFree(io ->ContextID, ElementOffsets); | |||
244 | if (ElementSizes != NULL((void*)0)) _cmsFree(io ->ContextID, ElementSizes); | |||
245 | return TRUE1; | |||
246 | ||||
247 | Error: | |||
248 | if (ElementOffsets != NULL((void*)0)) _cmsFree(io ->ContextID, ElementOffsets); | |||
249 | if (ElementSizes != NULL((void*)0)) _cmsFree(io ->ContextID, ElementSizes); | |||
250 | return FALSE0; | |||
251 | } | |||
252 | ||||
253 | // Same as anterior, but for write position tables | |||
254 | static | |||
255 | cmsBool WritePositionTable(struct _cms_typehandler_struct* self, | |||
256 | cmsIOHANDLER* io, | |||
257 | cmsUInt32Number SizeOfTag, | |||
258 | cmsUInt32Number Count, | |||
259 | cmsUInt32Number BaseOffset, | |||
260 | void *Cargo, | |||
261 | PositionTableEntryFn ElementFn) | |||
262 | { | |||
263 | cmsUInt32Number i; | |||
264 | cmsUInt32Number DirectoryPos, CurrentPos, Before; | |||
265 | cmsUInt32Number *ElementOffsets = NULL((void*)0), *ElementSizes = NULL((void*)0); | |||
266 | ||||
267 | // Create table | |||
268 | ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); | |||
269 | if (ElementOffsets == NULL((void*)0)) goto Error; | |||
270 | ||||
271 | ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number)); | |||
272 | if (ElementSizes == NULL((void*)0)) goto Error; | |||
273 | ||||
274 | // Keep starting position of curve offsets | |||
275 | DirectoryPos = io ->Tell(io); | |||
276 | ||||
277 | // Write a fake directory to be filled latter on | |||
278 | for (i=0; i < Count; i++) { | |||
279 | ||||
280 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; // Offset | |||
281 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; // size | |||
282 | } | |||
283 | ||||
284 | // Write each element. Keep track of the size as well. | |||
285 | for (i=0; i < Count; i++) { | |||
286 | ||||
287 | Before = io ->Tell(io); | |||
288 | ElementOffsets[i] = Before - BaseOffset; | |||
289 | ||||
290 | // Callback to write... | |||
291 | if (!ElementFn(self, io, Cargo, i, SizeOfTag)) goto Error; | |||
292 | ||||
293 | // Now the size | |||
294 | ElementSizes[i] = io ->Tell(io) - Before; | |||
295 | } | |||
296 | ||||
297 | // Write the directory | |||
298 | CurrentPos = io ->Tell(io); | |||
299 | if (!io ->Seek(io, DirectoryPos)) goto Error; | |||
300 | ||||
301 | for (i=0; i < Count; i++) { | |||
302 | if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error; | |||
303 | if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error; | |||
304 | } | |||
305 | ||||
306 | if (!io ->Seek(io, CurrentPos)) goto Error; | |||
307 | ||||
308 | if (ElementOffsets != NULL((void*)0)) _cmsFree(io ->ContextID, ElementOffsets); | |||
309 | if (ElementSizes != NULL((void*)0)) _cmsFree(io ->ContextID, ElementSizes); | |||
310 | return TRUE1; | |||
311 | ||||
312 | Error: | |||
313 | if (ElementOffsets != NULL((void*)0)) _cmsFree(io ->ContextID, ElementOffsets); | |||
314 | if (ElementSizes != NULL((void*)0)) _cmsFree(io ->ContextID, ElementSizes); | |||
315 | return FALSE0; | |||
316 | } | |||
317 | ||||
318 | ||||
319 | // ******************************************************************************** | |||
320 | // Type XYZ. Only one value is allowed | |||
321 | // ******************************************************************************** | |||
322 | ||||
323 | //The XYZType contains an array of three encoded values for the XYZ tristimulus | |||
324 | //values. Tristimulus values must be non-negative. The signed encoding allows for | |||
325 | //implementation optimizations by minimizing the number of fixed formats. | |||
326 | ||||
327 | ||||
328 | static | |||
329 | void *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
330 | { | |||
331 | cmsCIEXYZ* xyz; | |||
332 | ||||
333 | *nItems = 0; | |||
334 | xyz = (cmsCIEXYZ*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIEXYZ)); | |||
335 | if (xyz == NULL((void*)0)) return NULL((void*)0); | |||
336 | ||||
337 | if (!_cmsReadXYZNumber(io, xyz)) { | |||
338 | _cmsFree(self ->ContextID, xyz); | |||
339 | return NULL((void*)0); | |||
340 | } | |||
341 | ||||
342 | *nItems = 1; | |||
343 | return (void*) xyz; | |||
344 | ||||
345 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
346 | } | |||
347 | ||||
348 | static | |||
349 | cmsBool Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
350 | { | |||
351 | return _cmsWriteXYZNumber(io, (cmsCIEXYZ*) Ptr); | |||
352 | ||||
353 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
354 | cmsUNUSED_PARAMETER(self)((void)self); | |||
355 | } | |||
356 | ||||
357 | static | |||
358 | void* Type_XYZ_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
359 | { | |||
360 | return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIEXYZ)); | |||
361 | ||||
362 | cmsUNUSED_PARAMETER(n)((void)n); | |||
363 | } | |||
364 | ||||
365 | static | |||
366 | void Type_XYZ_Free(struct _cms_typehandler_struct* self, void *Ptr) | |||
367 | { | |||
368 | _cmsFree(self ->ContextID, Ptr); | |||
369 | } | |||
370 | ||||
371 | ||||
372 | static | |||
373 | cmsTagTypeSignature DecideXYZtype(cmsFloat64Number ICCVersion, const void *Data) | |||
374 | { | |||
375 | return cmsSigXYZType; | |||
376 | ||||
377 | cmsUNUSED_PARAMETER(ICCVersion)((void)ICCVersion); | |||
378 | cmsUNUSED_PARAMETER(Data)((void)Data); | |||
379 | } | |||
380 | ||||
381 | ||||
382 | // ******************************************************************************** | |||
383 | // Type chromaticity. Only one value is allowed | |||
384 | // ******************************************************************************** | |||
385 | // The chromaticity tag type provides basic chromaticity data and type of | |||
386 | // phosphors or colorants of a monitor to applications and utilities. | |||
387 | ||||
388 | static | |||
389 | void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
390 | { | |||
391 | cmsCIExyYTRIPLE* chrm; | |||
392 | cmsUInt16Number nChans, Table; | |||
393 | ||||
394 | *nItems = 0; | |||
395 | chrm = (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE)); | |||
396 | if (chrm == NULL((void*)0)) return NULL((void*)0); | |||
397 | ||||
398 | if (!_cmsReadUInt16Number(io, &nChans)) goto Error; | |||
399 | ||||
400 | // Let's recover from a bug introduced in early versions of lcms1 | |||
401 | if (nChans == 0 && SizeOfTag == 32) { | |||
402 | ||||
403 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) goto Error; | |||
404 | if (!_cmsReadUInt16Number(io, &nChans)) goto Error; | |||
405 | } | |||
406 | ||||
407 | if (nChans != 3) goto Error; | |||
408 | ||||
409 | if (!_cmsReadUInt16Number(io, &Table)) goto Error; | |||
410 | ||||
411 | if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error; | |||
412 | if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error; | |||
413 | ||||
414 | chrm ->Red.Y = 1.0; | |||
415 | ||||
416 | if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error; | |||
417 | if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error; | |||
418 | ||||
419 | chrm ->Green.Y = 1.0; | |||
420 | ||||
421 | if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error; | |||
422 | if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error; | |||
423 | ||||
424 | chrm ->Blue.Y = 1.0; | |||
425 | ||||
426 | *nItems = 1; | |||
427 | return (void*) chrm; | |||
428 | ||||
429 | Error: | |||
430 | _cmsFree(self ->ContextID, (void*) chrm); | |||
431 | return NULL((void*)0); | |||
432 | ||||
433 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
434 | } | |||
435 | ||||
436 | static | |||
437 | cmsBool SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io) | |||
438 | { | |||
439 | if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) _cmsDoubleTo15Fixed16(x))) return FALSE0; | |||
440 | if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) _cmsDoubleTo15Fixed16(y))) return FALSE0; | |||
441 | ||||
442 | return TRUE1; | |||
443 | } | |||
444 | ||||
445 | static | |||
446 | cmsBool Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
447 | { | |||
448 | cmsCIExyYTRIPLE* chrm = (cmsCIExyYTRIPLE*) Ptr; | |||
449 | ||||
450 | if (!_cmsWriteUInt16Number(io, 3)) return FALSE0; // nChannels | |||
451 | if (!_cmsWriteUInt16Number(io, 0)) return FALSE0; // Table | |||
452 | ||||
453 | if (!SaveOneChromaticity(chrm -> Red.x, chrm -> Red.y, io)) return FALSE0; | |||
454 | if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, io)) return FALSE0; | |||
455 | if (!SaveOneChromaticity(chrm -> Blue.x, chrm -> Blue.y, io)) return FALSE0; | |||
456 | ||||
457 | return TRUE1; | |||
458 | ||||
459 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
460 | cmsUNUSED_PARAMETER(self)((void)self); | |||
461 | } | |||
462 | ||||
463 | static | |||
464 | void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
465 | { | |||
466 | return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE)); | |||
467 | ||||
468 | cmsUNUSED_PARAMETER(n)((void)n); | |||
469 | } | |||
470 | ||||
471 | static | |||
472 | void Type_Chromaticity_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
473 | { | |||
474 | _cmsFree(self ->ContextID, Ptr); | |||
475 | } | |||
476 | ||||
477 | ||||
478 | // ******************************************************************************** | |||
479 | // Type cmsSigColorantOrderType | |||
480 | // ******************************************************************************** | |||
481 | ||||
482 | // This is an optional tag which specifies the laydown order in which colorants will | |||
483 | // be printed on an n-colorant device. The laydown order may be the same as the | |||
484 | // channel generation order listed in the colorantTableTag or the channel order of a | |||
485 | // colour space such as CMYK, in which case this tag is not needed. When this is not | |||
486 | // the case (for example, ink-towers sometimes use the order KCMY), this tag may be | |||
487 | // used to specify the laydown order of the colorants. | |||
488 | ||||
489 | ||||
490 | static | |||
491 | void *Type_ColorantOrderType_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
492 | { | |||
493 | cmsUInt8Number* ColorantOrder; | |||
494 | cmsUInt32Number Count; | |||
495 | ||||
496 | *nItems = 0; | |||
497 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
498 | if (Count > cmsMAXCHANNELS16) return NULL((void*)0); | |||
499 | ||||
500 | ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS16, sizeof(cmsUInt8Number)); | |||
501 | if (ColorantOrder == NULL((void*)0)) return NULL((void*)0); | |||
502 | ||||
503 | // We use FF as end marker | |||
504 | memset(ColorantOrder, 0xFF, cmsMAXCHANNELS16 * sizeof(cmsUInt8Number)); | |||
505 | ||||
506 | if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) { | |||
507 | ||||
508 | _cmsFree(self ->ContextID, (void*) ColorantOrder); | |||
509 | return NULL((void*)0); | |||
510 | } | |||
511 | ||||
512 | *nItems = 1; | |||
513 | return (void*) ColorantOrder; | |||
514 | ||||
515 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
516 | } | |||
517 | ||||
518 | static | |||
519 | cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
520 | { | |||
521 | cmsUInt8Number* ColorantOrder = (cmsUInt8Number*) Ptr; | |||
522 | cmsUInt32Number i, sz, Count; | |||
523 | ||||
524 | // Get the length | |||
525 | for (Count=i=0; i < cmsMAXCHANNELS16; i++) { | |||
526 | if (ColorantOrder[i] != 0xFF) Count++; | |||
527 | } | |||
528 | ||||
529 | if (!_cmsWriteUInt32Number(io, Count)) return FALSE0; | |||
530 | ||||
531 | sz = Count * sizeof(cmsUInt8Number); | |||
532 | if (!io -> Write(io, sz, ColorantOrder)) return FALSE0; | |||
533 | ||||
534 | return TRUE1; | |||
535 | ||||
536 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
537 | cmsUNUSED_PARAMETER(self)((void)self); | |||
538 | } | |||
539 | ||||
540 | static | |||
541 | void* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
542 | { | |||
543 | return _cmsDupMem(self ->ContextID, Ptr, cmsMAXCHANNELS16 * sizeof(cmsUInt8Number)); | |||
544 | ||||
545 | cmsUNUSED_PARAMETER(n)((void)n); | |||
546 | } | |||
547 | ||||
548 | ||||
549 | static | |||
550 | void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
551 | { | |||
552 | _cmsFree(self ->ContextID, Ptr); | |||
553 | } | |||
554 | ||||
555 | // ******************************************************************************** | |||
556 | // Type cmsSigS15Fixed16ArrayType | |||
557 | // ******************************************************************************** | |||
558 | // This type represents an array of generic 4-byte/32-bit fixed point quantity. | |||
559 | // The number of values is determined from the size of the tag. | |||
560 | ||||
561 | static | |||
562 | void *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
563 | { | |||
564 | cmsFloat64Number* array_double; | |||
565 | cmsUInt32Number i, n; | |||
566 | ||||
567 | *nItems = 0; | |||
568 | n = SizeOfTag / sizeof(cmsUInt32Number); | |||
569 | array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number)); | |||
570 | if (array_double == NULL((void*)0)) return NULL((void*)0); | |||
571 | ||||
572 | for (i=0; i < n; i++) { | |||
573 | ||||
574 | if (!_cmsRead15Fixed16Number(io, &array_double[i])) { | |||
575 | ||||
576 | _cmsFree(self ->ContextID, array_double); | |||
577 | return NULL((void*)0); | |||
578 | } | |||
579 | } | |||
580 | ||||
581 | *nItems = n; | |||
582 | return (void*) array_double; | |||
583 | } | |||
584 | ||||
585 | static | |||
586 | cmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
587 | { | |||
588 | cmsFloat64Number* Value = (cmsFloat64Number*) Ptr; | |||
589 | cmsUInt32Number i; | |||
590 | ||||
591 | for (i=0; i < nItems; i++) { | |||
592 | ||||
593 | if (!_cmsWrite15Fixed16Number(io, Value[i])) return FALSE0; | |||
594 | } | |||
595 | ||||
596 | return TRUE1; | |||
597 | ||||
598 | cmsUNUSED_PARAMETER(self)((void)self); | |||
599 | } | |||
600 | ||||
601 | static | |||
602 | void* Type_S15Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
603 | { | |||
604 | return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number)); | |||
605 | } | |||
606 | ||||
607 | ||||
608 | static | |||
609 | void Type_S15Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
610 | { | |||
611 | _cmsFree(self ->ContextID, Ptr); | |||
612 | } | |||
613 | ||||
614 | // ******************************************************************************** | |||
615 | // Type cmsSigU16Fixed16ArrayType | |||
616 | // ******************************************************************************** | |||
617 | // This type represents an array of generic 4-byte/32-bit quantity. | |||
618 | // The number of values is determined from the size of the tag. | |||
619 | ||||
620 | ||||
621 | static | |||
622 | void *Type_U16Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
623 | { | |||
624 | cmsFloat64Number* array_double; | |||
625 | cmsUInt32Number v; | |||
626 | cmsUInt32Number i, n; | |||
627 | ||||
628 | *nItems = 0; | |||
629 | n = SizeOfTag / sizeof(cmsUInt32Number); | |||
630 | array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number)); | |||
631 | if (array_double == NULL((void*)0)) return NULL((void*)0); | |||
632 | ||||
633 | for (i=0; i < n; i++) { | |||
634 | ||||
635 | if (!_cmsReadUInt32Number(io, &v)) { | |||
636 | _cmsFree(self ->ContextID, (void*) array_double); | |||
637 | return NULL((void*)0); | |||
638 | } | |||
639 | ||||
640 | // Convert to cmsFloat64Number | |||
641 | array_double[i] = (cmsFloat64Number) (v / 65536.0); | |||
642 | } | |||
643 | ||||
644 | *nItems = n; | |||
645 | return (void*) array_double; | |||
646 | } | |||
647 | ||||
648 | static | |||
649 | cmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
650 | { | |||
651 | cmsFloat64Number* Value = (cmsFloat64Number*) Ptr; | |||
652 | cmsUInt32Number i; | |||
653 | ||||
654 | for (i=0; i < nItems; i++) { | |||
655 | ||||
656 | cmsUInt32Number v = (cmsUInt32Number) floor(Value[i]*65536.0 + 0.5); | |||
657 | ||||
658 | if (!_cmsWriteUInt32Number(io, v)) return FALSE0; | |||
659 | } | |||
660 | ||||
661 | return TRUE1; | |||
662 | ||||
663 | cmsUNUSED_PARAMETER(self)((void)self); | |||
664 | } | |||
665 | ||||
666 | ||||
667 | static | |||
668 | void* Type_U16Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
669 | { | |||
670 | return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number)); | |||
671 | } | |||
672 | ||||
673 | static | |||
674 | void Type_U16Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
675 | { | |||
676 | _cmsFree(self ->ContextID, Ptr); | |||
677 | } | |||
678 | ||||
679 | // ******************************************************************************** | |||
680 | // Type cmsSigSignatureType | |||
681 | // ******************************************************************************** | |||
682 | // | |||
683 | // The signatureType contains a four-byte sequence, Sequences of less than four | |||
684 | // characters are padded at the end with spaces, 20h. | |||
685 | // Typically this type is used for registered tags that can be displayed on many | |||
686 | // development systems as a sequence of four characters. | |||
687 | ||||
688 | static | |||
689 | void *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
690 | { | |||
691 | cmsSignature* SigPtr = (cmsSignature*) _cmsMalloc(self ->ContextID, sizeof(cmsSignature)); | |||
692 | if (SigPtr == NULL((void*)0)) return NULL((void*)0); | |||
693 | ||||
694 | if (!_cmsReadUInt32Number(io, SigPtr)) return NULL((void*)0); | |||
695 | *nItems = 1; | |||
696 | ||||
697 | return SigPtr; | |||
698 | ||||
699 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
700 | } | |||
701 | ||||
702 | static | |||
703 | cmsBool Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
704 | { | |||
705 | cmsSignature* SigPtr = (cmsSignature*) Ptr; | |||
706 | ||||
707 | return _cmsWriteUInt32Number(io, *SigPtr); | |||
708 | ||||
709 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
710 | cmsUNUSED_PARAMETER(self)((void)self); | |||
711 | } | |||
712 | ||||
713 | static | |||
714 | void* Type_Signature_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
715 | { | |||
716 | return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsSignature)); | |||
717 | } | |||
718 | ||||
719 | static | |||
720 | void Type_Signature_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
721 | { | |||
722 | _cmsFree(self ->ContextID, Ptr); | |||
723 | } | |||
724 | ||||
725 | ||||
726 | // ******************************************************************************** | |||
727 | // Type cmsSigTextType | |||
728 | // ******************************************************************************** | |||
729 | // | |||
730 | // The textType is a simple text structure that contains a 7-bit ASCII text string. | |||
731 | // The length of the string is obtained by subtracting 8 from the element size portion | |||
732 | // of the tag itself. This string must be terminated with a 00h byte. | |||
733 | ||||
734 | static | |||
735 | void *Type_Text_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
736 | { | |||
737 | char* Text = NULL((void*)0); | |||
738 | cmsMLU* mlu = NULL((void*)0); | |||
739 | ||||
740 | // Create a container | |||
741 | mlu = cmsMLUalloc(self ->ContextID, 1); | |||
742 | if (mlu == NULL((void*)0)) return NULL((void*)0); | |||
743 | ||||
744 | *nItems = 0; | |||
745 | ||||
746 | // We need to store the "\0" at the end, so +1 | |||
747 | if (SizeOfTag == UINT_MAX(2147483647 *2U +1U)) goto Error; | |||
748 | ||||
749 | Text = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1); | |||
750 | if (Text == NULL((void*)0)) goto Error; | |||
751 | ||||
752 | if (io -> Read(io, Text, sizeof(char), SizeOfTag) != SizeOfTag) goto Error; | |||
753 | ||||
754 | // Make sure text is properly ended | |||
755 | Text[SizeOfTag] = 0; | |||
756 | *nItems = 1; | |||
757 | ||||
758 | // Keep the result | |||
759 | if (!cmsMLUsetASCII(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", Text)) goto Error; | |||
760 | ||||
761 | _cmsFree(self ->ContextID, Text); | |||
762 | return (void*) mlu; | |||
763 | ||||
764 | Error: | |||
765 | if (mlu != NULL((void*)0)) | |||
766 | cmsMLUfree(mlu); | |||
767 | if (Text != NULL((void*)0)) | |||
768 | _cmsFree(self ->ContextID, Text); | |||
769 | ||||
770 | return NULL((void*)0); | |||
771 | } | |||
772 | ||||
773 | // The conversion implies to choose a language. So, we choose the actual language. | |||
774 | static | |||
775 | cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
776 | { | |||
777 | cmsMLU* mlu = (cmsMLU*) Ptr; | |||
778 | cmsUInt32Number size; | |||
779 | cmsBool rc; | |||
780 | char* Text; | |||
781 | ||||
782 | // Get the size of the string. Note there is an extra "\0" at the end | |||
783 | size = cmsMLUgetASCII(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", NULL((void*)0), 0); | |||
784 | if (size == 0) return FALSE0; // Cannot be zero! | |||
785 | ||||
786 | // Create memory | |||
787 | Text = (char*) _cmsMalloc(self ->ContextID, size); | |||
788 | if (Text == NULL((void*)0)) return FALSE0; | |||
789 | ||||
790 | cmsMLUgetASCII(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", Text, size); | |||
791 | ||||
792 | // Write it, including separator | |||
793 | rc = io ->Write(io, size, Text); | |||
794 | ||||
795 | _cmsFree(self ->ContextID, Text); | |||
796 | return rc; | |||
797 | ||||
798 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
799 | } | |||
800 | ||||
801 | static | |||
802 | void* Type_Text_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
803 | { | |||
804 | return (void*) cmsMLUdup((cmsMLU*) Ptr); | |||
805 | ||||
806 | cmsUNUSED_PARAMETER(n)((void)n); | |||
807 | cmsUNUSED_PARAMETER(self)((void)self); | |||
808 | } | |||
809 | ||||
810 | ||||
811 | static | |||
812 | void Type_Text_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
813 | { | |||
814 | cmsMLU* mlu = (cmsMLU*) Ptr; | |||
815 | cmsMLUfree(mlu); | |||
816 | return; | |||
817 | ||||
818 | cmsUNUSED_PARAMETER(self)((void)self); | |||
819 | } | |||
820 | ||||
821 | static | |||
822 | cmsTagTypeSignature DecideTextType(cmsFloat64Number ICCVersion, const void *Data) | |||
823 | { | |||
824 | if (ICCVersion >= 4.0) | |||
825 | return cmsSigMultiLocalizedUnicodeType; | |||
826 | ||||
827 | return cmsSigTextType; | |||
828 | ||||
829 | cmsUNUSED_PARAMETER(Data)((void)Data); | |||
830 | } | |||
831 | ||||
832 | ||||
833 | // ******************************************************************************** | |||
834 | // Type cmsSigDataType | |||
835 | // ******************************************************************************** | |||
836 | ||||
837 | // General purpose data type | |||
838 | static | |||
839 | void *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
840 | { | |||
841 | cmsICCData* BinData; | |||
842 | cmsUInt32Number LenOfData; | |||
843 | ||||
844 | *nItems = 0; | |||
845 | ||||
846 | if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL((void*)0); | |||
847 | ||||
848 | LenOfData = SizeOfTag - sizeof(cmsUInt32Number); | |||
849 | if (LenOfData > INT_MAX2147483647) return NULL((void*)0); | |||
850 | ||||
851 | BinData = (cmsICCData*) _cmsMalloc(self ->ContextID, sizeof(cmsICCData) + LenOfData - 1); | |||
852 | if (BinData == NULL((void*)0)) return NULL((void*)0); | |||
853 | ||||
854 | BinData ->len = LenOfData; | |||
855 | if (!_cmsReadUInt32Number(io, &BinData->flag)) { | |||
856 | _cmsFree(self ->ContextID, BinData); | |||
857 | return NULL((void*)0); | |||
858 | } | |||
859 | ||||
860 | if (io -> Read(io, BinData ->data, sizeof(cmsUInt8Number), LenOfData) != LenOfData) { | |||
861 | ||||
862 | _cmsFree(self ->ContextID, BinData); | |||
863 | return NULL((void*)0); | |||
864 | } | |||
865 | ||||
866 | *nItems = 1; | |||
867 | ||||
868 | return (void*) BinData; | |||
869 | } | |||
870 | ||||
871 | ||||
872 | static | |||
873 | cmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
874 | { | |||
875 | cmsICCData* BinData = (cmsICCData*) Ptr; | |||
876 | ||||
877 | if (!_cmsWriteUInt32Number(io, BinData ->flag)) return FALSE0; | |||
878 | ||||
879 | return io ->Write(io, BinData ->len, BinData ->data); | |||
880 | ||||
881 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
882 | cmsUNUSED_PARAMETER(self)((void)self); | |||
883 | } | |||
884 | ||||
885 | ||||
886 | static | |||
887 | void* Type_Data_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
888 | { | |||
889 | cmsICCData* BinData = (cmsICCData*) Ptr; | |||
890 | ||||
891 | return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1); | |||
892 | ||||
893 | cmsUNUSED_PARAMETER(n)((void)n); | |||
894 | } | |||
895 | ||||
896 | static | |||
897 | void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
898 | { | |||
899 | _cmsFree(self ->ContextID, Ptr); | |||
900 | } | |||
901 | ||||
902 | // ******************************************************************************** | |||
903 | // Type cmsSigTextDescriptionType | |||
904 | // ******************************************************************************** | |||
905 | ||||
906 | static | |||
907 | void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
908 | { | |||
909 | char* Text = NULL((void*)0); | |||
910 | cmsMLU* mlu = NULL((void*)0); | |||
911 | cmsUInt32Number AsciiCount; | |||
912 | cmsUInt32Number i, UnicodeCode, UnicodeCount; | |||
913 | cmsUInt16Number ScriptCodeCode, Dummy; | |||
914 | cmsUInt8Number ScriptCodeCount; | |||
915 | ||||
916 | *nItems = 0; | |||
917 | ||||
918 | // One dword should be there | |||
919 | if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL((void*)0); | |||
920 | ||||
921 | // Read len of ASCII | |||
922 | if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL((void*)0); | |||
923 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
924 | ||||
925 | // Check for size | |||
926 | if (SizeOfTag < AsciiCount) return NULL((void*)0); | |||
927 | ||||
928 | // All seems Ok, allocate the container | |||
929 | mlu = cmsMLUalloc(self ->ContextID, 1); | |||
930 | if (mlu == NULL((void*)0)) return NULL((void*)0); | |||
931 | ||||
932 | // As many memory as size of tag | |||
933 | Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1); | |||
934 | if (Text == NULL((void*)0)) goto Error; | |||
935 | ||||
936 | // Read it | |||
937 | if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error; | |||
938 | SizeOfTag -= AsciiCount; | |||
939 | ||||
940 | // Make sure there is a terminator | |||
941 | Text[AsciiCount] = 0; | |||
942 | ||||
943 | // Set the MLU entry. From here we can be tolerant to wrong types | |||
944 | if (!cmsMLUsetASCII(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", Text)) goto Error; | |||
945 | _cmsFree(self ->ContextID, (void*) Text); | |||
946 | Text = NULL((void*)0); | |||
947 | ||||
948 | // Skip Unicode code | |||
949 | if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done; | |||
950 | if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done; | |||
951 | if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done; | |||
952 | SizeOfTag -= 2* sizeof(cmsUInt32Number); | |||
953 | ||||
954 | if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done; | |||
955 | ||||
956 | for (i=0; i < UnicodeCount; i++) { | |||
957 | if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done; | |||
958 | } | |||
959 | SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number); | |||
960 | ||||
961 | // Skip ScriptCode code if present. Some buggy profiles does have less | |||
962 | // data that stricttly required. We need to skip it as this type may come | |||
963 | // embedded in other types. | |||
964 | ||||
965 | if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) { | |||
966 | ||||
967 | if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done; | |||
968 | if (!_cmsReadUInt8Number(io, &ScriptCodeCount)) goto Done; | |||
969 | ||||
970 | // Skip rest of tag | |||
971 | for (i=0; i < 67; i++) { | |||
972 | if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error; | |||
973 | } | |||
974 | } | |||
975 | ||||
976 | Done: | |||
977 | ||||
978 | *nItems = 1; | |||
979 | return mlu; | |||
980 | ||||
981 | Error: | |||
982 | if (Text) _cmsFree(self ->ContextID, (void*) Text); | |||
983 | if (mlu) cmsMLUfree(mlu); | |||
984 | return NULL((void*)0); | |||
985 | } | |||
986 | ||||
987 | ||||
988 | // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it | |||
989 | static | |||
990 | cmsBool Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
991 | { | |||
992 | cmsMLU* mlu = (cmsMLU*) Ptr; | |||
993 | char *Text = NULL((void*)0); | |||
994 | wchar_t *Wide = NULL((void*)0); | |||
995 | cmsUInt32Number len, len_text, len_tag_requirement, len_aligned; | |||
996 | cmsBool rc = FALSE0; | |||
997 | char Filler[68]; | |||
998 | ||||
999 | // Used below for writing zeroes | |||
1000 | memset(Filler, 0, sizeof(Filler)); | |||
1001 | ||||
1002 | // Get the len of string | |||
1003 | len = cmsMLUgetASCII(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", NULL((void*)0), 0); | |||
1004 | ||||
1005 | // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data | |||
1006 | //(see clause 4.1 for the definition of 'aligned'). Because the Unicode language | |||
1007 | // code and Unicode count immediately follow the ASCII description, their | |||
1008 | // alignment is not correct if the ASCII count is not a multiple of four. The | |||
1009 | // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and | |||
1010 | // writing software must be written carefully in order to handle these alignment | |||
1011 | // problems. | |||
1012 | // | |||
1013 | // The above last sentence suggest to handle alignment issues in the | |||
1014 | // parser. The provided example (Table 69 on Page 60) makes this clear. | |||
1015 | // The padding only in the ASCII count is not sufficient for a aligned tag | |||
1016 | // size, with the same text size in ASCII and Unicode. | |||
1017 | ||||
1018 | // Null strings | |||
1019 | if (len <= 0) { | |||
1020 | ||||
1021 | Text = (char*) _cmsDupMem(self ->ContextID, "", sizeof(char)); | |||
1022 | Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t)); | |||
1023 | } | |||
1024 | else { | |||
1025 | // Create independent buffers | |||
1026 | Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char)); | |||
1027 | if (Text == NULL((void*)0)) goto Error; | |||
1028 | ||||
1029 | Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t)); | |||
1030 | if (Wide == NULL((void*)0)) goto Error; | |||
1031 | ||||
1032 | // Get both representations. | |||
1033 | cmsMLUgetASCII(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", Text, len * sizeof(char)); | |||
1034 | cmsMLUgetWide(mlu, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", Wide, len * sizeof(wchar_t)); | |||
1035 | } | |||
1036 | ||||
1037 | // Tell the real text len including the null terminator and padding | |||
1038 | len_text = (cmsUInt32Number) strlen(Text) + 1; | |||
1039 | // Compute an total tag size requirement | |||
1040 | len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67); | |||
1041 | len_aligned = _cmsALIGNLONG(len_tag_requirement)(((len_tag_requirement)+(sizeof(cmsUInt32Number)-1)) & ~( sizeof(cmsUInt32Number)-1)); | |||
1042 | ||||
1043 | // * cmsUInt32Number count; * Description length | |||
1044 | // * cmsInt8Number desc[count] * NULL terminated ascii string | |||
1045 | // * cmsUInt32Number ucLangCode; * UniCode language code | |||
1046 | // * cmsUInt32Number ucCount; * UniCode description length | |||
1047 | // * cmsInt16Number ucDesc[ucCount];* The UniCode description | |||
1048 | // * cmsUInt16Number scCode; * ScriptCode code | |||
1049 | // * cmsUInt8Number scCount; * ScriptCode count | |||
1050 | // * cmsInt8Number scDesc[67]; * ScriptCode Description | |||
1051 | ||||
1052 | if (!_cmsWriteUInt32Number(io, len_text)) goto Error; | |||
1053 | if (!io ->Write(io, len_text, Text)) goto Error; | |||
1054 | ||||
1055 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; // ucLanguageCode | |||
1056 | ||||
1057 | if (!_cmsWriteUInt32Number(io, len_text)) goto Error; | |||
1058 | // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t) | |||
1059 | if (!_cmsWriteWCharArray(io, len_text, Wide)) goto Error; | |||
1060 | ||||
1061 | // ScriptCode Code & count (unused) | |||
1062 | if (!_cmsWriteUInt16Number(io, 0)) goto Error; | |||
1063 | if (!_cmsWriteUInt8Number(io, 0)) goto Error; | |||
1064 | ||||
1065 | if (!io ->Write(io, 67, Filler)) goto Error; | |||
1066 | ||||
1067 | // possibly add pad at the end of tag | |||
1068 | if(len_aligned - len_tag_requirement > 0) | |||
1069 | if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error; | |||
1070 | ||||
1071 | rc = TRUE1; | |||
1072 | ||||
1073 | Error: | |||
1074 | if (Text) _cmsFree(self ->ContextID, Text); | |||
1075 | if (Wide) _cmsFree(self ->ContextID, Wide); | |||
1076 | ||||
1077 | return rc; | |||
1078 | ||||
1079 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1080 | } | |||
1081 | ||||
1082 | ||||
1083 | static | |||
1084 | void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1085 | { | |||
1086 | return (void*) cmsMLUdup((cmsMLU*) Ptr); | |||
1087 | ||||
1088 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1089 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1090 | } | |||
1091 | ||||
1092 | static | |||
1093 | void Type_Text_Description_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1094 | { | |||
1095 | cmsMLU* mlu = (cmsMLU*) Ptr; | |||
1096 | ||||
1097 | cmsMLUfree(mlu); | |||
1098 | return; | |||
1099 | ||||
1100 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1101 | } | |||
1102 | ||||
1103 | ||||
1104 | static | |||
1105 | cmsTagTypeSignature DecideTextDescType(cmsFloat64Number ICCVersion, const void *Data) | |||
1106 | { | |||
1107 | if (ICCVersion >= 4.0) | |||
1108 | return cmsSigMultiLocalizedUnicodeType; | |||
1109 | ||||
1110 | return cmsSigTextDescriptionType; | |||
1111 | ||||
1112 | cmsUNUSED_PARAMETER(Data)((void)Data); | |||
1113 | } | |||
1114 | ||||
1115 | ||||
1116 | // ******************************************************************************** | |||
1117 | // Type cmsSigCurveType | |||
1118 | // ******************************************************************************** | |||
1119 | ||||
1120 | static | |||
1121 | void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
1122 | { | |||
1123 | cmsUInt32Number Count; | |||
1124 | cmsToneCurve* NewGamma; | |||
1125 | ||||
1126 | *nItems = 0; | |||
1127 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
1128 | ||||
1129 | switch (Count) { | |||
1130 | ||||
1131 | case 0: // Linear. | |||
1132 | { | |||
1133 | cmsFloat64Number SingleGamma = 1.0; | |||
1134 | ||||
1135 | NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma); | |||
1136 | if (!NewGamma) return NULL((void*)0); | |||
1137 | *nItems = 1; | |||
1138 | return NewGamma; | |||
1139 | } | |||
1140 | ||||
1141 | case 1: // Specified as the exponent of gamma function | |||
1142 | { | |||
1143 | cmsUInt16Number SingleGammaFixed; | |||
1144 | cmsFloat64Number SingleGamma; | |||
1145 | ||||
1146 | if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL((void*)0); | |||
1147 | SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed); | |||
1148 | ||||
1149 | *nItems = 1; | |||
1150 | return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma); | |||
1151 | } | |||
1152 | ||||
1153 | default: // Curve | |||
1154 | ||||
1155 | if (Count > 0x7FFF) | |||
1156 | return NULL((void*)0); // This is to prevent bad guys for doing bad things | |||
1157 | ||||
1158 | NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL((void*)0)); | |||
1159 | if (!NewGamma) return NULL((void*)0); | |||
1160 | ||||
1161 | if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) { | |||
1162 | cmsFreeToneCurve(NewGamma); | |||
1163 | return NULL((void*)0); | |||
1164 | } | |||
1165 | ||||
1166 | *nItems = 1; | |||
1167 | return NewGamma; | |||
1168 | } | |||
1169 | ||||
1170 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
1171 | } | |||
1172 | ||||
1173 | ||||
1174 | static | |||
1175 | cmsBool Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
1176 | { | |||
1177 | cmsToneCurve* Curve = (cmsToneCurve*) Ptr; | |||
1178 | ||||
1179 | if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) { | |||
1180 | ||||
1181 | // Single gamma, preserve number | |||
1182 | cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]); | |||
1183 | ||||
1184 | if (!_cmsWriteUInt32Number(io, 1)) return FALSE0; | |||
1185 | if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE0; | |||
1186 | return TRUE1; | |||
1187 | ||||
1188 | } | |||
1189 | ||||
1190 | if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE0; | |||
1191 | return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16); | |||
1192 | ||||
1193 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1194 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1195 | } | |||
1196 | ||||
1197 | ||||
1198 | static | |||
1199 | void* Type_Curve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1200 | { | |||
1201 | return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr); | |||
1202 | ||||
1203 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1204 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1205 | } | |||
1206 | ||||
1207 | static | |||
1208 | void Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1209 | { | |||
1210 | cmsToneCurve* gamma = (cmsToneCurve*) Ptr; | |||
1211 | ||||
1212 | cmsFreeToneCurve(gamma); | |||
1213 | return; | |||
1214 | ||||
1215 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1216 | } | |||
1217 | ||||
1218 | ||||
1219 | // ******************************************************************************** | |||
1220 | // Type cmsSigParametricCurveType | |||
1221 | // ******************************************************************************** | |||
1222 | ||||
1223 | ||||
1224 | // Decide which curve type to use on writing | |||
1225 | static | |||
1226 | cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data) | |||
1227 | { | |||
1228 | cmsToneCurve* Curve = (cmsToneCurve*) Data; | |||
1229 | ||||
1230 | if (ICCVersion < 4.0) return cmsSigCurveType; | |||
1231 | if (Curve ->nSegments != 1) return cmsSigCurveType; // Only 1-segment curves can be saved as parametric | |||
1232 | if (Curve ->Segments[0].Type < 0) return cmsSigCurveType; // Only non-inverted curves | |||
1233 | if (Curve ->Segments[0].Type > 5) return cmsSigCurveType; // Only ICC parametric curves | |||
1234 | ||||
1235 | return cmsSigParametricCurveType; | |||
1236 | } | |||
1237 | ||||
1238 | static | |||
1239 | void *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
1240 | { | |||
1241 | static const int ParamsByType[] = { 1, 3, 4, 5, 7 }; | |||
1242 | cmsFloat64Number Params[10]; | |||
1243 | cmsUInt16Number Type; | |||
1244 | int i, n; | |||
1245 | cmsToneCurve* NewGamma; | |||
1246 | ||||
1247 | if (!_cmsReadUInt16Number(io, &Type)) return NULL((void*)0); | |||
1248 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) return NULL((void*)0); // Reserved | |||
1249 | ||||
1250 | if (Type > 4) { | |||
1251 | ||||
1252 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown parametric curve type '%d'", Type); | |||
1253 | return NULL((void*)0); | |||
1254 | } | |||
1255 | ||||
1256 | memset(Params, 0, sizeof(Params)); | |||
1257 | n = ParamsByType[Type]; | |||
1258 | ||||
1259 | for (i=0; i < n; i++) { | |||
1260 | ||||
1261 | if (!_cmsRead15Fixed16Number(io, &Params[i])) return NULL((void*)0); | |||
1262 | } | |||
1263 | ||||
1264 | NewGamma = cmsBuildParametricToneCurve(self ->ContextID, Type+1, Params); | |||
1265 | ||||
1266 | *nItems = 1; | |||
1267 | return NewGamma; | |||
1268 | ||||
1269 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
1270 | } | |||
1271 | ||||
1272 | ||||
1273 | static | |||
1274 | cmsBool Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
1275 | { | |||
1276 | cmsToneCurve* Curve = (cmsToneCurve*) Ptr; | |||
1277 | int i, nParams, typen; | |||
1278 | static const int ParamsByType[] = { 0, 1, 3, 4, 5, 7 }; | |||
1279 | ||||
1280 | typen = Curve -> Segments[0].Type; | |||
1281 | ||||
1282 | if (Curve ->nSegments > 1 || typen < 1) { | |||
1283 | ||||
1284 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Multisegment or Inverted parametric curves cannot be written"); | |||
1285 | return FALSE0; | |||
1286 | } | |||
1287 | ||||
1288 | if (typen > 5) { | |||
1289 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unsupported parametric curve"); | |||
1290 | return FALSE0; | |||
1291 | } | |||
1292 | ||||
1293 | nParams = ParamsByType[typen]; | |||
1294 | ||||
1295 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) (Curve ->Segments[0].Type - 1))) return FALSE0; | |||
1296 | if (!_cmsWriteUInt16Number(io, 0)) return FALSE0; // Reserved | |||
1297 | ||||
1298 | for (i=0; i < nParams; i++) { | |||
1299 | ||||
1300 | if (!_cmsWrite15Fixed16Number(io, Curve -> Segments[0].Params[i])) return FALSE0; | |||
1301 | } | |||
1302 | ||||
1303 | return TRUE1; | |||
1304 | ||||
1305 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1306 | } | |||
1307 | ||||
1308 | static | |||
1309 | void* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1310 | { | |||
1311 | return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr); | |||
1312 | ||||
1313 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1314 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1315 | } | |||
1316 | ||||
1317 | static | |||
1318 | void Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1319 | { | |||
1320 | cmsToneCurve* gamma = (cmsToneCurve*) Ptr; | |||
1321 | ||||
1322 | cmsFreeToneCurve(gamma); | |||
1323 | return; | |||
1324 | ||||
1325 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1326 | } | |||
1327 | ||||
1328 | ||||
1329 | // ******************************************************************************** | |||
1330 | // Type cmsSigDateTimeType | |||
1331 | // ******************************************************************************** | |||
1332 | ||||
1333 | // A 12-byte value representation of the time and date, where the byte usage is assigned | |||
1334 | // as specified in table 1. The actual values are encoded as 16-bit unsigned integers | |||
1335 | // (uInt16Number - see 5.1.6). | |||
1336 | // | |||
1337 | // All the dateTimeNumber values in a profile shall be in Coordinated Universal Time | |||
1338 | // (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local | |||
1339 | // time to UTC when setting these values. Programmes that display these values may show | |||
1340 | // the dateTimeNumber as UTC, show the equivalent local time (at current locale), or | |||
1341 | // display both UTC and local versions of the dateTimeNumber. | |||
1342 | ||||
1343 | static | |||
1344 | void *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
1345 | { | |||
1346 | cmsDateTimeNumber timestamp; | |||
1347 | struct tm * NewDateTime; | |||
1348 | ||||
1349 | *nItems = 0; | |||
1350 | NewDateTime = (struct tm*) _cmsMalloc(self ->ContextID, sizeof(struct tm)); | |||
1351 | if (NewDateTime == NULL((void*)0)) return NULL((void*)0); | |||
1352 | ||||
1353 | if (io->Read(io, ×tamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL((void*)0); | |||
1354 | ||||
1355 | _cmsDecodeDateTimeNumber(×tamp, NewDateTime); | |||
1356 | ||||
1357 | *nItems = 1; | |||
1358 | return NewDateTime; | |||
1359 | ||||
1360 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
1361 | } | |||
1362 | ||||
1363 | ||||
1364 | static | |||
1365 | cmsBool Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
1366 | { | |||
1367 | struct tm * DateTime = (struct tm*) Ptr; | |||
1368 | cmsDateTimeNumber timestamp; | |||
1369 | ||||
1370 | _cmsEncodeDateTimeNumber(×tamp, DateTime); | |||
1371 | if (!io ->Write(io, sizeof(cmsDateTimeNumber), ×tamp)) return FALSE0; | |||
1372 | ||||
1373 | return TRUE1; | |||
1374 | ||||
1375 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1376 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1377 | } | |||
1378 | ||||
1379 | static | |||
1380 | void* Type_DateTime_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1381 | { | |||
1382 | return _cmsDupMem(self ->ContextID, Ptr, sizeof(struct tm)); | |||
1383 | ||||
1384 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1385 | } | |||
1386 | ||||
1387 | static | |||
1388 | void Type_DateTime_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1389 | { | |||
1390 | _cmsFree(self ->ContextID, Ptr); | |||
1391 | } | |||
1392 | ||||
1393 | ||||
1394 | ||||
1395 | // ******************************************************************************** | |||
1396 | // Type icMeasurementType | |||
1397 | // ******************************************************************************** | |||
1398 | ||||
1399 | /* | |||
1400 | The measurementType information refers only to the internal profile data and is | |||
1401 | meant to provide profile makers an alternative to the default measurement | |||
1402 | specifications. | |||
1403 | */ | |||
1404 | ||||
1405 | static | |||
1406 | void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
1407 | { | |||
1408 | cmsICCMeasurementConditions mc; | |||
1409 | ||||
1410 | ||||
1411 | memset(&mc, 0, sizeof(mc)); | |||
1412 | ||||
1413 | if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL((void*)0); | |||
1414 | if (!_cmsReadXYZNumber(io, &mc.Backing)) return NULL((void*)0); | |||
1415 | if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL((void*)0); | |||
1416 | if (!_cmsRead15Fixed16Number(io, &mc.Flare)) return NULL((void*)0); | |||
1417 | if (!_cmsReadUInt32Number(io, &mc.IlluminantType)) return NULL((void*)0); | |||
1418 | ||||
1419 | *nItems = 1; | |||
1420 | return _cmsDupMem(self ->ContextID, &mc, sizeof(cmsICCMeasurementConditions)); | |||
1421 | ||||
1422 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
1423 | } | |||
1424 | ||||
1425 | ||||
1426 | static | |||
1427 | cmsBool Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
1428 | { | |||
1429 | cmsICCMeasurementConditions* mc =(cmsICCMeasurementConditions*) Ptr; | |||
1430 | ||||
1431 | if (!_cmsWriteUInt32Number(io, mc->Observer)) return FALSE0; | |||
1432 | if (!_cmsWriteXYZNumber(io, &mc->Backing)) return FALSE0; | |||
1433 | if (!_cmsWriteUInt32Number(io, mc->Geometry)) return FALSE0; | |||
1434 | if (!_cmsWrite15Fixed16Number(io, mc->Flare)) return FALSE0; | |||
1435 | if (!_cmsWriteUInt32Number(io, mc->IlluminantType)) return FALSE0; | |||
1436 | ||||
1437 | return TRUE1; | |||
1438 | ||||
1439 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1440 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1441 | } | |||
1442 | ||||
1443 | static | |||
1444 | void* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1445 | { | |||
1446 | return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCMeasurementConditions)); | |||
1447 | ||||
1448 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1449 | } | |||
1450 | ||||
1451 | static | |||
1452 | void Type_Measurement_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1453 | { | |||
1454 | _cmsFree(self ->ContextID, Ptr); | |||
1455 | } | |||
1456 | ||||
1457 | ||||
1458 | // ******************************************************************************** | |||
1459 | // Type cmsSigMultiLocalizedUnicodeType | |||
1460 | // ******************************************************************************** | |||
1461 | // | |||
1462 | // Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from | |||
1463 | // Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be | |||
1464 | // taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance) | |||
1465 | // | |||
1466 | ||||
1467 | static | |||
1468 | void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
1469 | { | |||
1470 | cmsMLU* mlu; | |||
1471 | cmsUInt32Number Count, RecLen, NumOfWchar; | |||
1472 | cmsUInt32Number SizeOfHeader; | |||
1473 | cmsUInt32Number Len, Offset; | |||
1474 | cmsUInt32Number i; | |||
1475 | wchar_t* Block; | |||
1476 | cmsUInt32Number BeginOfThisString, EndOfThisString, LargestPosition; | |||
1477 | ||||
1478 | *nItems = 0; | |||
1479 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
1480 | if (!_cmsReadUInt32Number(io, &RecLen)) return NULL((void*)0); | |||
1481 | ||||
1482 | if (RecLen != 12) { | |||
1483 | ||||
1484 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "multiLocalizedUnicodeType of len != 12 is not supported."); | |||
1485 | return NULL((void*)0); | |||
1486 | } | |||
1487 | ||||
1488 | mlu = cmsMLUalloc(self ->ContextID, Count); | |||
1489 | if (mlu == NULL((void*)0)) return NULL((void*)0); | |||
1490 | ||||
1491 | mlu ->UsedEntries = Count; | |||
1492 | ||||
1493 | SizeOfHeader = 12 * Count + sizeof(_cmsTagBase); | |||
1494 | LargestPosition = 0; | |||
1495 | ||||
1496 | for (i=0; i < Count; i++) { | |||
1497 | ||||
1498 | if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error; | |||
1499 | if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country)) goto Error; | |||
1500 | ||||
1501 | // Now deal with Len and offset. | |||
1502 | if (!_cmsReadUInt32Number(io, &Len)) goto Error; | |||
1503 | if (!_cmsReadUInt32Number(io, &Offset)) goto Error; | |||
1504 | ||||
1505 | // Check for overflow | |||
1506 | if (Offset < (SizeOfHeader + 8)) goto Error; | |||
1507 | if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error; | |||
1508 | ||||
1509 | // True begin of the string | |||
1510 | BeginOfThisString = Offset - SizeOfHeader - 8; | |||
1511 | ||||
1512 | // Adjust to wchar_t elements | |||
1513 | mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number); | |||
1514 | mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number); | |||
1515 | ||||
1516 | // To guess maximum size, add offset + len | |||
1517 | EndOfThisString = BeginOfThisString + Len; | |||
1518 | if (EndOfThisString > LargestPosition) | |||
1519 | LargestPosition = EndOfThisString; | |||
1520 | } | |||
1521 | ||||
1522 | // Now read the remaining of tag and fill all strings. Subtract the directory | |||
1523 | SizeOfTag = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number); | |||
1524 | if (SizeOfTag == 0) | |||
1525 | { | |||
1526 | Block = NULL((void*)0); | |||
1527 | NumOfWchar = 0; | |||
1528 | ||||
1529 | } | |||
1530 | else | |||
1531 | { | |||
1532 | Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag); | |||
1533 | if (Block == NULL((void*)0)) goto Error; | |||
1534 | NumOfWchar = SizeOfTag / sizeof(wchar_t); | |||
1535 | if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error; | |||
1536 | } | |||
1537 | ||||
1538 | mlu ->MemPool = Block; | |||
1539 | mlu ->PoolSize = SizeOfTag; | |||
1540 | mlu ->PoolUsed = SizeOfTag; | |||
1541 | ||||
1542 | *nItems = 1; | |||
1543 | return (void*) mlu; | |||
1544 | ||||
1545 | Error: | |||
1546 | if (mlu) cmsMLUfree(mlu); | |||
1547 | return NULL((void*)0); | |||
1548 | } | |||
1549 | ||||
1550 | static | |||
1551 | cmsBool Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
1552 | { | |||
1553 | cmsMLU* mlu =(cmsMLU*) Ptr; | |||
1554 | cmsUInt32Number HeaderSize; | |||
1555 | cmsUInt32Number Len, Offset; | |||
1556 | cmsUInt32Number i; | |||
1557 | ||||
1558 | if (Ptr == NULL((void*)0)) { | |||
1559 | ||||
1560 | // Empty placeholder | |||
1561 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
1562 | if (!_cmsWriteUInt32Number(io, 12)) return FALSE0; | |||
1563 | return TRUE1; | |||
1564 | } | |||
1565 | ||||
1566 | if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE0; | |||
1567 | if (!_cmsWriteUInt32Number(io, 12)) return FALSE0; | |||
1568 | ||||
1569 | HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase); | |||
1570 | ||||
1571 | for (i=0; i < mlu ->UsedEntries; i++) { | |||
1572 | ||||
1573 | Len = mlu ->Entries[i].Len; | |||
1574 | Offset = mlu ->Entries[i].StrW; | |||
1575 | ||||
1576 | Len = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t); | |||
1577 | Offset = (Offset * sizeof(cmsUInt16Number)) / sizeof(wchar_t) + HeaderSize + 8; | |||
1578 | ||||
1579 | if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE0; | |||
1580 | if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country)) return FALSE0; | |||
1581 | if (!_cmsWriteUInt32Number(io, Len)) return FALSE0; | |||
1582 | if (!_cmsWriteUInt32Number(io, Offset)) return FALSE0; | |||
1583 | } | |||
1584 | ||||
1585 | if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*) mlu ->MemPool)) return FALSE0; | |||
1586 | ||||
1587 | return TRUE1; | |||
1588 | ||||
1589 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1590 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1591 | } | |||
1592 | ||||
1593 | ||||
1594 | static | |||
1595 | void* Type_MLU_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1596 | { | |||
1597 | return (void*) cmsMLUdup((cmsMLU*) Ptr); | |||
1598 | ||||
1599 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1600 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1601 | } | |||
1602 | ||||
1603 | static | |||
1604 | void Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1605 | { | |||
1606 | cmsMLUfree((cmsMLU*) Ptr); | |||
1607 | return; | |||
1608 | ||||
1609 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1610 | } | |||
1611 | ||||
1612 | ||||
1613 | // ******************************************************************************** | |||
1614 | // Type cmsSigLut8Type | |||
1615 | // ******************************************************************************** | |||
1616 | ||||
1617 | // Decide which LUT type to use on writing | |||
1618 | static | |||
1619 | cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data) | |||
1620 | { | |||
1621 | cmsPipeline* Lut = (cmsPipeline*) Data; | |||
1622 | ||||
1623 | if (ICCVersion < 4.0) { | |||
1624 | if (Lut ->SaveAs8Bits) return cmsSigLut8Type; | |||
1625 | return cmsSigLut16Type; | |||
1626 | } | |||
1627 | else { | |||
1628 | return cmsSigLutAtoBType; | |||
1629 | } | |||
1630 | } | |||
1631 | ||||
1632 | static | |||
1633 | cmsTagTypeSignature DecideLUTtypeB2A(cmsFloat64Number ICCVersion, const void *Data) | |||
1634 | { | |||
1635 | cmsPipeline* Lut = (cmsPipeline*) Data; | |||
1636 | ||||
1637 | if (ICCVersion < 4.0) { | |||
1638 | if (Lut ->SaveAs8Bits) return cmsSigLut8Type; | |||
1639 | return cmsSigLut16Type; | |||
1640 | } | |||
1641 | else { | |||
1642 | return cmsSigLutBtoAType; | |||
1643 | } | |||
1644 | } | |||
1645 | ||||
1646 | /* | |||
1647 | This structure represents a colour transform using tables of 8-bit precision. | |||
1648 | This type contains four processing elements: a 3 by 3 matrix (which shall be | |||
1649 | the identity matrix unless the input colour space is XYZ), a set of one dimensional | |||
1650 | input tables, a multidimensional lookup table, and a set of one dimensional output | |||
1651 | tables. Data is processed using these elements via the following sequence: | |||
1652 | (matrix) -> (1d input tables) -> (multidimensional lookup table - CLUT) -> (1d output tables) | |||
1653 | ||||
1654 | Byte Position Field Length (bytes) Content Encoded as... | |||
1655 | 8 1 Number of Input Channels (i) uInt8Number | |||
1656 | 9 1 Number of Output Channels (o) uInt8Number | |||
1657 | 10 1 Number of CLUT grid points (identical for each side) (g) uInt8Number | |||
1658 | 11 1 Reserved for padding (fill with 00h) | |||
1659 | ||||
1660 | 12..15 4 Encoded e00 parameter s15Fixed16Number | |||
1661 | */ | |||
1662 | ||||
1663 | ||||
1664 | // Read 8 bit tables as gamma functions | |||
1665 | static | |||
1666 | cmsBool Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, cmsUInt32Number nChannels) | |||
1667 | { | |||
1668 | cmsUInt8Number* Temp = NULL((void*)0); | |||
1669 | cmsUInt32Number i, j; | |||
1670 | cmsToneCurve* Tables[cmsMAXCHANNELS16]; | |||
1671 | ||||
1672 | if (nChannels > cmsMAXCHANNELS16) return FALSE0; | |||
1673 | if (nChannels <= 0) return FALSE0; | |||
1674 | ||||
1675 | memset(Tables, 0, sizeof(Tables)); | |||
1676 | ||||
1677 | Temp = (cmsUInt8Number*) _cmsMalloc(ContextID, 256); | |||
1678 | if (Temp == NULL((void*)0)) return FALSE0; | |||
1679 | ||||
1680 | for (i=0; i < nChannels; i++) { | |||
1681 | Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL((void*)0)); | |||
1682 | if (Tables[i] == NULL((void*)0)) goto Error; | |||
1683 | } | |||
1684 | ||||
1685 | for (i=0; i < nChannels; i++) { | |||
1686 | ||||
1687 | if (io ->Read(io, Temp, 256, 1) != 1) goto Error; | |||
1688 | ||||
1689 | for (j=0; j < 256; j++) | |||
1690 | Tables[i]->Table16[j] = (cmsUInt16Number) FROM_8_TO_16(Temp[j])(cmsUInt16Number) ((((cmsUInt16Number) (Temp[j])) << 8) |(Temp[j])); | |||
1691 | } | |||
1692 | ||||
1693 | _cmsFree(ContextID, Temp); | |||
1694 | Temp = NULL((void*)0); | |||
1695 | ||||
1696 | if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables))) | |||
1697 | goto Error; | |||
1698 | ||||
1699 | for (i=0; i < nChannels; i++) | |||
1700 | cmsFreeToneCurve(Tables[i]); | |||
1701 | ||||
1702 | return TRUE1; | |||
1703 | ||||
1704 | Error: | |||
1705 | for (i=0; i < nChannels; i++) { | |||
1706 | if (Tables[i]) cmsFreeToneCurve(Tables[i]); | |||
1707 | } | |||
1708 | ||||
1709 | if (Temp) _cmsFree(ContextID, Temp); | |||
1710 | return FALSE0; | |||
1711 | } | |||
1712 | ||||
1713 | ||||
1714 | static | |||
1715 | cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number n, _cmsStageToneCurvesData* Tables) | |||
1716 | { | |||
1717 | int j; | |||
1718 | cmsUInt32Number i; | |||
1719 | cmsUInt8Number val; | |||
1720 | ||||
1721 | for (i=0; i < n; i++) { | |||
1722 | ||||
1723 | if (Tables) { | |||
1724 | ||||
1725 | // Usual case of identity curves | |||
1726 | if ((Tables ->TheCurves[i]->nEntries == 2) && | |||
1727 | (Tables->TheCurves[i]->Table16[0] == 0) && | |||
1728 | (Tables->TheCurves[i]->Table16[1] == 65535)) { | |||
1729 | ||||
1730 | for (j=0; j < 256; j++) { | |||
1731 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE0; | |||
1732 | } | |||
1733 | } | |||
1734 | else | |||
1735 | if (Tables ->TheCurves[i]->nEntries != 256) { | |||
1736 | cmsSignalError(ContextID, cmsERROR_RANGE2, "LUT8 needs 256 entries on prelinearization"); | |||
1737 | return FALSE0; | |||
1738 | } | |||
1739 | else | |||
1740 | for (j=0; j < 256; j++) { | |||
1741 | ||||
1742 | val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j])(cmsUInt8Number) ((((cmsUInt32Number)(Tables->TheCurves[i] ->Table16[j]) * 65281U + 8388608U) >> 24) & 0xFFU ); | |||
1743 | ||||
1744 | if (!_cmsWriteUInt8Number(io, val)) return FALSE0; | |||
1745 | } | |||
1746 | } | |||
1747 | } | |||
1748 | return TRUE1; | |||
1749 | } | |||
1750 | ||||
1751 | ||||
1752 | // Check overflow | |||
1753 | static | |||
1754 | cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b) | |||
1755 | { | |||
1756 | cmsUInt32Number rv = 1, rc; | |||
1757 | ||||
1758 | if (a == 0) return 0; | |||
1759 | if (n == 0) return 0; | |||
1760 | ||||
1761 | for (; b > 0; b--) { | |||
1762 | ||||
1763 | rv *= a; | |||
1764 | ||||
1765 | // Check for overflow | |||
1766 | if (rv > UINT_MAX(2147483647 *2U +1U) / a) return (cmsUInt32Number) -1; | |||
1767 | ||||
1768 | } | |||
1769 | ||||
1770 | rc = rv * n; | |||
1771 | ||||
1772 | if (rv != rc / n) return (cmsUInt32Number) -1; | |||
1773 | return rc; | |||
1774 | } | |||
1775 | ||||
1776 | ||||
1777 | // That will create a MPE LUT with Matrix, pre tables, CLUT and post tables. | |||
1778 | // 8 bit lut may be scaled easely to v4 PCS, but we need also to properly adjust | |||
1779 | // PCS on BToAxx tags and AtoB if abstract. We need to fix input direction. | |||
1780 | ||||
1781 | static | |||
1782 | void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
1783 | { | |||
1784 | cmsUInt8Number InputChannels, OutputChannels, CLUTpoints; | |||
1785 | cmsUInt8Number* Temp = NULL((void*)0); | |||
1786 | cmsPipeline* NewLUT = NULL((void*)0); | |||
1787 | cmsUInt32Number nTabSize, i; | |||
1788 | cmsFloat64Number Matrix[3*3]; | |||
1789 | ||||
1790 | *nItems = 0; | |||
1791 | ||||
1792 | if (!_cmsReadUInt8Number(io, &InputChannels)) goto Error; | |||
1793 | if (!_cmsReadUInt8Number(io, &OutputChannels)) goto Error; | |||
1794 | if (!_cmsReadUInt8Number(io, &CLUTpoints)) goto Error; | |||
1795 | ||||
1796 | if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least | |||
1797 | ||||
1798 | // Padding | |||
1799 | if (!_cmsReadUInt8Number(io, NULL((void*)0))) goto Error; | |||
1800 | ||||
1801 | // Do some checking | |||
1802 | if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS16) goto Error; | |||
1803 | if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS16) goto Error; | |||
1804 | ||||
1805 | // Allocates an empty Pipeline | |||
1806 | NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); | |||
1807 | if (NewLUT == NULL((void*)0)) goto Error; | |||
1808 | ||||
1809 | // Read the Matrix | |||
1810 | if (!_cmsRead15Fixed16Number(io, &Matrix[0])) goto Error; | |||
1811 | if (!_cmsRead15Fixed16Number(io, &Matrix[1])) goto Error; | |||
1812 | if (!_cmsRead15Fixed16Number(io, &Matrix[2])) goto Error; | |||
1813 | if (!_cmsRead15Fixed16Number(io, &Matrix[3])) goto Error; | |||
1814 | if (!_cmsRead15Fixed16Number(io, &Matrix[4])) goto Error; | |||
1815 | if (!_cmsRead15Fixed16Number(io, &Matrix[5])) goto Error; | |||
1816 | if (!_cmsRead15Fixed16Number(io, &Matrix[6])) goto Error; | |||
1817 | if (!_cmsRead15Fixed16Number(io, &Matrix[7])) goto Error; | |||
1818 | if (!_cmsRead15Fixed16Number(io, &Matrix[8])) goto Error; | |||
1819 | ||||
1820 | ||||
1821 | // Only operates if not identity... | |||
1822 | if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) { | |||
1823 | ||||
1824 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL((void*)0)))) | |||
1825 | goto Error; | |||
1826 | } | |||
1827 | ||||
1828 | // Get input tables | |||
1829 | if (!Read8bitTables(self ->ContextID, io, NewLUT, InputChannels)) goto Error; | |||
1830 | ||||
1831 | // Get 3D CLUT. Check the overflow.... | |||
1832 | nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels); | |||
1833 | if (nTabSize == (cmsUInt32Number) -1) goto Error; | |||
1834 | if (nTabSize > 0) { | |||
1835 | ||||
1836 | cmsUInt16Number *PtrW, *T; | |||
1837 | ||||
1838 | PtrW = T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number)); | |||
1839 | if (T == NULL((void*)0)) goto Error; | |||
1840 | ||||
1841 | Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize); | |||
1842 | if (Temp == NULL((void*)0)) { | |||
1843 | _cmsFree(self ->ContextID, T); | |||
1844 | goto Error; | |||
1845 | } | |||
1846 | ||||
1847 | if (io ->Read(io, Temp, nTabSize, 1) != 1) { | |||
1848 | _cmsFree(self ->ContextID, T); | |||
1849 | _cmsFree(self ->ContextID, Temp); | |||
1850 | goto Error; | |||
1851 | } | |||
1852 | ||||
1853 | for (i = 0; i < nTabSize; i++) { | |||
1854 | ||||
1855 | *PtrW++ = FROM_8_TO_16(Temp[i])(cmsUInt16Number) ((((cmsUInt16Number) (Temp[i])) << 8) |(Temp[i])); | |||
1856 | } | |||
1857 | _cmsFree(self ->ContextID, Temp); | |||
1858 | Temp = NULL((void*)0); | |||
1859 | ||||
1860 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) { | |||
1861 | _cmsFree(self ->ContextID, T); | |||
1862 | goto Error; | |||
1863 | } | |||
1864 | _cmsFree(self ->ContextID, T); | |||
1865 | } | |||
1866 | ||||
1867 | ||||
1868 | // Get output tables | |||
1869 | if (!Read8bitTables(self ->ContextID, io, NewLUT, OutputChannels)) goto Error; | |||
1870 | ||||
1871 | *nItems = 1; | |||
1872 | return NewLUT; | |||
1873 | ||||
1874 | Error: | |||
1875 | if (NewLUT != NULL((void*)0)) cmsPipelineFree(NewLUT); | |||
1876 | return NULL((void*)0); | |||
1877 | ||||
1878 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
1879 | } | |||
1880 | ||||
1881 | // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin. | |||
1882 | static | |||
1883 | cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
1884 | { | |||
1885 | cmsUInt32Number j, nTabSize, i, n; | |||
1886 | cmsUInt8Number val; | |||
1887 | cmsPipeline* NewLUT = (cmsPipeline*) Ptr; | |||
1888 | cmsStage* mpe; | |||
1889 | _cmsStageToneCurvesData* PreMPE = NULL((void*)0), *PostMPE = NULL((void*)0); | |||
1890 | _cmsStageMatrixData* MatMPE = NULL((void*)0); | |||
1891 | _cmsStageCLutData* clut = NULL((void*)0); | |||
1892 | cmsUInt32Number clutPoints; | |||
1893 | ||||
1894 | // Disassemble the LUT into components. | |||
1895 | mpe = NewLUT -> Elements; | |||
1896 | if (mpe ->Type == cmsSigMatrixElemType) { | |||
1897 | ||||
1898 | if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE0; | |||
1899 | MatMPE = (_cmsStageMatrixData*) mpe ->Data; | |||
1900 | mpe = mpe -> Next; | |||
1901 | } | |||
1902 | ||||
1903 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigCurveSetElemType) { | |||
1904 | PreMPE = (_cmsStageToneCurvesData*) mpe ->Data; | |||
1905 | mpe = mpe -> Next; | |||
1906 | } | |||
1907 | ||||
1908 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigCLutElemType) { | |||
1909 | clut = (_cmsStageCLutData*) mpe -> Data; | |||
1910 | mpe = mpe ->Next; | |||
1911 | } | |||
1912 | ||||
1913 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigCurveSetElemType) { | |||
1914 | PostMPE = (_cmsStageToneCurvesData*) mpe ->Data; | |||
1915 | mpe = mpe -> Next; | |||
1916 | } | |||
1917 | ||||
1918 | // That should be all | |||
1919 | if (mpe != NULL((void*)0)) { | |||
1920 | cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "LUT is not suitable to be saved as LUT8"); | |||
1921 | return FALSE0; | |||
1922 | } | |||
1923 | ||||
1924 | if (clut == NULL((void*)0)) | |||
1925 | clutPoints = 0; | |||
1926 | else | |||
1927 | clutPoints = clut->Params->nSamples[0]; | |||
1928 | ||||
1929 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE0; | |||
1930 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE0; | |||
1931 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE0; | |||
1932 | if (!_cmsWriteUInt8Number(io, 0)) return FALSE0; // Padding | |||
1933 | ||||
1934 | n = NewLUT->InputChannels * NewLUT->OutputChannels; | |||
1935 | ||||
1936 | if (MatMPE != NULL((void*)0)) { | |||
1937 | ||||
1938 | for (i = 0; i < 9; i++) | |||
1939 | { | |||
1940 | if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE0; | |||
1941 | } | |||
1942 | } | |||
1943 | else { | |||
1944 | ||||
1945 | if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE0; | |||
1946 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
1947 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
1948 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
1949 | if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE0; | |||
1950 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
1951 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
1952 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
1953 | if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE0; | |||
1954 | } | |||
1955 | ||||
1956 | // The prelinearization table | |||
1957 | if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE0; | |||
1958 | ||||
1959 | nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels); | |||
1960 | if (nTabSize == (cmsUInt32Number) -1) return FALSE0; | |||
1961 | if (nTabSize > 0) { | |||
1962 | ||||
1963 | // The 3D CLUT. | |||
1964 | if (clut != NULL((void*)0)) { | |||
1965 | ||||
1966 | for (j=0; j < nTabSize; j++) { | |||
1967 | ||||
1968 | val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j])(cmsUInt8Number) ((((cmsUInt32Number)(clut ->Tab.T[j]) * 65281U + 8388608U) >> 24) & 0xFFU); | |||
1969 | if (!_cmsWriteUInt8Number(io, val)) return FALSE0; | |||
1970 | } | |||
1971 | } | |||
1972 | } | |||
1973 | ||||
1974 | // The postlinearization table | |||
1975 | if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE0; | |||
1976 | ||||
1977 | return TRUE1; | |||
1978 | ||||
1979 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
1980 | } | |||
1981 | ||||
1982 | ||||
1983 | static | |||
1984 | void* Type_LUT8_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
1985 | { | |||
1986 | return (void*) cmsPipelineDup((cmsPipeline*) Ptr); | |||
1987 | ||||
1988 | cmsUNUSED_PARAMETER(n)((void)n); | |||
1989 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1990 | } | |||
1991 | ||||
1992 | static | |||
1993 | void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
1994 | { | |||
1995 | cmsPipelineFree((cmsPipeline*) Ptr); | |||
1996 | return; | |||
1997 | ||||
1998 | cmsUNUSED_PARAMETER(self)((void)self); | |||
1999 | } | |||
2000 | ||||
2001 | // ******************************************************************************** | |||
2002 | // Type cmsSigLut16Type | |||
2003 | // ******************************************************************************** | |||
2004 | ||||
2005 | // Read 16 bit tables as gamma functions | |||
2006 | static | |||
2007 | cmsBool Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, | |||
2008 | cmsUInt32Number nChannels, cmsUInt32Number nEntries) | |||
2009 | { | |||
2010 | cmsUInt32Number i; | |||
2011 | cmsToneCurve* Tables[cmsMAXCHANNELS16]; | |||
2012 | ||||
2013 | // Maybe an empty table? (this is a lcms extension) | |||
2014 | if (nEntries <= 0) return TRUE1; | |||
2015 | ||||
2016 | // Check for malicious profiles | |||
2017 | if (nEntries < 2) return FALSE0; | |||
2018 | if (nChannels > cmsMAXCHANNELS16) return FALSE0; | |||
2019 | ||||
2020 | // Init table to zero | |||
2021 | memset(Tables, 0, sizeof(Tables)); | |||
2022 | ||||
2023 | for (i=0; i < nChannels; i++) { | |||
2024 | ||||
2025 | Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, nEntries, NULL((void*)0)); | |||
2026 | if (Tables[i] == NULL((void*)0)) goto Error; | |||
2027 | ||||
2028 | if (!_cmsReadUInt16Array(io, nEntries, Tables[i]->Table16)) goto Error; | |||
2029 | } | |||
2030 | ||||
2031 | ||||
2032 | // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code) | |||
2033 | if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables))) | |||
2034 | goto Error; | |||
2035 | ||||
2036 | for (i=0; i < nChannels; i++) | |||
2037 | cmsFreeToneCurve(Tables[i]); | |||
2038 | ||||
2039 | return TRUE1; | |||
2040 | ||||
2041 | Error: | |||
2042 | for (i=0; i < nChannels; i++) { | |||
2043 | if (Tables[i]) cmsFreeToneCurve(Tables[i]); | |||
2044 | } | |||
2045 | ||||
2046 | return FALSE0; | |||
2047 | } | |||
2048 | ||||
2049 | static | |||
2050 | cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables) | |||
2051 | { | |||
2052 | cmsUInt32Number j; | |||
2053 | cmsUInt32Number i; | |||
2054 | cmsUInt16Number val; | |||
2055 | cmsUInt32Number nEntries; | |||
2056 | ||||
2057 | _cmsAssert(Tables != NULL)(((Tables != ((void*)0))) ? (void) (0) : __assert_fail ("(Tables != ((void*)0))" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/liblcms/cmstypes.c" , 2057, __extension__ __PRETTY_FUNCTION__)); | |||
2058 | ||||
2059 | nEntries = Tables->TheCurves[0]->nEntries; | |||
2060 | ||||
2061 | for (i=0; i < Tables ->nCurves; i++) { | |||
2062 | ||||
2063 | for (j=0; j < nEntries; j++) { | |||
2064 | ||||
2065 | val = Tables->TheCurves[i]->Table16[j]; | |||
2066 | if (!_cmsWriteUInt16Number(io, val)) return FALSE0; | |||
2067 | } | |||
2068 | } | |||
2069 | return TRUE1; | |||
2070 | ||||
2071 | cmsUNUSED_PARAMETER(ContextID)((void)ContextID); | |||
2072 | } | |||
2073 | ||||
2074 | static | |||
2075 | void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
2076 | { | |||
2077 | cmsUInt8Number InputChannels, OutputChannels, CLUTpoints; | |||
2078 | cmsPipeline* NewLUT = NULL((void*)0); | |||
2079 | cmsUInt32Number nTabSize; | |||
2080 | cmsFloat64Number Matrix[3*3]; | |||
2081 | cmsUInt16Number InputEntries, OutputEntries; | |||
2082 | ||||
2083 | *nItems = 0; | |||
2084 | ||||
2085 | if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL((void*)0); | |||
2086 | if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL((void*)0); | |||
2087 | if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL((void*)0); // 255 maximum | |||
2088 | ||||
2089 | // Padding | |||
2090 | if (!_cmsReadUInt8Number(io, NULL((void*)0))) return NULL((void*)0); | |||
2091 | ||||
2092 | // Do some checking | |||
2093 | if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS16) goto Error; | |||
2094 | if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS16) goto Error; | |||
2095 | ||||
2096 | // Allocates an empty LUT | |||
2097 | NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels); | |||
2098 | if (NewLUT == NULL((void*)0)) goto Error; | |||
2099 | ||||
2100 | // Read the Matrix | |||
2101 | if (!_cmsRead15Fixed16Number(io, &Matrix[0])) goto Error; | |||
2102 | if (!_cmsRead15Fixed16Number(io, &Matrix[1])) goto Error; | |||
2103 | if (!_cmsRead15Fixed16Number(io, &Matrix[2])) goto Error; | |||
2104 | if (!_cmsRead15Fixed16Number(io, &Matrix[3])) goto Error; | |||
2105 | if (!_cmsRead15Fixed16Number(io, &Matrix[4])) goto Error; | |||
2106 | if (!_cmsRead15Fixed16Number(io, &Matrix[5])) goto Error; | |||
2107 | if (!_cmsRead15Fixed16Number(io, &Matrix[6])) goto Error; | |||
2108 | if (!_cmsRead15Fixed16Number(io, &Matrix[7])) goto Error; | |||
2109 | if (!_cmsRead15Fixed16Number(io, &Matrix[8])) goto Error; | |||
2110 | ||||
2111 | ||||
2112 | // Only operates on 3 channels | |||
2113 | if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) { | |||
2114 | ||||
2115 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL((void*)0)))) | |||
2116 | goto Error; | |||
2117 | } | |||
2118 | ||||
2119 | if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error; | |||
2120 | if (!_cmsReadUInt16Number(io, &OutputEntries)) goto Error; | |||
2121 | ||||
2122 | if (InputEntries > 0x7FFF || OutputEntries > 0x7FFF) goto Error; | |||
2123 | if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least | |||
2124 | ||||
2125 | // Get input tables | |||
2126 | if (!Read16bitTables(self ->ContextID, io, NewLUT, InputChannels, InputEntries)) goto Error; | |||
2127 | ||||
2128 | // Get 3D CLUT | |||
2129 | nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels); | |||
2130 | if (nTabSize == (cmsUInt32Number) -1) goto Error; | |||
2131 | if (nTabSize > 0) { | |||
2132 | ||||
2133 | cmsUInt16Number *T; | |||
2134 | ||||
2135 | T = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number)); | |||
2136 | if (T == NULL((void*)0)) goto Error; | |||
2137 | ||||
2138 | if (!_cmsReadUInt16Array(io, nTabSize, T)) { | |||
2139 | _cmsFree(self ->ContextID, T); | |||
2140 | goto Error; | |||
2141 | } | |||
2142 | ||||
2143 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) { | |||
2144 | _cmsFree(self ->ContextID, T); | |||
2145 | goto Error; | |||
2146 | } | |||
2147 | _cmsFree(self ->ContextID, T); | |||
2148 | } | |||
2149 | ||||
2150 | ||||
2151 | // Get output tables | |||
2152 | if (!Read16bitTables(self ->ContextID, io, NewLUT, OutputChannels, OutputEntries)) goto Error; | |||
2153 | ||||
2154 | *nItems = 1; | |||
2155 | return NewLUT; | |||
2156 | ||||
2157 | Error: | |||
2158 | if (NewLUT != NULL((void*)0)) cmsPipelineFree(NewLUT); | |||
2159 | return NULL((void*)0); | |||
2160 | ||||
2161 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
2162 | } | |||
2163 | ||||
2164 | // We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin. | |||
2165 | // Some empty defaults are created for missing parts | |||
2166 | ||||
2167 | static | |||
2168 | cmsBool Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
2169 | { | |||
2170 | cmsUInt32Number nTabSize; | |||
2171 | cmsPipeline* NewLUT = (cmsPipeline*) Ptr; | |||
2172 | cmsStage* mpe; | |||
2173 | _cmsStageToneCurvesData* PreMPE = NULL((void*)0), *PostMPE = NULL((void*)0); | |||
2174 | _cmsStageMatrixData* MatMPE = NULL((void*)0); | |||
2175 | _cmsStageCLutData* clut = NULL((void*)0); | |||
2176 | cmsUInt32Number i, InputChannels, OutputChannels, clutPoints; | |||
2177 | ||||
2178 | // Disassemble the LUT into components. | |||
2179 | mpe = NewLUT -> Elements; | |||
2180 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigMatrixElemType) { | |||
2181 | ||||
2182 | MatMPE = (_cmsStageMatrixData*) mpe ->Data; | |||
2183 | if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE0; | |||
2184 | mpe = mpe -> Next; | |||
2185 | } | |||
2186 | ||||
2187 | ||||
2188 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigCurveSetElemType) { | |||
2189 | PreMPE = (_cmsStageToneCurvesData*) mpe ->Data; | |||
2190 | mpe = mpe -> Next; | |||
2191 | } | |||
2192 | ||||
2193 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigCLutElemType) { | |||
2194 | clut = (_cmsStageCLutData*) mpe -> Data; | |||
2195 | mpe = mpe ->Next; | |||
2196 | } | |||
2197 | ||||
2198 | if (mpe != NULL((void*)0) && mpe ->Type == cmsSigCurveSetElemType) { | |||
2199 | PostMPE = (_cmsStageToneCurvesData*) mpe ->Data; | |||
2200 | mpe = mpe -> Next; | |||
2201 | } | |||
2202 | ||||
2203 | // That should be all | |||
2204 | if (mpe != NULL((void*)0)) { | |||
2205 | cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "LUT is not suitable to be saved as LUT16"); | |||
2206 | return FALSE0; | |||
2207 | } | |||
2208 | ||||
2209 | InputChannels = cmsPipelineInputChannels(NewLUT); | |||
2210 | OutputChannels = cmsPipelineOutputChannels(NewLUT); | |||
2211 | ||||
2212 | if (clut == NULL((void*)0)) | |||
2213 | clutPoints = 0; | |||
2214 | else | |||
2215 | clutPoints = clut->Params->nSamples[0]; | |||
2216 | ||||
2217 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE0; | |||
2218 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE0; | |||
2219 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE0; | |||
2220 | if (!_cmsWriteUInt8Number(io, 0)) return FALSE0; // Padding | |||
2221 | ||||
2222 | if (MatMPE != NULL((void*)0)) { | |||
2223 | ||||
2224 | for (i = 0; i < 9; i++) | |||
2225 | { | |||
2226 | if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE0; | |||
2227 | } | |||
2228 | ||||
2229 | } | |||
2230 | else { | |||
2231 | ||||
2232 | if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE0; | |||
2233 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2234 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2235 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2236 | if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE0; | |||
2237 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2238 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2239 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2240 | if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE0; | |||
2241 | } | |||
2242 | ||||
2243 | ||||
2244 | if (PreMPE != NULL((void*)0)) { | |||
2245 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE0; | |||
2246 | } else { | |||
2247 | if (!_cmsWriteUInt16Number(io, 2)) return FALSE0; | |||
2248 | } | |||
2249 | ||||
2250 | if (PostMPE != NULL((void*)0)) { | |||
2251 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE0; | |||
2252 | } else { | |||
2253 | if (!_cmsWriteUInt16Number(io, 2)) return FALSE0; | |||
2254 | ||||
2255 | } | |||
2256 | ||||
2257 | // The prelinearization table | |||
2258 | ||||
2259 | if (PreMPE != NULL((void*)0)) { | |||
2260 | if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE0; | |||
2261 | } | |||
2262 | else { | |||
2263 | for (i=0; i < InputChannels; i++) { | |||
2264 | ||||
2265 | if (!_cmsWriteUInt16Number(io, 0)) return FALSE0; | |||
2266 | if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE0; | |||
2267 | } | |||
2268 | } | |||
2269 | ||||
2270 | nTabSize = uipow(OutputChannels, clutPoints, InputChannels); | |||
2271 | if (nTabSize == (cmsUInt32Number) -1) return FALSE0; | |||
2272 | if (nTabSize > 0) { | |||
2273 | // The 3D CLUT. | |||
2274 | if (clut != NULL((void*)0)) { | |||
2275 | if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE0; | |||
2276 | } | |||
2277 | } | |||
2278 | ||||
2279 | // The postlinearization table | |||
2280 | if (PostMPE != NULL((void*)0)) { | |||
2281 | if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE0; | |||
2282 | } | |||
2283 | else { | |||
2284 | for (i=0; i < OutputChannels; i++) { | |||
2285 | ||||
2286 | if (!_cmsWriteUInt16Number(io, 0)) return FALSE0; | |||
2287 | if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE0; | |||
2288 | } | |||
2289 | } | |||
2290 | ||||
2291 | return TRUE1; | |||
2292 | ||||
2293 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
2294 | } | |||
2295 | ||||
2296 | static | |||
2297 | void* Type_LUT16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
2298 | { | |||
2299 | return (void*) cmsPipelineDup((cmsPipeline*) Ptr); | |||
2300 | ||||
2301 | cmsUNUSED_PARAMETER(n)((void)n); | |||
2302 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2303 | } | |||
2304 | ||||
2305 | static | |||
2306 | void Type_LUT16_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
2307 | { | |||
2308 | cmsPipelineFree((cmsPipeline*) Ptr); | |||
2309 | return; | |||
2310 | ||||
2311 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2312 | } | |||
2313 | ||||
2314 | ||||
2315 | // ******************************************************************************** | |||
2316 | // Type cmsSigLutAToBType | |||
2317 | // ******************************************************************************** | |||
2318 | ||||
2319 | ||||
2320 | // V4 stuff. Read matrix for LutAtoB and LutBtoA | |||
2321 | ||||
2322 | static | |||
2323 | cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset) | |||
2324 | { | |||
2325 | cmsFloat64Number dMat[3*3]; | |||
2326 | cmsFloat64Number dOff[3]; | |||
2327 | cmsStage* Mat; | |||
2328 | ||||
2329 | // Go to address | |||
2330 | if (!io -> Seek(io, Offset)) return NULL((void*)0); | |||
2331 | ||||
2332 | // Read the Matrix | |||
2333 | if (!_cmsRead15Fixed16Number(io, &dMat[0])) return NULL((void*)0); | |||
2334 | if (!_cmsRead15Fixed16Number(io, &dMat[1])) return NULL((void*)0); | |||
2335 | if (!_cmsRead15Fixed16Number(io, &dMat[2])) return NULL((void*)0); | |||
2336 | if (!_cmsRead15Fixed16Number(io, &dMat[3])) return NULL((void*)0); | |||
2337 | if (!_cmsRead15Fixed16Number(io, &dMat[4])) return NULL((void*)0); | |||
2338 | if (!_cmsRead15Fixed16Number(io, &dMat[5])) return NULL((void*)0); | |||
2339 | if (!_cmsRead15Fixed16Number(io, &dMat[6])) return NULL((void*)0); | |||
2340 | if (!_cmsRead15Fixed16Number(io, &dMat[7])) return NULL((void*)0); | |||
2341 | if (!_cmsRead15Fixed16Number(io, &dMat[8])) return NULL((void*)0); | |||
2342 | ||||
2343 | if (!_cmsRead15Fixed16Number(io, &dOff[0])) return NULL((void*)0); | |||
2344 | if (!_cmsRead15Fixed16Number(io, &dOff[1])) return NULL((void*)0); | |||
2345 | if (!_cmsRead15Fixed16Number(io, &dOff[2])) return NULL((void*)0); | |||
2346 | ||||
2347 | Mat = cmsStageAllocMatrix(self ->ContextID, 3, 3, dMat, dOff); | |||
2348 | ||||
2349 | return Mat; | |||
2350 | } | |||
2351 | ||||
2352 | ||||
2353 | ||||
2354 | ||||
2355 | // V4 stuff. Read CLUT part for LutAtoB and LutBtoA | |||
2356 | ||||
2357 | static | |||
2358 | cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, | |||
2359 | cmsUInt32Number Offset, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels) | |||
2360 | { | |||
2361 | cmsUInt8Number gridPoints8[cmsMAXCHANNELS16]; // Number of grid points in each dimension. | |||
2362 | cmsUInt32Number GridPoints[cmsMAXCHANNELS16], i; | |||
2363 | cmsUInt8Number Precision; | |||
2364 | cmsStage* CLUT; | |||
2365 | _cmsStageCLutData* Data; | |||
2366 | ||||
2367 | if (!io -> Seek(io, Offset)) return NULL((void*)0); | |||
2368 | if (io -> Read(io, gridPoints8, cmsMAXCHANNELS16, 1) != 1) return NULL((void*)0); | |||
2369 | ||||
2370 | ||||
2371 | for (i=0; i < cmsMAXCHANNELS16; i++) { | |||
2372 | ||||
2373 | if (gridPoints8[i] == 1) return NULL((void*)0); // Impossible value, 0 for no CLUT and then 2 at least | |||
2374 | GridPoints[i] = gridPoints8[i]; | |||
2375 | } | |||
2376 | ||||
2377 | if (!_cmsReadUInt8Number(io, &Precision)) return NULL((void*)0); | |||
2378 | ||||
2379 | if (!_cmsReadUInt8Number(io, NULL((void*)0))) return NULL((void*)0); | |||
2380 | if (!_cmsReadUInt8Number(io, NULL((void*)0))) return NULL((void*)0); | |||
2381 | if (!_cmsReadUInt8Number(io, NULL((void*)0))) return NULL((void*)0); | |||
2382 | ||||
2383 | CLUT = cmsStageAllocCLut16bitGranular(self ->ContextID, GridPoints, InputChannels, OutputChannels, NULL((void*)0)); | |||
2384 | if (CLUT == NULL((void*)0)) return NULL((void*)0); | |||
2385 | ||||
2386 | Data = (_cmsStageCLutData*) CLUT ->Data; | |||
2387 | ||||
2388 | // Precision can be 1 or 2 bytes | |||
2389 | if (Precision == 1) { | |||
2390 | ||||
2391 | cmsUInt8Number v; | |||
2392 | ||||
2393 | for (i=0; i < Data ->nEntries; i++) { | |||
2394 | ||||
2395 | if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) { | |||
2396 | cmsStageFree(CLUT); | |||
2397 | return NULL((void*)0); | |||
2398 | } | |||
2399 | Data ->Tab.T[i] = FROM_8_TO_16(v)(cmsUInt16Number) ((((cmsUInt16Number) (v)) << 8)|(v)); | |||
2400 | } | |||
2401 | ||||
2402 | } | |||
2403 | else | |||
2404 | if (Precision == 2) { | |||
2405 | ||||
2406 | if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) { | |||
2407 | cmsStageFree(CLUT); | |||
2408 | return NULL((void*)0); | |||
2409 | } | |||
2410 | } | |||
2411 | else { | |||
2412 | cmsStageFree(CLUT); | |||
2413 | cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown precision of '%d'", Precision); | |||
2414 | return NULL((void*)0); | |||
2415 | } | |||
2416 | ||||
2417 | return CLUT; | |||
2418 | } | |||
2419 | ||||
2420 | static | |||
2421 | cmsToneCurve* ReadEmbeddedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io) | |||
2422 | { | |||
2423 | cmsTagTypeSignature BaseType; | |||
2424 | cmsUInt32Number nItems; | |||
2425 | ||||
2426 | BaseType = _cmsReadTypeBase(io); | |||
2427 | switch (BaseType) { | |||
2428 | ||||
2429 | case cmsSigCurveType: | |||
2430 | return (cmsToneCurve*) Type_Curve_Read(self, io, &nItems, 0); | |||
2431 | ||||
2432 | case cmsSigParametricCurveType: | |||
2433 | return (cmsToneCurve*) Type_ParametricCurve_Read(self, io, &nItems, 0); | |||
2434 | ||||
2435 | default: | |||
2436 | { | |||
2437 | char String[5]; | |||
2438 | ||||
2439 | _cmsTagSignature2String(String, (cmsTagSignature) BaseType); | |||
2440 | cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown curve type '%s'", String); | |||
2441 | } | |||
2442 | return NULL((void*)0); | |||
2443 | } | |||
2444 | } | |||
2445 | ||||
2446 | ||||
2447 | // Read a set of curves from specific offset | |||
2448 | static | |||
2449 | cmsStage* ReadSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, cmsUInt32Number nCurves) | |||
2450 | { | |||
2451 | cmsToneCurve* Curves[cmsMAXCHANNELS16]; | |||
2452 | cmsUInt32Number i; | |||
2453 | cmsStage* Lin = NULL((void*)0); | |||
2454 | ||||
2455 | if (nCurves > cmsMAXCHANNELS16) return FALSE0; | |||
2456 | ||||
2457 | if (!io -> Seek(io, Offset)) return FALSE0; | |||
2458 | ||||
2459 | for (i=0; i < nCurves; i++) | |||
2460 | Curves[i] = NULL((void*)0); | |||
2461 | ||||
2462 | for (i=0; i < nCurves; i++) { | |||
2463 | ||||
2464 | Curves[i] = ReadEmbeddedCurve(self, io); | |||
2465 | if (Curves[i] == NULL((void*)0)) goto Error; | |||
2466 | if (!_cmsReadAlignment(io)) goto Error; | |||
2467 | ||||
2468 | } | |||
2469 | ||||
2470 | Lin = cmsStageAllocToneCurves(self ->ContextID, nCurves, Curves); | |||
2471 | ||||
2472 | Error: | |||
2473 | for (i=0; i < nCurves; i++) | |||
2474 | cmsFreeToneCurve(Curves[i]); | |||
2475 | ||||
2476 | return Lin; | |||
2477 | } | |||
2478 | ||||
2479 | ||||
2480 | // LutAtoB type | |||
2481 | ||||
2482 | // This structure represents a colour transform. The type contains up to five processing | |||
2483 | // elements which are stored in the AtoBTag tag in the following order: a set of one | |||
2484 | // dimensional curves, a 3 by 3 matrix with offset terms, a set of one dimensional curves, | |||
2485 | // a multidimensional lookup table, and a set of one dimensional output curves. | |||
2486 | // Data are processed using these elements via the following sequence: | |||
2487 | // | |||
2488 | //("A" curves) -> (multidimensional lookup table - CLUT) -> ("M" curves) -> (matrix) -> ("B" curves). | |||
2489 | // | |||
2490 | /* | |||
2491 | It is possible to use any or all of these processing elements. At least one processing element | |||
2492 | must be included.Only the following combinations are allowed: | |||
2493 | ||||
2494 | B | |||
2495 | M - Matrix - B | |||
2496 | A - CLUT - B | |||
2497 | A - CLUT - M - Matrix - B | |||
2498 | ||||
2499 | */ | |||
2500 | ||||
2501 | static | |||
2502 | void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
2503 | { | |||
2504 | cmsUInt32Number BaseOffset; | |||
2505 | cmsUInt8Number inputChan; // Number of input channels | |||
2506 | cmsUInt8Number outputChan; // Number of output channels | |||
2507 | cmsUInt32Number offsetB; // Offset to first "B" curve | |||
2508 | cmsUInt32Number offsetMat; // Offset to matrix | |||
2509 | cmsUInt32Number offsetM; // Offset to first "M" curve | |||
2510 | cmsUInt32Number offsetC; // Offset to CLUT | |||
2511 | cmsUInt32Number offsetA; // Offset to first "A" curve | |||
2512 | cmsPipeline* NewLUT = NULL((void*)0); | |||
2513 | ||||
2514 | ||||
2515 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
2516 | ||||
2517 | if (!_cmsReadUInt8Number(io, &inputChan)) return NULL((void*)0); | |||
2518 | if (!_cmsReadUInt8Number(io, &outputChan)) return NULL((void*)0); | |||
2519 | ||||
2520 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) return NULL((void*)0); | |||
2521 | ||||
2522 | if (!_cmsReadUInt32Number(io, &offsetB)) return NULL((void*)0); | |||
2523 | if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL((void*)0); | |||
2524 | if (!_cmsReadUInt32Number(io, &offsetM)) return NULL((void*)0); | |||
2525 | if (!_cmsReadUInt32Number(io, &offsetC)) return NULL((void*)0); | |||
2526 | if (!_cmsReadUInt32Number(io, &offsetA)) return NULL((void*)0); | |||
2527 | ||||
2528 | if (inputChan == 0 || inputChan >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
2529 | if (outputChan == 0 || outputChan >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
2530 | ||||
2531 | // Allocates an empty LUT | |||
2532 | NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); | |||
2533 | if (NewLUT == NULL((void*)0)) return NULL((void*)0); | |||
2534 | ||||
2535 | if (offsetA!= 0) { | |||
2536 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan))) | |||
2537 | goto Error; | |||
2538 | } | |||
2539 | ||||
2540 | if (offsetC != 0) { | |||
2541 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan))) | |||
2542 | goto Error; | |||
2543 | } | |||
2544 | ||||
2545 | if (offsetM != 0) { | |||
2546 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan))) | |||
2547 | goto Error; | |||
2548 | } | |||
2549 | ||||
2550 | if (offsetMat != 0) { | |||
2551 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat))) | |||
2552 | goto Error; | |||
2553 | } | |||
2554 | ||||
2555 | if (offsetB != 0) { | |||
2556 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan))) | |||
2557 | goto Error; | |||
2558 | } | |||
2559 | ||||
2560 | *nItems = 1; | |||
2561 | return NewLUT; | |||
2562 | Error: | |||
2563 | cmsPipelineFree(NewLUT); | |||
2564 | return NULL((void*)0); | |||
2565 | ||||
2566 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
2567 | } | |||
2568 | ||||
2569 | // Write a set of curves | |||
2570 | static | |||
2571 | cmsBool WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe) | |||
2572 | { | |||
2573 | cmsUInt32Number i, n; | |||
2574 | ||||
2575 | _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data; | |||
2576 | ||||
2577 | n = mpe->InputChannels * mpe->OutputChannels; | |||
2578 | ||||
2579 | // Write the Matrix | |||
2580 | for (i = 0; i < n; i++) | |||
2581 | { | |||
2582 | if (!_cmsWrite15Fixed16Number(io, m->Double[i])) return FALSE0; | |||
2583 | } | |||
2584 | ||||
2585 | if (m->Offset != NULL((void*)0)) { | |||
2586 | ||||
2587 | for (i = 0; i < mpe->OutputChannels; i++) | |||
2588 | { | |||
2589 | if (!_cmsWrite15Fixed16Number(io, m->Offset[i])) return FALSE0; | |||
2590 | } | |||
2591 | } | |||
2592 | else { | |||
2593 | for (i = 0; i < mpe->OutputChannels; i++) | |||
2594 | { | |||
2595 | if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE0; | |||
2596 | } | |||
2597 | } | |||
2598 | ||||
2599 | ||||
2600 | return TRUE1; | |||
2601 | ||||
2602 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2603 | } | |||
2604 | ||||
2605 | ||||
2606 | // Write a set of curves | |||
2607 | static | |||
2608 | cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe) | |||
2609 | { | |||
2610 | cmsUInt32Number i, n; | |||
2611 | cmsTagTypeSignature CurrentType; | |||
2612 | cmsToneCurve** Curves; | |||
2613 | ||||
2614 | ||||
2615 | n = cmsStageOutputChannels(mpe); | |||
2616 | Curves = _cmsStageGetPtrToCurveSet(mpe); | |||
2617 | ||||
2618 | for (i=0; i < n; i++) { | |||
2619 | ||||
2620 | // If this is a table-based curve, use curve type even on V4 | |||
2621 | CurrentType = Type; | |||
2622 | ||||
2623 | if ((Curves[i] ->nSegments == 0)|| | |||
2624 | ((Curves[i]->nSegments == 2) && (Curves[i] ->Segments[1].Type == 0)) ) | |||
2625 | CurrentType = cmsSigCurveType; | |||
2626 | else | |||
2627 | if (Curves[i] ->Segments[0].Type < 0) | |||
2628 | CurrentType = cmsSigCurveType; | |||
2629 | ||||
2630 | if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE0; | |||
2631 | ||||
2632 | switch (CurrentType) { | |||
2633 | ||||
2634 | case cmsSigCurveType: | |||
2635 | if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE0; | |||
2636 | break; | |||
2637 | ||||
2638 | case cmsSigParametricCurveType: | |||
2639 | if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE0; | |||
2640 | break; | |||
2641 | ||||
2642 | default: | |||
2643 | { | |||
2644 | char String[5]; | |||
2645 | ||||
2646 | _cmsTagSignature2String(String, (cmsTagSignature) Type); | |||
2647 | cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown curve type '%s'", String); | |||
2648 | } | |||
2649 | return FALSE0; | |||
2650 | } | |||
2651 | ||||
2652 | if (!_cmsWriteAlignment(io)) return FALSE0; | |||
2653 | } | |||
2654 | ||||
2655 | ||||
2656 | return TRUE1; | |||
2657 | } | |||
2658 | ||||
2659 | ||||
2660 | static | |||
2661 | cmsBool WriteCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt8Number Precision, cmsStage* mpe) | |||
2662 | { | |||
2663 | cmsUInt8Number gridPoints[cmsMAXCHANNELS16]; // Number of grid points in each dimension. | |||
2664 | cmsUInt32Number i; | |||
2665 | _cmsStageCLutData* CLUT = ( _cmsStageCLutData*) mpe -> Data; | |||
2666 | ||||
2667 | if (CLUT ->HasFloatValues) { | |||
2668 | cmsSignalError(self ->ContextID, cmsERROR_NOT_SUITABLE13, "Cannot save floating point data, CLUT are 8 or 16 bit only"); | |||
2669 | return FALSE0; | |||
2670 | } | |||
2671 | ||||
2672 | memset(gridPoints, 0, sizeof(gridPoints)); | |||
2673 | for (i=0; i < (cmsUInt32Number) CLUT ->Params ->nInputs; i++) | |||
2674 | gridPoints[i] = (cmsUInt8Number) CLUT ->Params ->nSamples[i]; | |||
2675 | ||||
2676 | if (!io -> Write(io, cmsMAXCHANNELS16*sizeof(cmsUInt8Number), gridPoints)) return FALSE0; | |||
2677 | ||||
2678 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) Precision)) return FALSE0; | |||
2679 | if (!_cmsWriteUInt8Number(io, 0)) return FALSE0; | |||
2680 | if (!_cmsWriteUInt8Number(io, 0)) return FALSE0; | |||
2681 | if (!_cmsWriteUInt8Number(io, 0)) return FALSE0; | |||
2682 | ||||
2683 | // Precision can be 1 or 2 bytes | |||
2684 | if (Precision == 1) { | |||
2685 | ||||
2686 | for (i=0; i < CLUT->nEntries; i++) { | |||
2687 | ||||
2688 | if (!_cmsWriteUInt8Number(io, FROM_16_TO_8(CLUT->Tab.T[i])(cmsUInt8Number) ((((cmsUInt32Number)(CLUT->Tab.T[i]) * 65281U + 8388608U) >> 24) & 0xFFU))) return FALSE0; | |||
2689 | } | |||
2690 | } | |||
2691 | else | |||
2692 | if (Precision == 2) { | |||
2693 | ||||
2694 | if (!_cmsWriteUInt16Array(io, CLUT->nEntries, CLUT ->Tab.T)) return FALSE0; | |||
2695 | } | |||
2696 | else { | |||
2697 | cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown precision of '%d'", Precision); | |||
2698 | return FALSE0; | |||
2699 | } | |||
2700 | ||||
2701 | if (!_cmsWriteAlignment(io)) return FALSE0; | |||
2702 | ||||
2703 | return TRUE1; | |||
2704 | } | |||
2705 | ||||
2706 | ||||
2707 | ||||
2708 | ||||
2709 | static | |||
2710 | cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
2711 | { | |||
2712 | cmsPipeline* Lut = (cmsPipeline*) Ptr; | |||
2713 | cmsUInt32Number inputChan, outputChan; | |||
2714 | cmsStage *A = NULL((void*)0), *B = NULL((void*)0), *M = NULL((void*)0); | |||
2715 | cmsStage * Matrix = NULL((void*)0); | |||
2716 | cmsStage * CLUT = NULL((void*)0); | |||
2717 | cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0; | |||
2718 | cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos; | |||
2719 | ||||
2720 | // Get the base for all offsets | |||
2721 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
2722 | ||||
2723 | if (Lut ->Elements != NULL((void*)0)) | |||
2724 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B)) | |||
2725 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &M, &Matrix, &B)) | |||
2726 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &A, &CLUT, &B)) | |||
2727 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, | |||
2728 | cmsSigMatrixElemType, cmsSigCurveSetElemType, &A, &CLUT, &M, &Matrix, &B)) { | |||
2729 | ||||
2730 | cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE13, "LUT is not suitable to be saved as LutAToB"); | |||
2731 | return FALSE0; | |||
2732 | } | |||
2733 | ||||
2734 | // Get input, output channels | |||
2735 | inputChan = cmsPipelineInputChannels(Lut); | |||
2736 | outputChan = cmsPipelineOutputChannels(Lut); | |||
2737 | ||||
2738 | // Write channel count | |||
2739 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE0; | |||
2740 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE0; | |||
2741 | if (!_cmsWriteUInt16Number(io, 0)) return FALSE0; | |||
2742 | ||||
2743 | // Keep directory to be filled latter | |||
2744 | DirectoryPos = io ->Tell(io); | |||
2745 | ||||
2746 | // Write the directory | |||
2747 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2748 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2749 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2750 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2751 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2752 | ||||
2753 | if (A != NULL((void*)0)) { | |||
2754 | ||||
2755 | offsetA = io ->Tell(io) - BaseOffset; | |||
2756 | if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE0; | |||
2757 | } | |||
2758 | ||||
2759 | if (CLUT != NULL((void*)0)) { | |||
2760 | offsetC = io ->Tell(io) - BaseOffset; | |||
2761 | if (!WriteCLUT(self, io, (Lut ->SaveAs8Bits ? 1U : 2U), CLUT)) return FALSE0; | |||
2762 | ||||
2763 | } | |||
2764 | if (M != NULL((void*)0)) { | |||
2765 | ||||
2766 | offsetM = io ->Tell(io) - BaseOffset; | |||
2767 | if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE0; | |||
2768 | } | |||
2769 | ||||
2770 | if (Matrix != NULL((void*)0)) { | |||
2771 | offsetMat = io ->Tell(io) - BaseOffset; | |||
2772 | if (!WriteMatrix(self, io, Matrix)) return FALSE0; | |||
2773 | } | |||
2774 | ||||
2775 | if (B != NULL((void*)0)) { | |||
2776 | ||||
2777 | offsetB = io ->Tell(io) - BaseOffset; | |||
2778 | if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE0; | |||
2779 | } | |||
2780 | ||||
2781 | CurrentPos = io ->Tell(io); | |||
2782 | ||||
2783 | if (!io ->Seek(io, DirectoryPos)) return FALSE0; | |||
2784 | ||||
2785 | if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE0; | |||
2786 | if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE0; | |||
2787 | if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE0; | |||
2788 | if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE0; | |||
2789 | if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE0; | |||
2790 | ||||
2791 | if (!io ->Seek(io, CurrentPos)) return FALSE0; | |||
2792 | ||||
2793 | return TRUE1; | |||
2794 | ||||
2795 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
2796 | } | |||
2797 | ||||
2798 | ||||
2799 | static | |||
2800 | void* Type_LUTA2B_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
2801 | { | |||
2802 | return (void*) cmsPipelineDup((cmsPipeline*) Ptr); | |||
2803 | ||||
2804 | cmsUNUSED_PARAMETER(n)((void)n); | |||
2805 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2806 | } | |||
2807 | ||||
2808 | static | |||
2809 | void Type_LUTA2B_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
2810 | { | |||
2811 | cmsPipelineFree((cmsPipeline*) Ptr); | |||
2812 | return; | |||
2813 | ||||
2814 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2815 | } | |||
2816 | ||||
2817 | ||||
2818 | // LutBToA type | |||
2819 | ||||
2820 | static | |||
2821 | void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
2822 | { | |||
2823 | cmsUInt8Number inputChan; // Number of input channels | |||
2824 | cmsUInt8Number outputChan; // Number of output channels | |||
2825 | cmsUInt32Number BaseOffset; // Actual position in file | |||
2826 | cmsUInt32Number offsetB; // Offset to first "B" curve | |||
2827 | cmsUInt32Number offsetMat; // Offset to matrix | |||
2828 | cmsUInt32Number offsetM; // Offset to first "M" curve | |||
2829 | cmsUInt32Number offsetC; // Offset to CLUT | |||
2830 | cmsUInt32Number offsetA; // Offset to first "A" curve | |||
2831 | cmsPipeline* NewLUT = NULL((void*)0); | |||
2832 | ||||
2833 | ||||
2834 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
2835 | ||||
2836 | if (!_cmsReadUInt8Number(io, &inputChan)) return NULL((void*)0); | |||
2837 | if (!_cmsReadUInt8Number(io, &outputChan)) return NULL((void*)0); | |||
2838 | ||||
2839 | if (inputChan == 0 || inputChan >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
2840 | if (outputChan == 0 || outputChan >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
2841 | ||||
2842 | // Padding | |||
2843 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) return NULL((void*)0); | |||
2844 | ||||
2845 | if (!_cmsReadUInt32Number(io, &offsetB)) return NULL((void*)0); | |||
2846 | if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL((void*)0); | |||
2847 | if (!_cmsReadUInt32Number(io, &offsetM)) return NULL((void*)0); | |||
2848 | if (!_cmsReadUInt32Number(io, &offsetC)) return NULL((void*)0); | |||
2849 | if (!_cmsReadUInt32Number(io, &offsetA)) return NULL((void*)0); | |||
2850 | ||||
2851 | // Allocates an empty LUT | |||
2852 | NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan); | |||
2853 | if (NewLUT == NULL((void*)0)) return NULL((void*)0); | |||
2854 | ||||
2855 | if (offsetB != 0) { | |||
2856 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan))) | |||
2857 | goto Error; | |||
2858 | } | |||
2859 | ||||
2860 | if (offsetMat != 0) { | |||
2861 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat))) | |||
2862 | goto Error; | |||
2863 | } | |||
2864 | ||||
2865 | if (offsetM != 0) { | |||
2866 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan))) | |||
2867 | goto Error; | |||
2868 | } | |||
2869 | ||||
2870 | if (offsetC != 0) { | |||
2871 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan))) | |||
2872 | goto Error; | |||
2873 | } | |||
2874 | ||||
2875 | if (offsetA!= 0) { | |||
2876 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan))) | |||
2877 | goto Error; | |||
2878 | } | |||
2879 | ||||
2880 | *nItems = 1; | |||
2881 | return NewLUT; | |||
2882 | Error: | |||
2883 | cmsPipelineFree(NewLUT); | |||
2884 | return NULL((void*)0); | |||
2885 | ||||
2886 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
2887 | } | |||
2888 | ||||
2889 | ||||
2890 | /* | |||
2891 | B | |||
2892 | B - Matrix - M | |||
2893 | B - CLUT - A | |||
2894 | B - Matrix - M - CLUT - A | |||
2895 | */ | |||
2896 | ||||
2897 | static | |||
2898 | cmsBool Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
2899 | { | |||
2900 | cmsPipeline* Lut = (cmsPipeline*) Ptr; | |||
2901 | cmsUInt32Number inputChan, outputChan; | |||
2902 | cmsStage *A = NULL((void*)0), *B = NULL((void*)0), *M = NULL((void*)0); | |||
2903 | cmsStage *Matrix = NULL((void*)0); | |||
2904 | cmsStage *CLUT = NULL((void*)0); | |||
2905 | cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0; | |||
2906 | cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos; | |||
2907 | ||||
2908 | ||||
2909 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
2910 | ||||
2911 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B)) | |||
2912 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &B, &Matrix, &M)) | |||
2913 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &CLUT, &A)) | |||
2914 | if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, | |||
2915 | cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &Matrix, &M, &CLUT, &A)) { | |||
2916 | cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE13, "LUT is not suitable to be saved as LutBToA"); | |||
2917 | return FALSE0; | |||
2918 | } | |||
2919 | ||||
2920 | inputChan = cmsPipelineInputChannels(Lut); | |||
2921 | outputChan = cmsPipelineOutputChannels(Lut); | |||
2922 | ||||
2923 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE0; | |||
2924 | if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE0; | |||
2925 | if (!_cmsWriteUInt16Number(io, 0)) return FALSE0; | |||
2926 | ||||
2927 | DirectoryPos = io ->Tell(io); | |||
2928 | ||||
2929 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2930 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2931 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2932 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2933 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
2934 | ||||
2935 | if (A != NULL((void*)0)) { | |||
2936 | ||||
2937 | offsetA = io ->Tell(io) - BaseOffset; | |||
2938 | if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE0; | |||
2939 | } | |||
2940 | ||||
2941 | if (CLUT != NULL((void*)0)) { | |||
2942 | offsetC = io ->Tell(io) - BaseOffset; | |||
2943 | if (!WriteCLUT(self, io, (Lut ->SaveAs8Bits ? 1U : 2U), CLUT)) return FALSE0; | |||
2944 | ||||
2945 | } | |||
2946 | if (M != NULL((void*)0)) { | |||
2947 | ||||
2948 | offsetM = io ->Tell(io) - BaseOffset; | |||
2949 | if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE0; | |||
2950 | } | |||
2951 | ||||
2952 | if (Matrix != NULL((void*)0)) { | |||
2953 | offsetMat = io ->Tell(io) - BaseOffset; | |||
2954 | if (!WriteMatrix(self, io, Matrix)) return FALSE0; | |||
2955 | } | |||
2956 | ||||
2957 | if (B != NULL((void*)0)) { | |||
2958 | ||||
2959 | offsetB = io ->Tell(io) - BaseOffset; | |||
2960 | if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE0; | |||
2961 | } | |||
2962 | ||||
2963 | CurrentPos = io ->Tell(io); | |||
2964 | ||||
2965 | if (!io ->Seek(io, DirectoryPos)) return FALSE0; | |||
2966 | ||||
2967 | if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE0; | |||
2968 | if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE0; | |||
2969 | if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE0; | |||
2970 | if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE0; | |||
2971 | if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE0; | |||
2972 | ||||
2973 | if (!io ->Seek(io, CurrentPos)) return FALSE0; | |||
2974 | ||||
2975 | return TRUE1; | |||
2976 | ||||
2977 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
2978 | } | |||
2979 | ||||
2980 | ||||
2981 | ||||
2982 | static | |||
2983 | void* Type_LUTB2A_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
2984 | { | |||
2985 | return (void*) cmsPipelineDup((cmsPipeline*) Ptr); | |||
2986 | ||||
2987 | cmsUNUSED_PARAMETER(n)((void)n); | |||
2988 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2989 | } | |||
2990 | ||||
2991 | static | |||
2992 | void Type_LUTB2A_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
2993 | { | |||
2994 | cmsPipelineFree((cmsPipeline*) Ptr); | |||
2995 | return; | |||
2996 | ||||
2997 | cmsUNUSED_PARAMETER(self)((void)self); | |||
2998 | } | |||
2999 | ||||
3000 | ||||
3001 | ||||
3002 | // ******************************************************************************** | |||
3003 | // Type cmsSigColorantTableType | |||
3004 | // ******************************************************************************** | |||
3005 | /* | |||
3006 | The purpose of this tag is to identify the colorants used in the profile by a | |||
3007 | unique name and set of XYZ or L*a*b* values to give the colorant an unambiguous | |||
3008 | value. The first colorant listed is the colorant of the first device channel of | |||
3009 | a lut tag. The second colorant listed is the colorant of the second device channel | |||
3010 | of a lut tag, and so on. | |||
3011 | */ | |||
3012 | ||||
3013 | static | |||
3014 | void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3015 | { | |||
3016 | cmsUInt32Number i, Count; | |||
3017 | cmsNAMEDCOLORLIST* List; | |||
3018 | char Name[34]; | |||
3019 | cmsUInt16Number PCS[3]; | |||
3020 | ||||
3021 | ||||
3022 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
3023 | ||||
3024 | if (Count > cmsMAXCHANNELS16) { | |||
3025 | cmsSignalError(self->ContextID, cmsERROR_RANGE2, "Too many colorants '%d'", Count); | |||
3026 | return NULL((void*)0); | |||
3027 | } | |||
3028 | ||||
3029 | List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", ""); | |||
3030 | if (List == NULL((void*)0)) | |||
3031 | return NULL((void*)0); | |||
3032 | ||||
3033 | for (i=0; i < Count; i++) { | |||
3034 | ||||
3035 | if (io ->Read(io, Name, 32, 1) != 1) goto Error; | |||
3036 | Name[32] = 0; | |||
3037 | ||||
3038 | if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; | |||
3039 | ||||
3040 | if (!cmsAppendNamedColor(List, Name, PCS, NULL((void*)0))) goto Error; | |||
3041 | ||||
3042 | } | |||
3043 | ||||
3044 | *nItems = 1; | |||
3045 | return List; | |||
3046 | ||||
3047 | Error: | |||
3048 | *nItems = 0; | |||
3049 | cmsFreeNamedColorList(List); | |||
3050 | return NULL((void*)0); | |||
3051 | ||||
3052 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
3053 | } | |||
3054 | ||||
3055 | ||||
3056 | ||||
3057 | // Saves a colorant table. It is using the named color structure for simplicity sake | |||
3058 | static | |||
3059 | cmsBool Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3060 | { | |||
3061 | cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; | |||
3062 | cmsUInt32Number i, nColors; | |||
3063 | ||||
3064 | nColors = cmsNamedColorCount(NamedColorList); | |||
3065 | ||||
3066 | if (!_cmsWriteUInt32Number(io, nColors)) return FALSE0; | |||
3067 | ||||
3068 | for (i=0; i < nColors; i++) { | |||
3069 | ||||
3070 | char root[cmsMAX_PATH256]; | |||
3071 | cmsUInt16Number PCS[3]; | |||
3072 | ||||
3073 | memset(root, 0, sizeof(root)); | |||
3074 | ||||
3075 | if (!cmsNamedColorInfo(NamedColorList, i, root, NULL((void*)0), NULL((void*)0), PCS, NULL((void*)0))) return 0; | |||
3076 | root[32] = 0; | |||
3077 | ||||
3078 | if (!io ->Write(io, 32, root)) return FALSE0; | |||
3079 | if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE0; | |||
3080 | } | |||
3081 | ||||
3082 | return TRUE1; | |||
3083 | ||||
3084 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3085 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3086 | } | |||
3087 | ||||
3088 | ||||
3089 | static | |||
3090 | void* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) | |||
3091 | { | |||
3092 | cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr; | |||
3093 | return (void*) cmsDupNamedColorList(nc); | |||
3094 | ||||
3095 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3096 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3097 | } | |||
3098 | ||||
3099 | ||||
3100 | static | |||
3101 | void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
3102 | { | |||
3103 | cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr); | |||
3104 | return; | |||
3105 | ||||
3106 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3107 | } | |||
3108 | ||||
3109 | ||||
3110 | // ******************************************************************************** | |||
3111 | // Type cmsSigNamedColor2Type | |||
3112 | // ******************************************************************************** | |||
3113 | // | |||
3114 | //The namedColor2Type is a count value and array of structures that provide color | |||
3115 | //coordinates for 7-bit ASCII color names. For each named color, a PCS and optional | |||
3116 | //device representation of the color are given. Both representations are 16-bit values. | |||
3117 | //The device representation corresponds to the header's 'color space of data' field. | |||
3118 | //This representation should be consistent with the 'number of device components' | |||
3119 | //field in the namedColor2Type. If this field is 0, device coordinates are not provided. | |||
3120 | //The PCS representation corresponds to the header's PCS field. The PCS representation | |||
3121 | //is always provided. Color names are fixed-length, 32-byte fields including null | |||
3122 | //termination. In order to maintain maximum portability, it is strongly recommended | |||
3123 | //that special characters of the 7-bit ASCII set not be used. | |||
3124 | ||||
3125 | static | |||
3126 | void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3127 | { | |||
3128 | ||||
3129 | cmsUInt32Number vendorFlag; // Bottom 16 bits for ICC use | |||
3130 | cmsUInt32Number count; // Count of named colors | |||
3131 | cmsUInt32Number nDeviceCoords; // Num of device coordinates | |||
3132 | char prefix[32]; // Prefix for each color name | |||
3133 | char suffix[32]; // Suffix for each color name | |||
3134 | cmsNAMEDCOLORLIST* v; | |||
3135 | cmsUInt32Number i; | |||
3136 | ||||
3137 | ||||
3138 | *nItems = 0; | |||
3139 | if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL((void*)0); | |||
3140 | if (!_cmsReadUInt32Number(io, &count)) return NULL((void*)0); | |||
3141 | if (!_cmsReadUInt32Number(io, &nDeviceCoords)) return NULL((void*)0); | |||
3142 | ||||
3143 | if (io -> Read(io, prefix, 32, 1) != 1) return NULL((void*)0); | |||
3144 | if (io -> Read(io, suffix, 32, 1) != 1) return NULL((void*)0); | |||
3145 | ||||
3146 | prefix[31] = suffix[31] = 0; | |||
3147 | ||||
3148 | v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix); | |||
3149 | if (v == NULL((void*)0)) { | |||
3150 | cmsSignalError(self->ContextID, cmsERROR_RANGE2, "Too many named colors '%d'", count); | |||
3151 | return NULL((void*)0); | |||
3152 | } | |||
3153 | ||||
3154 | if (nDeviceCoords > cmsMAXCHANNELS16) { | |||
3155 | cmsSignalError(self->ContextID, cmsERROR_RANGE2, "Too many device coordinates '%d'", nDeviceCoords); | |||
3156 | goto Error; | |||
3157 | } | |||
3158 | for (i=0; i < count; i++) { | |||
3159 | ||||
3160 | cmsUInt16Number PCS[3]; | |||
3161 | cmsUInt16Number Colorant[cmsMAXCHANNELS16]; | |||
3162 | char Root[33]; | |||
3163 | ||||
3164 | memset(Colorant, 0, sizeof(Colorant)); | |||
3165 | if (io -> Read(io, Root, 32, 1) != 1) goto Error; | |||
3166 | Root[32] = 0; // To prevent exploits | |||
3167 | ||||
3168 | if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error; | |||
3169 | if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error; | |||
3170 | ||||
3171 | if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error; | |||
3172 | } | |||
3173 | ||||
3174 | *nItems = 1; | |||
3175 | return (void*) v ; | |||
3176 | ||||
3177 | Error: | |||
3178 | cmsFreeNamedColorList(v); | |||
3179 | return NULL((void*)0); | |||
3180 | ||||
3181 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
3182 | } | |||
3183 | ||||
3184 | ||||
3185 | // Saves a named color list into a named color profile | |||
3186 | static | |||
3187 | cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3188 | { | |||
3189 | cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr; | |||
3190 | char prefix[33]; // Prefix for each color name | |||
3191 | char suffix[33]; // Suffix for each color name | |||
3192 | cmsUInt32Number i, nColors; | |||
3193 | ||||
3194 | nColors = cmsNamedColorCount(NamedColorList); | |||
3195 | ||||
3196 | if (!_cmsWriteUInt32Number(io, 0)) return FALSE0; | |||
3197 | if (!_cmsWriteUInt32Number(io, nColors)) return FALSE0; | |||
3198 | if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE0; | |||
3199 | ||||
3200 | strncpy(prefix, (const char*) NamedColorList->Prefix, 32); | |||
3201 | strncpy(suffix, (const char*) NamedColorList->Suffix, 32); | |||
3202 | ||||
3203 | suffix[32] = prefix[32] = 0; | |||
3204 | ||||
3205 | if (!io ->Write(io, 32, prefix)) return FALSE0; | |||
3206 | if (!io ->Write(io, 32, suffix)) return FALSE0; | |||
3207 | ||||
3208 | for (i=0; i < nColors; i++) { | |||
3209 | ||||
3210 | cmsUInt16Number PCS[3]; | |||
3211 | cmsUInt16Number Colorant[cmsMAXCHANNELS16]; | |||
3212 | char Root[cmsMAX_PATH256]; | |||
3213 | ||||
3214 | if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL((void*)0), NULL((void*)0), PCS, Colorant)) return 0; | |||
3215 | Root[32] = 0; | |||
3216 | if (!io ->Write(io, 32 , Root)) return FALSE0; | |||
3217 | if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE0; | |||
3218 | if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE0; | |||
3219 | } | |||
3220 | ||||
3221 | return TRUE1; | |||
3222 | ||||
3223 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3224 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3225 | } | |||
3226 | ||||
3227 | static | |||
3228 | void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) | |||
3229 | { | |||
3230 | cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr; | |||
3231 | ||||
3232 | return (void*) cmsDupNamedColorList(nc); | |||
3233 | ||||
3234 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3235 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3236 | } | |||
3237 | ||||
3238 | ||||
3239 | static | |||
3240 | void Type_NamedColor_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
3241 | { | |||
3242 | cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr); | |||
3243 | return; | |||
3244 | ||||
3245 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3246 | } | |||
3247 | ||||
3248 | ||||
3249 | // ******************************************************************************** | |||
3250 | // Type cmsSigProfileSequenceDescType | |||
3251 | // ******************************************************************************** | |||
3252 | ||||
3253 | // This type is an array of structures, each of which contains information from the | |||
3254 | // header fields and tags from the original profiles which were combined to create | |||
3255 | // the final profile. The order of the structures is the order in which the profiles | |||
3256 | // were combined and includes a structure for the final profile. This provides a | |||
3257 | // description of the profile sequence from source to destination, | |||
3258 | // typically used with the DeviceLink profile. | |||
3259 | ||||
3260 | static | |||
3261 | cmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag) | |||
3262 | { | |||
3263 | cmsTagTypeSignature BaseType; | |||
3264 | cmsUInt32Number nItems; | |||
3265 | ||||
3266 | BaseType = _cmsReadTypeBase(io); | |||
3267 | ||||
3268 | switch (BaseType) { | |||
3269 | ||||
3270 | case cmsSigTextType: | |||
3271 | if (*mlu) cmsMLUfree(*mlu); | |||
3272 | *mlu = (cmsMLU*)Type_Text_Read(self, io, &nItems, SizeOfTag); | |||
3273 | return (*mlu != NULL((void*)0)); | |||
3274 | ||||
3275 | case cmsSigTextDescriptionType: | |||
3276 | if (*mlu) cmsMLUfree(*mlu); | |||
3277 | *mlu = (cmsMLU*) Type_Text_Description_Read(self, io, &nItems, SizeOfTag); | |||
3278 | return (*mlu != NULL((void*)0)); | |||
3279 | ||||
3280 | /* | |||
3281 | TBD: Size is needed for MLU, and we have no idea on which is the available size | |||
3282 | */ | |||
3283 | ||||
3284 | case cmsSigMultiLocalizedUnicodeType: | |||
3285 | if (*mlu) cmsMLUfree(*mlu); | |||
3286 | *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, SizeOfTag); | |||
3287 | return (*mlu != NULL((void*)0)); | |||
3288 | ||||
3289 | default: return FALSE0; | |||
3290 | } | |||
3291 | } | |||
3292 | ||||
3293 | ||||
3294 | static | |||
3295 | void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3296 | { | |||
3297 | cmsSEQ* OutSeq; | |||
3298 | cmsUInt32Number i, Count; | |||
3299 | ||||
3300 | *nItems = 0; | |||
3301 | ||||
3302 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
3303 | ||||
3304 | if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL((void*)0); | |||
3305 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3306 | ||||
3307 | ||||
3308 | OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count); | |||
3309 | if (OutSeq == NULL((void*)0)) return NULL((void*)0); | |||
3310 | ||||
3311 | OutSeq ->n = Count; | |||
3312 | ||||
3313 | // Get structures as well | |||
3314 | ||||
3315 | for (i=0; i < Count; i++) { | |||
3316 | ||||
3317 | cmsPSEQDESC* sec = &OutSeq -> seq[i]; | |||
3318 | ||||
3319 | if (!_cmsReadUInt32Number(io, &sec ->deviceMfg)) goto Error; | |||
3320 | if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; | |||
3321 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3322 | ||||
3323 | if (!_cmsReadUInt32Number(io, &sec ->deviceModel)) goto Error; | |||
3324 | if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; | |||
3325 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3326 | ||||
3327 | if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error; | |||
3328 | if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error; | |||
3329 | SizeOfTag -= sizeof(cmsUInt64Number); | |||
3330 | ||||
3331 | if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error; | |||
3332 | if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error; | |||
3333 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3334 | ||||
3335 | if (!ReadEmbeddedText(self, io, &sec ->Manufacturer, SizeOfTag)) goto Error; | |||
3336 | if (!ReadEmbeddedText(self, io, &sec ->Model, SizeOfTag)) goto Error; | |||
3337 | } | |||
3338 | ||||
3339 | *nItems = 1; | |||
3340 | return OutSeq; | |||
3341 | ||||
3342 | Error: | |||
3343 | cmsFreeProfileSequenceDescription(OutSeq); | |||
3344 | return NULL((void*)0); | |||
3345 | } | |||
3346 | ||||
3347 | ||||
3348 | // Aux--Embed a text description type. It can be of type text description or multilocalized unicode | |||
3349 | // and it depends of the version number passed on cmsTagDescriptor structure instead of stack | |||
3350 | static | |||
3351 | cmsBool SaveDescription(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* Text) | |||
3352 | { | |||
3353 | if (self ->ICCVersion < 0x4000000) { | |||
3354 | ||||
3355 | if (!_cmsWriteTypeBase(io, cmsSigTextDescriptionType)) return FALSE0; | |||
3356 | return Type_Text_Description_Write(self, io, Text, 1); | |||
3357 | } | |||
3358 | else { | |||
3359 | if (!_cmsWriteTypeBase(io, cmsSigMultiLocalizedUnicodeType)) return FALSE0; | |||
3360 | return Type_MLU_Write(self, io, Text, 1); | |||
3361 | } | |||
3362 | } | |||
3363 | ||||
3364 | ||||
3365 | static | |||
3366 | cmsBool Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3367 | { | |||
3368 | cmsSEQ* Seq = (cmsSEQ*) Ptr; | |||
3369 | cmsUInt32Number i; | |||
3370 | ||||
3371 | if (!_cmsWriteUInt32Number(io, Seq->n)) return FALSE0; | |||
3372 | ||||
3373 | for (i=0; i < Seq ->n; i++) { | |||
3374 | ||||
3375 | cmsPSEQDESC* sec = &Seq -> seq[i]; | |||
3376 | ||||
3377 | if (!_cmsWriteUInt32Number(io, sec ->deviceMfg)) return FALSE0; | |||
3378 | if (!_cmsWriteUInt32Number(io, sec ->deviceModel)) return FALSE0; | |||
3379 | if (!_cmsWriteUInt64Number(io, &sec ->attributes)) return FALSE0; | |||
3380 | if (!_cmsWriteUInt32Number(io, sec ->technology)) return FALSE0; | |||
3381 | ||||
3382 | if (!SaveDescription(self, io, sec ->Manufacturer)) return FALSE0; | |||
3383 | if (!SaveDescription(self, io, sec ->Model)) return FALSE0; | |||
3384 | } | |||
3385 | ||||
3386 | return TRUE1; | |||
3387 | ||||
3388 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3389 | } | |||
3390 | ||||
3391 | ||||
3392 | static | |||
3393 | void* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) | |||
3394 | { | |||
3395 | return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr); | |||
3396 | ||||
3397 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3398 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3399 | } | |||
3400 | ||||
3401 | static | |||
3402 | void Type_ProfileSequenceDesc_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
3403 | { | |||
3404 | cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr); | |||
3405 | return; | |||
3406 | ||||
3407 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3408 | } | |||
3409 | ||||
3410 | ||||
3411 | // ******************************************************************************** | |||
3412 | // Type cmsSigProfileSequenceIdType | |||
3413 | // ******************************************************************************** | |||
3414 | /* | |||
3415 | In certain workflows using ICC Device Link Profiles, it is necessary to identify the | |||
3416 | original profiles that were combined to create the Device Link Profile. | |||
3417 | This type is an array of structures, each of which contains information for | |||
3418 | identification of a profile used in a sequence | |||
3419 | */ | |||
3420 | ||||
3421 | ||||
3422 | static | |||
3423 | cmsBool ReadSeqID(struct _cms_typehandler_struct* self, | |||
3424 | cmsIOHANDLER* io, | |||
3425 | void* Cargo, | |||
3426 | cmsUInt32Number n, | |||
3427 | cmsUInt32Number SizeOfTag) | |||
3428 | { | |||
3429 | cmsSEQ* OutSeq = (cmsSEQ*) Cargo; | |||
3430 | cmsPSEQDESC* seq = &OutSeq ->seq[n]; | |||
3431 | ||||
3432 | if (io -> Read(io, seq ->ProfileID.ID8, 16, 1) != 1) return FALSE0; | |||
3433 | if (!ReadEmbeddedText(self, io, &seq ->Description, SizeOfTag)) return FALSE0; | |||
3434 | ||||
3435 | return TRUE1; | |||
3436 | } | |||
3437 | ||||
3438 | ||||
3439 | ||||
3440 | static | |||
3441 | void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3442 | { | |||
3443 | cmsSEQ* OutSeq; | |||
3444 | cmsUInt32Number Count; | |||
3445 | cmsUInt32Number BaseOffset; | |||
3446 | ||||
3447 | *nItems = 0; | |||
3448 | ||||
3449 | // Get actual position as a basis for element offsets | |||
3450 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
3451 | ||||
3452 | // Get table count | |||
3453 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
3454 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3455 | ||||
3456 | // Allocate an empty structure | |||
3457 | OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count); | |||
3458 | if (OutSeq == NULL((void*)0)) return NULL((void*)0); | |||
3459 | ||||
3460 | ||||
3461 | // Read the position table | |||
3462 | if (!ReadPositionTable(self, io, Count, BaseOffset, OutSeq, ReadSeqID)) { | |||
3463 | ||||
3464 | cmsFreeProfileSequenceDescription(OutSeq); | |||
3465 | return NULL((void*)0); | |||
3466 | } | |||
3467 | ||||
3468 | // Success | |||
3469 | *nItems = 1; | |||
3470 | return OutSeq; | |||
3471 | ||||
3472 | } | |||
3473 | ||||
3474 | ||||
3475 | static | |||
3476 | cmsBool WriteSeqID(struct _cms_typehandler_struct* self, | |||
3477 | cmsIOHANDLER* io, | |||
3478 | void* Cargo, | |||
3479 | cmsUInt32Number n, | |||
3480 | cmsUInt32Number SizeOfTag) | |||
3481 | { | |||
3482 | cmsSEQ* Seq = (cmsSEQ*) Cargo; | |||
3483 | ||||
3484 | if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE0; | |||
3485 | ||||
3486 | // Store here the MLU | |||
3487 | if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE0; | |||
3488 | ||||
3489 | return TRUE1; | |||
3490 | ||||
3491 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
3492 | } | |||
3493 | ||||
3494 | static | |||
3495 | cmsBool Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3496 | { | |||
3497 | cmsSEQ* Seq = (cmsSEQ*) Ptr; | |||
3498 | cmsUInt32Number BaseOffset; | |||
3499 | ||||
3500 | // Keep the base offset | |||
3501 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
3502 | ||||
3503 | // This is the table count | |||
3504 | if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE0; | |||
3505 | ||||
3506 | // This is the position table and content | |||
3507 | if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE0; | |||
3508 | ||||
3509 | return TRUE1; | |||
3510 | ||||
3511 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3512 | } | |||
3513 | ||||
3514 | static | |||
3515 | void* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n) | |||
3516 | { | |||
3517 | return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr); | |||
3518 | ||||
3519 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3520 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3521 | } | |||
3522 | ||||
3523 | static | |||
3524 | void Type_ProfileSequenceId_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
3525 | { | |||
3526 | cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr); | |||
3527 | return; | |||
3528 | ||||
3529 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3530 | } | |||
3531 | ||||
3532 | ||||
3533 | // ******************************************************************************** | |||
3534 | // Type cmsSigUcrBgType | |||
3535 | // ******************************************************************************** | |||
3536 | /* | |||
3537 | This type contains curves representing the under color removal and black | |||
3538 | generation and a text string which is a general description of the method used | |||
3539 | for the ucr/bg. | |||
3540 | */ | |||
3541 | ||||
3542 | static | |||
3543 | void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3544 | { | |||
3545 | cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg)); | |||
3546 | cmsUInt32Number CountUcr, CountBg; | |||
3547 | char* ASCIIString; | |||
3548 | ||||
3549 | *nItems = 0; | |||
3550 | if (n == NULL((void*)0)) return NULL((void*)0); | |||
3551 | ||||
3552 | // First curve is Under color removal | |||
3553 | if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL((void*)0); | |||
3554 | if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL((void*)0); | |||
3555 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3556 | ||||
3557 | n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL((void*)0)); | |||
3558 | if (n ->Ucr == NULL((void*)0)) return NULL((void*)0); | |||
3559 | ||||
3560 | if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL((void*)0); | |||
3561 | if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL((void*)0); | |||
3562 | SizeOfTag -= CountUcr * sizeof(cmsUInt16Number); | |||
3563 | ||||
3564 | // Second curve is Black generation | |||
3565 | if (!_cmsReadUInt32Number(io, &CountBg)) return NULL((void*)0); | |||
3566 | if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL((void*)0); | |||
3567 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
3568 | ||||
3569 | n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL((void*)0)); | |||
3570 | if (n ->Bg == NULL((void*)0)) return NULL((void*)0); | |||
3571 | if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL((void*)0); | |||
3572 | if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL((void*)0); | |||
3573 | SizeOfTag -= CountBg * sizeof(cmsUInt16Number); | |||
3574 | if (SizeOfTag == UINT_MAX(2147483647 *2U +1U)) return NULL((void*)0); | |||
3575 | ||||
3576 | // Now comes the text. The length is specified by the tag size | |||
3577 | n ->Desc = cmsMLUalloc(self ->ContextID, 1); | |||
3578 | if (n ->Desc == NULL((void*)0)) return NULL((void*)0); | |||
3579 | ||||
3580 | ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1); | |||
3581 | if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL((void*)0); | |||
3582 | ASCIIString[SizeOfTag] = 0; | |||
3583 | cmsMLUsetASCII(n ->Desc, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", ASCIIString); | |||
3584 | _cmsFree(self ->ContextID, ASCIIString); | |||
3585 | ||||
3586 | *nItems = 1; | |||
3587 | return (void*) n; | |||
3588 | } | |||
3589 | ||||
3590 | static | |||
3591 | cmsBool Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3592 | { | |||
3593 | cmsUcrBg* Value = (cmsUcrBg*) Ptr; | |||
3594 | cmsUInt32Number TextSize; | |||
3595 | char* Text; | |||
3596 | ||||
3597 | // First curve is Under color removal | |||
3598 | if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE0; | |||
3599 | if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE0; | |||
3600 | ||||
3601 | // Then black generation | |||
3602 | if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE0; | |||
3603 | if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE0; | |||
3604 | ||||
3605 | // Now comes the text. The length is specified by the tag size | |||
3606 | TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", NULL((void*)0), 0); | |||
3607 | Text = (char*) _cmsMalloc(self ->ContextID, TextSize); | |||
3608 | if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage"\0\0", cmsNoCountry"\0\0", Text, TextSize) != TextSize) return FALSE0; | |||
3609 | ||||
3610 | if (!io ->Write(io, TextSize, Text)) return FALSE0; | |||
3611 | _cmsFree(self ->ContextID, Text); | |||
3612 | ||||
3613 | return TRUE1; | |||
3614 | ||||
3615 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3616 | } | |||
3617 | ||||
3618 | static | |||
3619 | void* Type_UcrBg_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
3620 | { | |||
3621 | cmsUcrBg* Src = (cmsUcrBg*) Ptr; | |||
3622 | cmsUcrBg* NewUcrBg = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg)); | |||
3623 | ||||
3624 | if (NewUcrBg == NULL((void*)0)) return NULL((void*)0); | |||
3625 | ||||
3626 | NewUcrBg ->Bg = cmsDupToneCurve(Src ->Bg); | |||
3627 | NewUcrBg ->Ucr = cmsDupToneCurve(Src ->Ucr); | |||
3628 | NewUcrBg ->Desc = cmsMLUdup(Src ->Desc); | |||
3629 | ||||
3630 | return (void*) NewUcrBg; | |||
3631 | ||||
3632 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3633 | } | |||
3634 | ||||
3635 | static | |||
3636 | void Type_UcrBg_Free(struct _cms_typehandler_struct* self, void *Ptr) | |||
3637 | { | |||
3638 | cmsUcrBg* Src = (cmsUcrBg*) Ptr; | |||
3639 | ||||
3640 | if (Src ->Ucr) cmsFreeToneCurve(Src ->Ucr); | |||
3641 | if (Src ->Bg) cmsFreeToneCurve(Src ->Bg); | |||
3642 | if (Src ->Desc) cmsMLUfree(Src ->Desc); | |||
3643 | ||||
3644 | _cmsFree(self ->ContextID, Ptr); | |||
3645 | } | |||
3646 | ||||
3647 | // ******************************************************************************** | |||
3648 | // Type cmsSigCrdInfoType | |||
3649 | // ******************************************************************************** | |||
3650 | ||||
3651 | /* | |||
3652 | This type contains the PostScript product name to which this profile corresponds | |||
3653 | and the names of the companion CRDs. Recall that a single profile can generate | |||
3654 | multiple CRDs. It is implemented as a MLU being the language code "PS" and then | |||
3655 | country varies for each element: | |||
3656 | ||||
3657 | nm: PostScript product name | |||
3658 | #0: Rendering intent 0 CRD name | |||
3659 | #1: Rendering intent 1 CRD name | |||
3660 | #2: Rendering intent 2 CRD name | |||
3661 | #3: Rendering intent 3 CRD name | |||
3662 | */ | |||
3663 | ||||
3664 | ||||
3665 | ||||
3666 | // Auxiliary, read an string specified as count + string | |||
3667 | static | |||
3668 | cmsBool ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section) | |||
3669 | { | |||
3670 | cmsUInt32Number Count; | |||
3671 | char* Text; | |||
3672 | ||||
3673 | if (*SizeOfTag < sizeof(cmsUInt32Number)) return FALSE0; | |||
3674 | ||||
3675 | if (!_cmsReadUInt32Number(io, &Count)) return FALSE0; | |||
3676 | ||||
3677 | if (Count > UINT_MAX(2147483647 *2U +1U) - sizeof(cmsUInt32Number)) return FALSE0; | |||
3678 | if (*SizeOfTag < Count + sizeof(cmsUInt32Number)) return FALSE0; | |||
3679 | ||||
3680 | Text = (char*) _cmsMalloc(self ->ContextID, Count+1); | |||
3681 | if (Text == NULL((void*)0)) return FALSE0; | |||
3682 | ||||
3683 | if (io ->Read(io, Text, sizeof(cmsUInt8Number), Count) != Count) { | |||
3684 | _cmsFree(self ->ContextID, Text); | |||
3685 | return FALSE0; | |||
3686 | } | |||
3687 | ||||
3688 | Text[Count] = 0; | |||
3689 | ||||
3690 | cmsMLUsetASCII(mlu, "PS", Section, Text); | |||
3691 | _cmsFree(self ->ContextID, Text); | |||
3692 | ||||
3693 | *SizeOfTag -= (Count + sizeof(cmsUInt32Number)); | |||
3694 | return TRUE1; | |||
3695 | } | |||
3696 | ||||
3697 | static | |||
3698 | cmsBool WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section) | |||
3699 | { | |||
3700 | cmsUInt32Number TextSize; | |||
3701 | char* Text; | |||
3702 | ||||
3703 | TextSize = cmsMLUgetASCII(mlu, "PS", Section, NULL((void*)0), 0); | |||
3704 | Text = (char*) _cmsMalloc(self ->ContextID, TextSize); | |||
3705 | ||||
3706 | if (!_cmsWriteUInt32Number(io, TextSize)) return FALSE0; | |||
3707 | ||||
3708 | if (cmsMLUgetASCII(mlu, "PS", Section, Text, TextSize) == 0) return FALSE0; | |||
3709 | ||||
3710 | if (!io ->Write(io, TextSize, Text)) return FALSE0; | |||
3711 | _cmsFree(self ->ContextID, Text); | |||
3712 | ||||
3713 | return TRUE1; | |||
3714 | } | |||
3715 | ||||
3716 | static | |||
3717 | void *Type_CrdInfo_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3718 | { | |||
3719 | cmsMLU* mlu = cmsMLUalloc(self ->ContextID, 5); | |||
3720 | ||||
3721 | *nItems = 0; | |||
3722 | if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "nm")) goto Error; | |||
3723 | if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#0")) goto Error; | |||
3724 | if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#1")) goto Error; | |||
3725 | if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#2")) goto Error; | |||
3726 | if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#3")) goto Error; | |||
3727 | ||||
3728 | *nItems = 1; | |||
3729 | return (void*) mlu; | |||
3730 | ||||
3731 | Error: | |||
3732 | cmsMLUfree(mlu); | |||
3733 | return NULL((void*)0); | |||
3734 | ||||
3735 | } | |||
3736 | ||||
3737 | static | |||
3738 | cmsBool Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3739 | { | |||
3740 | ||||
3741 | cmsMLU* mlu = (cmsMLU*) Ptr; | |||
3742 | ||||
3743 | if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error; | |||
3744 | if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error; | |||
3745 | if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error; | |||
3746 | if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error; | |||
3747 | if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error; | |||
3748 | ||||
3749 | return TRUE1; | |||
3750 | ||||
3751 | Error: | |||
3752 | return FALSE0; | |||
3753 | ||||
3754 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3755 | } | |||
3756 | ||||
3757 | ||||
3758 | static | |||
3759 | void* Type_CrdInfo_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
3760 | { | |||
3761 | return (void*) cmsMLUdup((cmsMLU*) Ptr); | |||
3762 | ||||
3763 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3764 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3765 | } | |||
3766 | ||||
3767 | static | |||
3768 | void Type_CrdInfo_Free(struct _cms_typehandler_struct* self, void *Ptr) | |||
3769 | { | |||
3770 | cmsMLUfree((cmsMLU*) Ptr); | |||
3771 | return; | |||
3772 | ||||
3773 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3774 | } | |||
3775 | ||||
3776 | // ******************************************************************************** | |||
3777 | // Type cmsSigScreeningType | |||
3778 | // ******************************************************************************** | |||
3779 | // | |||
3780 | //The screeningType describes various screening parameters including screen | |||
3781 | //frequency, screening angle, and spot shape. | |||
3782 | ||||
3783 | static | |||
3784 | void *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3785 | { | |||
3786 | cmsScreening* sc = NULL((void*)0); | |||
3787 | cmsUInt32Number i; | |||
3788 | ||||
3789 | sc = (cmsScreening*) _cmsMallocZero(self ->ContextID, sizeof(cmsScreening)); | |||
3790 | if (sc == NULL((void*)0)) return NULL((void*)0); | |||
3791 | ||||
3792 | *nItems = 0; | |||
3793 | ||||
3794 | if (!_cmsReadUInt32Number(io, &sc ->Flag)) goto Error; | |||
3795 | if (!_cmsReadUInt32Number(io, &sc ->nChannels)) goto Error; | |||
3796 | ||||
3797 | if (sc ->nChannels > cmsMAXCHANNELS16 - 1) | |||
3798 | sc ->nChannels = cmsMAXCHANNELS16 - 1; | |||
3799 | ||||
3800 | for (i=0; i < sc ->nChannels; i++) { | |||
3801 | ||||
3802 | if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].Frequency)) goto Error; | |||
3803 | if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].ScreenAngle)) goto Error; | |||
3804 | if (!_cmsReadUInt32Number(io, &sc ->Channels[i].SpotShape)) goto Error; | |||
3805 | } | |||
3806 | ||||
3807 | ||||
3808 | *nItems = 1; | |||
3809 | ||||
3810 | return (void*) sc; | |||
3811 | ||||
3812 | Error: | |||
3813 | if (sc != NULL((void*)0)) | |||
3814 | _cmsFree(self ->ContextID, sc); | |||
3815 | ||||
3816 | return NULL((void*)0); | |||
3817 | ||||
3818 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
3819 | } | |||
3820 | ||||
3821 | ||||
3822 | static | |||
3823 | cmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3824 | { | |||
3825 | cmsScreening* sc = (cmsScreening* ) Ptr; | |||
3826 | cmsUInt32Number i; | |||
3827 | ||||
3828 | if (!_cmsWriteUInt32Number(io, sc ->Flag)) return FALSE0; | |||
3829 | if (!_cmsWriteUInt32Number(io, sc ->nChannels)) return FALSE0; | |||
3830 | ||||
3831 | for (i=0; i < sc ->nChannels; i++) { | |||
3832 | ||||
3833 | if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].Frequency)) return FALSE0; | |||
3834 | if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].ScreenAngle)) return FALSE0; | |||
3835 | if (!_cmsWriteUInt32Number(io, sc ->Channels[i].SpotShape)) return FALSE0; | |||
3836 | } | |||
3837 | ||||
3838 | return TRUE1; | |||
3839 | ||||
3840 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3841 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3842 | } | |||
3843 | ||||
3844 | ||||
3845 | static | |||
3846 | void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
3847 | { | |||
3848 | return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening)); | |||
3849 | ||||
3850 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3851 | } | |||
3852 | ||||
3853 | ||||
3854 | static | |||
3855 | void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
3856 | { | |||
3857 | _cmsFree(self ->ContextID, Ptr); | |||
3858 | } | |||
3859 | ||||
3860 | // ******************************************************************************** | |||
3861 | // Type cmsSigViewingConditionsType | |||
3862 | // ******************************************************************************** | |||
3863 | // | |||
3864 | //This type represents a set of viewing condition parameters including: | |||
3865 | //CIE 'absolute' illuminant white point tristimulus values and CIE 'absolute' | |||
3866 | //surround tristimulus values. | |||
3867 | ||||
3868 | static | |||
3869 | void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
3870 | { | |||
3871 | cmsICCViewingConditions* vc = NULL((void*)0); | |||
3872 | ||||
3873 | vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions)); | |||
3874 | if (vc == NULL((void*)0)) return NULL((void*)0); | |||
3875 | ||||
3876 | *nItems = 0; | |||
3877 | ||||
3878 | if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error; | |||
3879 | if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error; | |||
3880 | if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error; | |||
3881 | ||||
3882 | *nItems = 1; | |||
3883 | ||||
3884 | return (void*) vc; | |||
3885 | ||||
3886 | Error: | |||
3887 | if (vc != NULL((void*)0)) | |||
3888 | _cmsFree(self ->ContextID, vc); | |||
3889 | ||||
3890 | return NULL((void*)0); | |||
3891 | ||||
3892 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
3893 | } | |||
3894 | ||||
3895 | ||||
3896 | static | |||
3897 | cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
3898 | { | |||
3899 | cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr; | |||
3900 | ||||
3901 | if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE0; | |||
3902 | if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE0; | |||
3903 | if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE0; | |||
3904 | ||||
3905 | return TRUE1; | |||
3906 | ||||
3907 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
3908 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3909 | } | |||
3910 | ||||
3911 | ||||
3912 | static | |||
3913 | void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
3914 | { | |||
3915 | return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsICCViewingConditions)); | |||
3916 | ||||
3917 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3918 | } | |||
3919 | ||||
3920 | ||||
3921 | static | |||
3922 | void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
3923 | { | |||
3924 | _cmsFree(self ->ContextID, Ptr); | |||
3925 | } | |||
3926 | ||||
3927 | ||||
3928 | // ******************************************************************************** | |||
3929 | // Type cmsSigMultiProcessElementType | |||
3930 | // ******************************************************************************** | |||
3931 | ||||
3932 | ||||
3933 | static | |||
3934 | void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
3935 | { | |||
3936 | return (void*) cmsStageDup((cmsStage*) Ptr); | |||
3937 | ||||
3938 | cmsUNUSED_PARAMETER(n)((void)n); | |||
3939 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3940 | } | |||
3941 | ||||
3942 | static | |||
3943 | void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr) | |||
3944 | { | |||
3945 | cmsStageFree((cmsStage*) Ptr); | |||
3946 | return; | |||
3947 | ||||
3948 | cmsUNUSED_PARAMETER(self)((void)self); | |||
3949 | } | |||
3950 | ||||
3951 | // Each curve is stored in one or more curve segments, with break-points specified between curve segments. | |||
3952 | // The first curve segment always starts at -Infinity, and the last curve segment always ends at +Infinity. The | |||
3953 | // first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be | |||
3954 | // specified either in terms of a formula, or by a sampled curve. | |||
3955 | ||||
3956 | ||||
3957 | // Read an embedded segmented curve | |||
3958 | static | |||
3959 | cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io) | |||
3960 | { | |||
3961 | cmsCurveSegSignature ElementSig; | |||
3962 | cmsUInt32Number i, j; | |||
3963 | cmsUInt16Number nSegments; | |||
3964 | cmsCurveSegment* Segments; | |||
3965 | cmsToneCurve* Curve; | |||
3966 | cmsFloat32Number PrevBreak = MINUS_INF(-1E22F); // - infinite | |||
3967 | ||||
3968 | // Take signature and channels for each element. | |||
3969 | if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL((void*)0); | |||
3970 | ||||
3971 | // That should be a segmented curve | |||
3972 | if (ElementSig != cmsSigSegmentedCurve) return NULL((void*)0); | |||
3973 | ||||
3974 | if (!_cmsReadUInt32Number(io, NULL((void*)0))) return NULL((void*)0); | |||
3975 | if (!_cmsReadUInt16Number(io, &nSegments)) return NULL((void*)0); | |||
3976 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) return NULL((void*)0); | |||
3977 | ||||
3978 | if (nSegments < 1) return NULL((void*)0); | |||
3979 | Segments = (cmsCurveSegment*) _cmsCalloc(self ->ContextID, nSegments, sizeof(cmsCurveSegment)); | |||
3980 | if (Segments == NULL((void*)0)) return NULL((void*)0); | |||
3981 | ||||
3982 | // Read breakpoints | |||
3983 | for (i=0; i < (cmsUInt32Number) nSegments - 1; i++) { | |||
3984 | ||||
3985 | Segments[i].x0 = PrevBreak; | |||
3986 | if (!_cmsReadFloat32Number(io, &Segments[i].x1)) goto Error; | |||
3987 | PrevBreak = Segments[i].x1; | |||
3988 | } | |||
3989 | ||||
3990 | Segments[nSegments-1].x0 = PrevBreak; | |||
3991 | Segments[nSegments-1].x1 = PLUS_INF(+1E22F); // A big cmsFloat32Number number | |||
3992 | ||||
3993 | // Read segments | |||
3994 | for (i=0; i < nSegments; i++) { | |||
3995 | ||||
3996 | if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) goto Error; | |||
3997 | if (!_cmsReadUInt32Number(io, NULL((void*)0))) goto Error; | |||
3998 | ||||
3999 | switch (ElementSig) { | |||
4000 | ||||
4001 | case cmsSigFormulaCurveSeg: { | |||
4002 | ||||
4003 | cmsUInt16Number Type; | |||
4004 | cmsUInt32Number ParamsByType[] = {4, 5, 5 }; | |||
4005 | ||||
4006 | if (!_cmsReadUInt16Number(io, &Type)) goto Error; | |||
4007 | if (!_cmsReadUInt16Number(io, NULL((void*)0))) goto Error; | |||
4008 | ||||
4009 | Segments[i].Type = Type + 6; | |||
4010 | if (Type > 2) goto Error; | |||
4011 | ||||
4012 | for (j=0; j < ParamsByType[Type]; j++) { | |||
4013 | ||||
4014 | cmsFloat32Number f; | |||
4015 | if (!_cmsReadFloat32Number(io, &f)) goto Error; | |||
4016 | Segments[i].Params[j] = f; | |||
4017 | } | |||
4018 | } | |||
4019 | break; | |||
4020 | ||||
4021 | ||||
4022 | case cmsSigSampledCurveSeg: { | |||
4023 | cmsUInt32Number Count; | |||
4024 | ||||
4025 | if (!_cmsReadUInt32Number(io, &Count)) goto Error; | |||
4026 | ||||
4027 | Segments[i].nGridPoints = Count; | |||
4028 | Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number)); | |||
4029 | if (Segments[i].SampledPoints == NULL((void*)0)) goto Error; | |||
4030 | ||||
4031 | for (j=0; j < Count; j++) { | |||
4032 | if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error; | |||
4033 | } | |||
4034 | } | |||
4035 | break; | |||
4036 | ||||
4037 | default: | |||
4038 | { | |||
4039 | char String[5]; | |||
4040 | ||||
4041 | _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); | |||
4042 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown curve element type '%s' found.", String); | |||
4043 | } | |||
4044 | goto Error; | |||
4045 | ||||
4046 | } | |||
4047 | } | |||
4048 | ||||
4049 | Curve = cmsBuildSegmentedToneCurve(self ->ContextID, nSegments, Segments); | |||
4050 | ||||
4051 | for (i=0; i < nSegments; i++) { | |||
4052 | if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints); | |||
4053 | } | |||
4054 | _cmsFree(self ->ContextID, Segments); | |||
4055 | return Curve; | |||
4056 | ||||
4057 | Error: | |||
4058 | if (Segments) { | |||
4059 | for (i=0; i < nSegments; i++) { | |||
4060 | if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints); | |||
4061 | } | |||
4062 | _cmsFree(self ->ContextID, Segments); | |||
4063 | } | |||
4064 | return NULL((void*)0); | |||
4065 | } | |||
4066 | ||||
4067 | ||||
4068 | static | |||
4069 | cmsBool ReadMPECurve(struct _cms_typehandler_struct* self, | |||
4070 | cmsIOHANDLER* io, | |||
4071 | void* Cargo, | |||
4072 | cmsUInt32Number n, | |||
4073 | cmsUInt32Number SizeOfTag) | |||
4074 | { | |||
4075 | cmsToneCurve** GammaTables = ( cmsToneCurve**) Cargo; | |||
4076 | ||||
4077 | GammaTables[n] = ReadSegmentedCurve(self, io); | |||
4078 | return (GammaTables[n] != NULL((void*)0)); | |||
4079 | ||||
4080 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4081 | } | |||
4082 | ||||
4083 | static | |||
4084 | void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
4085 | { | |||
4086 | cmsStage* mpe = NULL((void*)0); | |||
4087 | cmsUInt16Number InputChans, OutputChans; | |||
4088 | cmsUInt32Number i, BaseOffset; | |||
4089 | cmsToneCurve** GammaTables; | |||
4090 | ||||
4091 | *nItems = 0; | |||
4092 | ||||
4093 | // Get actual position as a basis for element offsets | |||
4094 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
4095 | ||||
4096 | if (!_cmsReadUInt16Number(io, &InputChans)) return NULL((void*)0); | |||
4097 | if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL((void*)0); | |||
4098 | ||||
4099 | if (InputChans != OutputChans) return NULL((void*)0); | |||
4100 | ||||
4101 | GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*)); | |||
4102 | if (GammaTables == NULL((void*)0)) return NULL((void*)0); | |||
4103 | ||||
4104 | if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) { | |||
4105 | ||||
4106 | mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables); | |||
4107 | } | |||
4108 | else { | |||
4109 | mpe = NULL((void*)0); | |||
4110 | } | |||
4111 | ||||
4112 | for (i=0; i < InputChans; i++) { | |||
4113 | if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]); | |||
4114 | } | |||
4115 | ||||
4116 | _cmsFree(self ->ContextID, GammaTables); | |||
4117 | *nItems = (mpe != NULL((void*)0)) ? 1U : 0; | |||
4118 | return mpe; | |||
4119 | ||||
4120 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4121 | } | |||
4122 | ||||
4123 | ||||
4124 | // Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY | |||
4125 | static | |||
4126 | cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g) | |||
4127 | { | |||
4128 | cmsUInt32Number i, j; | |||
4129 | cmsCurveSegment* Segments = g ->Segments; | |||
4130 | cmsUInt32Number nSegments = g ->nSegments; | |||
4131 | ||||
4132 | if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error; | |||
4133 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; | |||
4134 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error; | |||
4135 | if (!_cmsWriteUInt16Number(io, 0)) goto Error; | |||
4136 | ||||
4137 | // Write the break-points | |||
4138 | for (i=0; i < nSegments - 1; i++) { | |||
4139 | if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error; | |||
4140 | } | |||
4141 | ||||
4142 | // Write the segments | |||
4143 | for (i=0; i < g ->nSegments; i++) { | |||
4144 | ||||
4145 | cmsCurveSegment* ActualSeg = Segments + i; | |||
4146 | ||||
4147 | if (ActualSeg -> Type == 0) { | |||
4148 | ||||
4149 | // This is a sampled curve | |||
4150 | if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigSampledCurveSeg)) goto Error; | |||
4151 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; | |||
4152 | if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints)) goto Error; | |||
4153 | ||||
4154 | for (j=0; j < g ->Segments[i].nGridPoints; j++) { | |||
4155 | if (!_cmsWriteFloat32Number(io, ActualSeg -> SampledPoints[j])) goto Error; | |||
4156 | } | |||
4157 | ||||
4158 | } | |||
4159 | else { | |||
4160 | int Type; | |||
4161 | cmsUInt32Number ParamsByType[] = { 4, 5, 5 }; | |||
4162 | ||||
4163 | // This is a formula-based | |||
4164 | if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigFormulaCurveSeg)) goto Error; | |||
4165 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; | |||
4166 | ||||
4167 | // We only allow 1, 2 and 3 as types | |||
4168 | Type = ActualSeg ->Type - 6; | |||
4169 | if (Type > 2 || Type < 0) goto Error; | |||
4170 | ||||
4171 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Type)) goto Error; | |||
4172 | if (!_cmsWriteUInt16Number(io, 0)) goto Error; | |||
4173 | ||||
4174 | for (j=0; j < ParamsByType[Type]; j++) { | |||
4175 | if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) ActualSeg ->Params[j])) goto Error; | |||
4176 | } | |||
4177 | } | |||
4178 | ||||
4179 | // It seems there is no need to align. Code is here, and for safety commented out | |||
4180 | // if (!_cmsWriteAlignment(io)) goto Error; | |||
4181 | } | |||
4182 | ||||
4183 | return TRUE1; | |||
4184 | ||||
4185 | Error: | |||
4186 | return FALSE0; | |||
4187 | } | |||
4188 | ||||
4189 | ||||
4190 | static | |||
4191 | cmsBool WriteMPECurve(struct _cms_typehandler_struct* self, | |||
4192 | cmsIOHANDLER* io, | |||
4193 | void* Cargo, | |||
4194 | cmsUInt32Number n, | |||
4195 | cmsUInt32Number SizeOfTag) | |||
4196 | { | |||
4197 | _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) Cargo; | |||
4198 | ||||
4199 | return WriteSegmentedCurve(io, Curves ->TheCurves[n]); | |||
4200 | ||||
4201 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4202 | cmsUNUSED_PARAMETER(self)((void)self); | |||
4203 | } | |||
4204 | ||||
4205 | // Write a curve, checking first for validity | |||
4206 | static | |||
4207 | cmsBool Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
4208 | { | |||
4209 | cmsUInt32Number BaseOffset; | |||
4210 | cmsStage* mpe = (cmsStage*) Ptr; | |||
4211 | _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data; | |||
4212 | ||||
4213 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
4214 | ||||
4215 | // Write the header. Since those are curves, input and output channels are same | |||
4216 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE0; | |||
4217 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE0; | |||
4218 | ||||
4219 | if (!WritePositionTable(self, io, 0, | |||
4220 | mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE0; | |||
4221 | ||||
4222 | ||||
4223 | return TRUE1; | |||
4224 | ||||
4225 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
4226 | } | |||
4227 | ||||
4228 | ||||
4229 | ||||
4230 | // The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the | |||
4231 | // matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array | |||
4232 | // is organized as follows: | |||
4233 | // array = [e11, e12, ..., e1P, e21, e22, ..., e2P, ..., eQ1, eQ2, ..., eQP, e1, e2, ..., eQ] | |||
4234 | ||||
4235 | static | |||
4236 | void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
4237 | { | |||
4238 | cmsStage* mpe; | |||
4239 | cmsUInt16Number InputChans, OutputChans; | |||
4240 | cmsUInt32Number nElems, i; | |||
4241 | cmsFloat64Number* Matrix; | |||
4242 | cmsFloat64Number* Offsets; | |||
4243 | ||||
4244 | if (!_cmsReadUInt16Number(io, &InputChans)) return NULL((void*)0); | |||
4245 | if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL((void*)0); | |||
4246 | ||||
4247 | ||||
4248 | // Input and output chans may be ANY (up to 0xffff), | |||
4249 | // but we choose to limit to 16 channels for now | |||
4250 | if (InputChans >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
4251 | if (OutputChans >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
4252 | ||||
4253 | nElems = (cmsUInt32Number) InputChans * OutputChans; | |||
4254 | ||||
4255 | Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number)); | |||
4256 | if (Matrix == NULL((void*)0)) return NULL((void*)0); | |||
4257 | ||||
4258 | Offsets = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, OutputChans, sizeof(cmsFloat64Number)); | |||
4259 | if (Offsets == NULL((void*)0)) { | |||
4260 | ||||
4261 | _cmsFree(self ->ContextID, Matrix); | |||
4262 | return NULL((void*)0); | |||
4263 | } | |||
4264 | ||||
4265 | for (i=0; i < nElems; i++) { | |||
4266 | ||||
4267 | cmsFloat32Number v; | |||
4268 | ||||
4269 | if (!_cmsReadFloat32Number(io, &v)) { | |||
4270 | _cmsFree(self ->ContextID, Matrix); | |||
4271 | _cmsFree(self ->ContextID, Offsets); | |||
4272 | return NULL((void*)0); | |||
4273 | } | |||
4274 | Matrix[i] = v; | |||
4275 | } | |||
4276 | ||||
4277 | ||||
4278 | for (i=0; i < OutputChans; i++) { | |||
4279 | ||||
4280 | cmsFloat32Number v; | |||
4281 | ||||
4282 | if (!_cmsReadFloat32Number(io, &v)) { | |||
4283 | _cmsFree(self ->ContextID, Matrix); | |||
4284 | _cmsFree(self ->ContextID, Offsets); | |||
4285 | return NULL((void*)0); | |||
4286 | } | |||
4287 | Offsets[i] = v; | |||
4288 | } | |||
4289 | ||||
4290 | ||||
4291 | mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets); | |||
4292 | _cmsFree(self ->ContextID, Matrix); | |||
4293 | _cmsFree(self ->ContextID, Offsets); | |||
4294 | ||||
4295 | *nItems = 1; | |||
4296 | ||||
4297 | return mpe; | |||
4298 | ||||
4299 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4300 | } | |||
4301 | ||||
4302 | static | |||
4303 | cmsBool Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
4304 | { | |||
4305 | cmsUInt32Number i, nElems; | |||
4306 | cmsStage* mpe = (cmsStage*) Ptr; | |||
4307 | _cmsStageMatrixData* Matrix = (_cmsStageMatrixData*) mpe ->Data; | |||
4308 | ||||
4309 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE0; | |||
4310 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE0; | |||
4311 | ||||
4312 | nElems = mpe ->InputChannels * mpe ->OutputChannels; | |||
4313 | ||||
4314 | for (i=0; i < nElems; i++) { | |||
4315 | if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Double[i])) return FALSE0; | |||
4316 | } | |||
4317 | ||||
4318 | ||||
4319 | for (i=0; i < mpe ->OutputChannels; i++) { | |||
4320 | ||||
4321 | if (Matrix ->Offset == NULL((void*)0)) { | |||
4322 | ||||
4323 | if (!_cmsWriteFloat32Number(io, 0)) return FALSE0; | |||
4324 | } | |||
4325 | else { | |||
4326 | if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Offset[i])) return FALSE0; | |||
4327 | } | |||
4328 | } | |||
4329 | ||||
4330 | return TRUE1; | |||
4331 | ||||
4332 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
4333 | cmsUNUSED_PARAMETER(self)((void)self); | |||
4334 | } | |||
4335 | ||||
4336 | ||||
4337 | ||||
4338 | static | |||
4339 | void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
4340 | { | |||
4341 | cmsStage* mpe = NULL((void*)0); | |||
4342 | cmsUInt16Number InputChans, OutputChans; | |||
4343 | cmsUInt8Number Dimensions8[16]; | |||
4344 | cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS15]; | |||
4345 | _cmsStageCLutData* clut; | |||
4346 | ||||
4347 | if (!_cmsReadUInt16Number(io, &InputChans)) return NULL((void*)0); | |||
4348 | if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL((void*)0); | |||
4349 | ||||
4350 | if (InputChans == 0) goto Error; | |||
4351 | if (OutputChans == 0) goto Error; | |||
4352 | ||||
4353 | if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16) | |||
4354 | goto Error; | |||
4355 | ||||
4356 | // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number | |||
4357 | nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS15 ? (cmsUInt32Number) MAX_INPUT_DIMENSIONS15 : InputChans; | |||
4358 | ||||
4359 | for (i = 0; i < nMaxGrids; i++) { | |||
4360 | if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least | |||
4361 | GridPoints[i] = (cmsUInt32Number)Dimensions8[i]; | |||
4362 | } | |||
4363 | ||||
4364 | // Allocate the true CLUT | |||
4365 | mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL((void*)0)); | |||
4366 | if (mpe == NULL((void*)0)) goto Error; | |||
4367 | ||||
4368 | // Read and sanitize the data | |||
4369 | clut = (_cmsStageCLutData*) mpe ->Data; | |||
4370 | for (i=0; i < clut ->nEntries; i++) { | |||
4371 | ||||
4372 | if (!_cmsReadFloat32Number(io, &clut->Tab.TFloat[i])) goto Error; | |||
4373 | } | |||
4374 | ||||
4375 | *nItems = 1; | |||
4376 | return mpe; | |||
4377 | ||||
4378 | Error: | |||
4379 | *nItems = 0; | |||
4380 | if (mpe != NULL((void*)0)) cmsStageFree(mpe); | |||
4381 | return NULL((void*)0); | |||
4382 | ||||
4383 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4384 | } | |||
4385 | ||||
4386 | // Write a CLUT in floating point | |||
4387 | static | |||
4388 | cmsBool Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
4389 | { | |||
4390 | cmsUInt8Number Dimensions8[16]; // 16 because the spec says 16 and not max number of channels | |||
4391 | cmsUInt32Number i; | |||
4392 | cmsStage* mpe = (cmsStage*) Ptr; | |||
4393 | _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data; | |||
4394 | ||||
4395 | // Check for maximum number of channels supported by lcms | |||
4396 | if (mpe -> InputChannels > MAX_INPUT_DIMENSIONS15) return FALSE0; | |||
4397 | ||||
4398 | // Only floats are supported in MPE | |||
4399 | if (clut ->HasFloatValues == FALSE0) return FALSE0; | |||
4400 | ||||
4401 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE0; | |||
4402 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE0; | |||
4403 | ||||
4404 | memset(Dimensions8, 0, sizeof(Dimensions8)); | |||
4405 | ||||
4406 | for (i=0; i < mpe ->InputChannels; i++) | |||
4407 | Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i]; | |||
4408 | ||||
4409 | if (!io ->Write(io, 16, Dimensions8)) return FALSE0; | |||
4410 | ||||
4411 | for (i=0; i < clut ->nEntries; i++) { | |||
4412 | ||||
4413 | if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE0; | |||
4414 | } | |||
4415 | ||||
4416 | return TRUE1; | |||
4417 | ||||
4418 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
4419 | cmsUNUSED_PARAMETER(self)((void)self); | |||
4420 | } | |||
4421 | ||||
4422 | ||||
4423 | ||||
4424 | // This is the list of built-in MPE types | |||
4425 | static _cmsTagTypeLinkedList SupportedMPEtypes[] = { | |||
4426 | ||||
4427 | {{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), 0 }, &SupportedMPEtypes[1] }, // Ignore those elements for now | |||
4428 | {{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), 0 }, &SupportedMPEtypes[2] }, // (That's what the spec says) | |||
4429 | ||||
4430 | {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCurveSetElemType, MPEcurve){ ((cmsTagTypeSignature) cmsSigCurveSetElemType), Type_MPEcurve_Read , Type_MPEcurve_Write, GenericMPEdup, GenericMPEfree, ((void* )0), 0 }, &SupportedMPEtypes[3] }, | |||
4431 | {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigMatrixElemType, MPEmatrix){ ((cmsTagTypeSignature) cmsSigMatrixElemType), Type_MPEmatrix_Read , Type_MPEmatrix_Write, GenericMPEdup, GenericMPEfree, ((void *)0), 0 }, &SupportedMPEtypes[4] }, | |||
4432 | {TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType, MPEclut){ ((cmsTagTypeSignature) cmsSigCLutElemType), Type_MPEclut_Read , Type_MPEclut_Write, GenericMPEdup, GenericMPEfree, ((void*) 0), 0 }, NULL((void*)0) }, | |||
4433 | }; | |||
4434 | ||||
4435 | _cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL((void*)0) }; | |||
4436 | ||||
4437 | static | |||
4438 | cmsBool ReadMPEElem(struct _cms_typehandler_struct* self, | |||
4439 | cmsIOHANDLER* io, | |||
4440 | void* Cargo, | |||
4441 | cmsUInt32Number n, | |||
4442 | cmsUInt32Number SizeOfTag) | |||
4443 | { | |||
4444 | cmsStageSignature ElementSig; | |||
4445 | cmsTagTypeHandler* TypeHandler; | |||
4446 | cmsUInt32Number nItems; | |||
4447 | cmsPipeline *NewLUT = (cmsPipeline *) Cargo; | |||
4448 | _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin); | |||
4449 | ||||
4450 | ||||
4451 | // Take signature and channels for each element. | |||
4452 | if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE0; | |||
4453 | ||||
4454 | // The reserved placeholder | |||
4455 | if (!_cmsReadUInt32Number(io, NULL((void*)0))) return FALSE0; | |||
4456 | ||||
4457 | // Read diverse MPE types | |||
4458 | TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes); | |||
4459 | if (TypeHandler == NULL((void*)0)) { | |||
4460 | ||||
4461 | char String[5]; | |||
4462 | ||||
4463 | _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); | |||
4464 | ||||
4465 | // An unknown element was found. | |||
4466 | cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown MPE type '%s' found.", String); | |||
4467 | return FALSE0; | |||
4468 | } | |||
4469 | ||||
4470 | // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType) | |||
4471 | // Read the MPE. No size is given | |||
4472 | if (TypeHandler ->ReadPtr != NULL((void*)0)) { | |||
4473 | ||||
4474 | // This is a real element which should be read and processed | |||
4475 | if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag))) | |||
4476 | return FALSE0; | |||
4477 | } | |||
4478 | ||||
4479 | return TRUE1; | |||
4480 | ||||
4481 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4482 | cmsUNUSED_PARAMETER(n)((void)n); | |||
4483 | } | |||
4484 | ||||
4485 | ||||
4486 | // This is the main dispatcher for MPE | |||
4487 | static | |||
4488 | void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
4489 | { | |||
4490 | cmsUInt16Number InputChans, OutputChans; | |||
4491 | cmsUInt32Number ElementCount; | |||
4492 | cmsPipeline *NewLUT = NULL((void*)0); | |||
4493 | cmsUInt32Number BaseOffset; | |||
4494 | ||||
4495 | // Get actual position as a basis for element offsets | |||
4496 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
4497 | ||||
4498 | // Read channels and element count | |||
4499 | if (!_cmsReadUInt16Number(io, &InputChans)) return NULL((void*)0); | |||
4500 | if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL((void*)0); | |||
4501 | ||||
4502 | if (InputChans == 0 || InputChans >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
4503 | if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS16) return NULL((void*)0); | |||
4504 | ||||
4505 | // Allocates an empty LUT | |||
4506 | NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans); | |||
4507 | if (NewLUT == NULL((void*)0)) return NULL((void*)0); | |||
4508 | ||||
4509 | if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error; | |||
4510 | if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error; | |||
4511 | ||||
4512 | // Check channel count | |||
4513 | if (InputChans != NewLUT->InputChannels || | |||
4514 | OutputChans != NewLUT->OutputChannels) goto Error; | |||
4515 | ||||
4516 | // Success | |||
4517 | *nItems = 1; | |||
4518 | return NewLUT; | |||
4519 | ||||
4520 | // Error | |||
4521 | Error: | |||
4522 | if (NewLUT != NULL((void*)0)) cmsPipelineFree(NewLUT); | |||
4523 | *nItems = 0; | |||
4524 | return NULL((void*)0); | |||
4525 | ||||
4526 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4527 | } | |||
4528 | ||||
4529 | ||||
4530 | ||||
4531 | // This one is a liitle bit more complex, so we don't use position tables this time. | |||
4532 | static | |||
4533 | cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
4534 | { | |||
4535 | cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos; | |||
4536 | cmsUInt32Number inputChan, outputChan; | |||
4537 | cmsUInt32Number ElemCount; | |||
4538 | cmsUInt32Number *ElementOffsets = NULL((void*)0), *ElementSizes = NULL((void*)0), Before; | |||
4539 | cmsStageSignature ElementSig; | |||
4540 | cmsPipeline* Lut = (cmsPipeline*) Ptr; | |||
4541 | cmsStage* Elem = Lut ->Elements; | |||
4542 | cmsTagTypeHandler* TypeHandler; | |||
4543 | _cmsTagTypePluginChunkType* MPETypePluginChunk = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin); | |||
4544 | ||||
4545 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
4546 | ||||
4547 | inputChan = cmsPipelineInputChannels(Lut); | |||
4548 | outputChan = cmsPipelineOutputChannels(Lut); | |||
4549 | ElemCount = cmsPipelineStageCount(Lut); | |||
4550 | ||||
4551 | ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number)); | |||
4552 | if (ElementOffsets == NULL((void*)0)) goto Error; | |||
4553 | ||||
4554 | ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number)); | |||
4555 | if (ElementSizes == NULL((void*)0)) goto Error; | |||
4556 | ||||
4557 | // Write the head | |||
4558 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) inputChan)) goto Error; | |||
4559 | if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) outputChan)) goto Error; | |||
4560 | if (!_cmsWriteUInt32Number(io, (cmsUInt16Number) ElemCount)) goto Error; | |||
4561 | ||||
4562 | DirectoryPos = io ->Tell(io); | |||
4563 | ||||
4564 | // Write a fake directory to be filled latter on | |||
4565 | for (i=0; i < ElemCount; i++) { | |||
4566 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; // Offset | |||
4567 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; // size | |||
4568 | } | |||
4569 | ||||
4570 | // Write each single tag. Keep track of the size as well. | |||
4571 | for (i=0; i < ElemCount; i++) { | |||
4572 | ||||
4573 | ElementOffsets[i] = io ->Tell(io) - BaseOffset; | |||
4574 | ||||
4575 | ElementSig = Elem ->Type; | |||
4576 | ||||
4577 | TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes); | |||
4578 | if (TypeHandler == NULL((void*)0)) { | |||
4579 | ||||
4580 | char String[5]; | |||
4581 | ||||
4582 | _cmsTagSignature2String(String, (cmsTagSignature) ElementSig); | |||
4583 | ||||
4584 | // An unknown element was found. | |||
4585 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Found unknown MPE type '%s'", String); | |||
4586 | goto Error; | |||
4587 | } | |||
4588 | ||||
4589 | if (!_cmsWriteUInt32Number(io, ElementSig)) goto Error; | |||
4590 | if (!_cmsWriteUInt32Number(io, 0)) goto Error; | |||
4591 | Before = io ->Tell(io); | |||
4592 | if (!TypeHandler ->WritePtr(self, io, Elem, 1)) goto Error; | |||
4593 | if (!_cmsWriteAlignment(io)) goto Error; | |||
4594 | ||||
4595 | ElementSizes[i] = io ->Tell(io) - Before; | |||
4596 | ||||
4597 | Elem = Elem ->Next; | |||
4598 | } | |||
4599 | ||||
4600 | // Write the directory | |||
4601 | CurrentPos = io ->Tell(io); | |||
4602 | ||||
4603 | if (!io ->Seek(io, DirectoryPos)) goto Error; | |||
4604 | ||||
4605 | for (i=0; i < ElemCount; i++) { | |||
4606 | if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error; | |||
4607 | if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error; | |||
4608 | } | |||
4609 | ||||
4610 | if (!io ->Seek(io, CurrentPos)) goto Error; | |||
4611 | ||||
4612 | if (ElementOffsets != NULL((void*)0)) _cmsFree(self ->ContextID, ElementOffsets); | |||
4613 | if (ElementSizes != NULL((void*)0)) _cmsFree(self ->ContextID, ElementSizes); | |||
4614 | return TRUE1; | |||
4615 | ||||
4616 | Error: | |||
4617 | if (ElementOffsets != NULL((void*)0)) _cmsFree(self ->ContextID, ElementOffsets); | |||
4618 | if (ElementSizes != NULL((void*)0)) _cmsFree(self ->ContextID, ElementSizes); | |||
4619 | return FALSE0; | |||
4620 | ||||
4621 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
4622 | } | |||
4623 | ||||
4624 | ||||
4625 | static | |||
4626 | void* Type_MPE_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
4627 | { | |||
4628 | return (void*) cmsPipelineDup((cmsPipeline*) Ptr); | |||
4629 | ||||
4630 | cmsUNUSED_PARAMETER(n)((void)n); | |||
4631 | cmsUNUSED_PARAMETER(self)((void)self); | |||
4632 | } | |||
4633 | ||||
4634 | static | |||
4635 | void Type_MPE_Free(struct _cms_typehandler_struct* self, void *Ptr) | |||
4636 | { | |||
4637 | cmsPipelineFree((cmsPipeline*) Ptr); | |||
4638 | return; | |||
4639 | ||||
4640 | cmsUNUSED_PARAMETER(self)((void)self); | |||
4641 | } | |||
4642 | ||||
4643 | ||||
4644 | // ******************************************************************************** | |||
4645 | // Type cmsSigVcgtType | |||
4646 | // ******************************************************************************** | |||
4647 | ||||
4648 | ||||
4649 | #define cmsVideoCardGammaTableType0 0 | |||
4650 | #define cmsVideoCardGammaFormulaType1 1 | |||
4651 | ||||
4652 | // Used internally | |||
4653 | typedef struct { | |||
4654 | double Gamma; | |||
4655 | double Min; | |||
4656 | double Max; | |||
4657 | } _cmsVCGTGAMMA; | |||
4658 | ||||
4659 | ||||
4660 | static | |||
4661 | void *Type_vcgt_Read(struct _cms_typehandler_struct* self, | |||
4662 | cmsIOHANDLER* io, | |||
4663 | cmsUInt32Number* nItems, | |||
4664 | cmsUInt32Number SizeOfTag) | |||
4665 | { | |||
4666 | cmsUInt32Number TagType, n, i; | |||
4667 | cmsToneCurve** Curves; | |||
4668 | ||||
4669 | *nItems = 0; | |||
4670 | ||||
4671 | // Read tag type | |||
4672 | if (!_cmsReadUInt32Number(io, &TagType)) return NULL((void*)0); | |||
4673 | ||||
4674 | // Allocate space for the array | |||
4675 | Curves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*)); | |||
4676 | if (Curves == NULL((void*)0)) return NULL((void*)0); | |||
4677 | ||||
4678 | // There are two possible flavors | |||
4679 | switch (TagType) { | |||
4680 | ||||
4681 | // Gamma is stored as a table | |||
4682 | case cmsVideoCardGammaTableType0: | |||
4683 | { | |||
4684 | cmsUInt16Number nChannels, nElems, nBytes; | |||
4685 | ||||
4686 | // Check channel count, which should be 3 (we don't support monochrome this time) | |||
4687 | if (!_cmsReadUInt16Number(io, &nChannels)) goto Error; | |||
4688 | ||||
4689 | if (nChannels != 3) { | |||
4690 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unsupported number of channels for VCGT '%d'", nChannels); | |||
4691 | goto Error; | |||
4692 | } | |||
4693 | ||||
4694 | // Get Table element count and bytes per element | |||
4695 | if (!_cmsReadUInt16Number(io, &nElems)) goto Error; | |||
4696 | if (!_cmsReadUInt16Number(io, &nBytes)) goto Error; | |||
4697 | ||||
4698 | // Adobe's quirk fixup. Fixing broken profiles... | |||
4699 | if (nElems == 256 && nBytes == 1 && SizeOfTag == 1576) | |||
4700 | nBytes = 2; | |||
4701 | ||||
4702 | ||||
4703 | // Populate tone curves | |||
4704 | for (n=0; n < 3; n++) { | |||
4705 | ||||
4706 | Curves[n] = cmsBuildTabulatedToneCurve16(self ->ContextID, nElems, NULL((void*)0)); | |||
4707 | if (Curves[n] == NULL((void*)0)) goto Error; | |||
4708 | ||||
4709 | // On depending on byte depth | |||
4710 | switch (nBytes) { | |||
4711 | ||||
4712 | // One byte, 0..255 | |||
4713 | case 1: | |||
4714 | for (i=0; i < nElems; i++) { | |||
4715 | ||||
4716 | cmsUInt8Number v; | |||
4717 | ||||
4718 | if (!_cmsReadUInt8Number(io, &v)) goto Error; | |||
4719 | Curves[n] ->Table16[i] = FROM_8_TO_16(v)(cmsUInt16Number) ((((cmsUInt16Number) (v)) << 8)|(v)); | |||
4720 | } | |||
4721 | break; | |||
4722 | ||||
4723 | // One word 0..65535 | |||
4724 | case 2: | |||
4725 | if (!_cmsReadUInt16Array(io, nElems, Curves[n]->Table16)) goto Error; | |||
4726 | break; | |||
4727 | ||||
4728 | // Unsupported | |||
4729 | default: | |||
4730 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unsupported bit depth for VCGT '%d'", nBytes * 8); | |||
4731 | goto Error; | |||
4732 | } | |||
4733 | } // For all 3 channels | |||
4734 | } | |||
4735 | break; | |||
4736 | ||||
4737 | // In this case, gamma is stored as a formula | |||
4738 | case cmsVideoCardGammaFormulaType1: | |||
4739 | { | |||
4740 | _cmsVCGTGAMMA Colorant[3]; | |||
4741 | ||||
4742 | // Populate tone curves | |||
4743 | for (n=0; n < 3; n++) { | |||
4744 | ||||
4745 | double Params[10]; | |||
4746 | ||||
4747 | if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error; | |||
4748 | if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error; | |||
4749 | if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error; | |||
4750 | ||||
4751 | // Parametric curve type 5 is: | |||
4752 | // Y = (aX + b)^Gamma + e | X >= d | |||
4753 | // Y = cX + f | X < d | |||
4754 | ||||
4755 | // vcgt formula is: | |||
4756 | // Y = (Max - Min) * (X ^ Gamma) + Min | |||
4757 | ||||
4758 | // So, the translation is | |||
4759 | // a = (Max - Min) ^ ( 1 / Gamma) | |||
4760 | // e = Min | |||
4761 | // b=c=d=f=0 | |||
4762 | ||||
4763 | Params[0] = Colorant[n].Gamma; | |||
4764 | Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma)); | |||
4765 | Params[2] = 0; | |||
4766 | Params[3] = 0; | |||
4767 | Params[4] = 0; | |||
4768 | Params[5] = Colorant[n].Min; | |||
4769 | Params[6] = 0; | |||
4770 | ||||
4771 | Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params); | |||
4772 | if (Curves[n] == NULL((void*)0)) goto Error; | |||
4773 | } | |||
4774 | } | |||
4775 | break; | |||
4776 | ||||
4777 | // Unsupported | |||
4778 | default: | |||
4779 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unsupported tag type for VCGT '%d'", TagType); | |||
4780 | goto Error; | |||
4781 | } | |||
4782 | ||||
4783 | *nItems = 1; | |||
4784 | return (void*) Curves; | |||
4785 | ||||
4786 | // Regret, free all resources | |||
4787 | Error: | |||
4788 | ||||
4789 | cmsFreeToneCurveTriple(Curves); | |||
4790 | _cmsFree(self ->ContextID, Curves); | |||
4791 | return NULL((void*)0); | |||
4792 | ||||
4793 | cmsUNUSED_PARAMETER(SizeOfTag)((void)SizeOfTag); | |||
4794 | } | |||
4795 | ||||
4796 | ||||
4797 | // We don't support all flavors, only 16bits tables and formula | |||
4798 | static | |||
4799 | cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
4800 | { | |||
4801 | cmsToneCurve** Curves = (cmsToneCurve**) Ptr; | |||
4802 | cmsUInt32Number i, j; | |||
4803 | ||||
4804 | if (cmsGetToneCurveParametricType(Curves[0]) == 5 && | |||
4805 | cmsGetToneCurveParametricType(Curves[1]) == 5 && | |||
4806 | cmsGetToneCurveParametricType(Curves[2]) == 5) { | |||
4807 | ||||
4808 | if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType1)) return FALSE0; | |||
4809 | ||||
4810 | // Save parameters | |||
4811 | for (i=0; i < 3; i++) { | |||
4812 | ||||
4813 | _cmsVCGTGAMMA v; | |||
4814 | ||||
4815 | v.Gamma = Curves[i] ->Segments[0].Params[0]; | |||
4816 | v.Min = Curves[i] ->Segments[0].Params[5]; | |||
4817 | v.Max = pow(Curves[i] ->Segments[0].Params[1], v.Gamma) + v.Min; | |||
4818 | ||||
4819 | if (!_cmsWrite15Fixed16Number(io, v.Gamma)) return FALSE0; | |||
4820 | if (!_cmsWrite15Fixed16Number(io, v.Min)) return FALSE0; | |||
4821 | if (!_cmsWrite15Fixed16Number(io, v.Max)) return FALSE0; | |||
4822 | } | |||
4823 | } | |||
4824 | ||||
4825 | else { | |||
4826 | ||||
4827 | // Always store as a table of 256 words | |||
4828 | if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType0)) return FALSE0; | |||
4829 | if (!_cmsWriteUInt16Number(io, 3)) return FALSE0; | |||
4830 | if (!_cmsWriteUInt16Number(io, 256)) return FALSE0; | |||
4831 | if (!_cmsWriteUInt16Number(io, 2)) return FALSE0; | |||
4832 | ||||
4833 | for (i=0; i < 3; i++) { | |||
4834 | for (j=0; j < 256; j++) { | |||
4835 | ||||
4836 | cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0)); | |||
4837 | cmsUInt16Number n = _cmsQuickSaturateWord(v * 65535.0); | |||
4838 | ||||
4839 | if (!_cmsWriteUInt16Number(io, n)) return FALSE0; | |||
4840 | } | |||
4841 | } | |||
4842 | } | |||
4843 | ||||
4844 | return TRUE1; | |||
4845 | ||||
4846 | cmsUNUSED_PARAMETER(self)((void)self); | |||
4847 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
4848 | } | |||
4849 | ||||
4850 | static | |||
4851 | void* Type_vcgt_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
4852 | { | |||
4853 | cmsToneCurve** OldCurves = (cmsToneCurve**) Ptr; | |||
4854 | cmsToneCurve** NewCurves; | |||
4855 | ||||
4856 | NewCurves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*)); | |||
4857 | if (NewCurves == NULL((void*)0)) return NULL((void*)0); | |||
4858 | ||||
4859 | NewCurves[0] = cmsDupToneCurve(OldCurves[0]); | |||
4860 | NewCurves[1] = cmsDupToneCurve(OldCurves[1]); | |||
4861 | NewCurves[2] = cmsDupToneCurve(OldCurves[2]); | |||
4862 | ||||
4863 | return (void*) NewCurves; | |||
4864 | ||||
4865 | cmsUNUSED_PARAMETER(n)((void)n); | |||
4866 | } | |||
4867 | ||||
4868 | ||||
4869 | static | |||
4870 | void Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
4871 | { | |||
4872 | cmsFreeToneCurveTriple((cmsToneCurve**) Ptr); | |||
4873 | _cmsFree(self ->ContextID, Ptr); | |||
4874 | } | |||
4875 | ||||
4876 | ||||
4877 | // ******************************************************************************** | |||
4878 | // Type cmsSigDictType | |||
4879 | // ******************************************************************************** | |||
4880 | ||||
4881 | // Single column of the table can point to wchar or MLUC elements. Holds arrays of data | |||
4882 | typedef struct { | |||
4883 | cmsContext ContextID; | |||
4884 | cmsUInt32Number *Offsets; | |||
4885 | cmsUInt32Number *Sizes; | |||
4886 | } _cmsDICelem; | |||
4887 | ||||
4888 | typedef struct { | |||
4889 | _cmsDICelem Name, Value, DisplayName, DisplayValue; | |||
4890 | ||||
4891 | } _cmsDICarray; | |||
4892 | ||||
4893 | // Allocate an empty array element | |||
4894 | static | |||
4895 | cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e, cmsUInt32Number Count) | |||
4896 | { | |||
4897 | e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number)); | |||
4898 | if (e->Offsets == NULL((void*)0)) return FALSE0; | |||
4899 | ||||
4900 | e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number)); | |||
4901 | if (e->Sizes == NULL((void*)0)) { | |||
4902 | ||||
4903 | _cmsFree(ContextID, e -> Offsets); | |||
4904 | return FALSE0; | |||
4905 | } | |||
4906 | ||||
4907 | e ->ContextID = ContextID; | |||
4908 | return TRUE1; | |||
4909 | } | |||
4910 | ||||
4911 | // Free an array element | |||
4912 | static | |||
4913 | void FreeElem(_cmsDICelem* e) | |||
4914 | { | |||
4915 | if (e ->Offsets != NULL((void*)0)) _cmsFree(e -> ContextID, e -> Offsets); | |||
4916 | if (e ->Sizes != NULL((void*)0)) _cmsFree(e -> ContextID, e -> Sizes); | |||
4917 | e->Offsets = e ->Sizes = NULL((void*)0); | |||
4918 | } | |||
4919 | ||||
4920 | // Get rid of whole array | |||
4921 | static | |||
4922 | void FreeArray( _cmsDICarray* a) | |||
4923 | { | |||
4924 | if (a ->Name.Offsets != NULL((void*)0)) FreeElem(&a->Name); | |||
4925 | if (a ->Value.Offsets != NULL((void*)0)) FreeElem(&a ->Value); | |||
4926 | if (a ->DisplayName.Offsets != NULL((void*)0)) FreeElem(&a->DisplayName); | |||
4927 | if (a ->DisplayValue.Offsets != NULL((void*)0)) FreeElem(&a ->DisplayValue); | |||
4928 | } | |||
4929 | ||||
4930 | ||||
4931 | // Allocate whole array | |||
4932 | static | |||
4933 | cmsBool AllocArray(cmsContext ContextID, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length) | |||
4934 | { | |||
4935 | // Empty values | |||
4936 | memset(a, 0, sizeof(_cmsDICarray)); | |||
4937 | ||||
4938 | // On depending on record size, create column arrays | |||
4939 | if (!AllocElem(ContextID, &a ->Name, Count)) goto Error; | |||
4940 | if (!AllocElem(ContextID, &a ->Value, Count)) goto Error; | |||
4941 | ||||
4942 | if (Length
| |||
4943 | if (!AllocElem(ContextID, &a -> DisplayName, Count)) goto Error; | |||
4944 | ||||
4945 | } | |||
4946 | if (Length
| |||
4947 | if (!AllocElem(ContextID, &a ->DisplayValue, Count)) goto Error; | |||
4948 | } | |||
4949 | return TRUE1; | |||
4950 | ||||
4951 | Error: | |||
4952 | FreeArray(a); | |||
4953 | return FALSE0; | |||
4954 | } | |||
4955 | ||||
4956 | // Read one element | |||
4957 | static | |||
4958 | cmsBool ReadOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsUInt32Number BaseOffset) | |||
4959 | { | |||
4960 | if (!_cmsReadUInt32Number(io, &e->Offsets[i])) return FALSE0; | |||
4961 | if (!_cmsReadUInt32Number(io, &e ->Sizes[i])) return FALSE0; | |||
4962 | ||||
4963 | // An offset of zero has special meaning and shal be preserved | |||
4964 | if (e ->Offsets[i] > 0) | |||
4965 | e ->Offsets[i] += BaseOffset; | |||
4966 | return TRUE1; | |||
4967 | } | |||
4968 | ||||
4969 | ||||
4970 | static | |||
4971 | cmsBool ReadOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset) | |||
4972 | { | |||
4973 | cmsUInt32Number i; | |||
4974 | ||||
4975 | // Read column arrays | |||
4976 | for (i=0; i < Count; i++) { | |||
4977 | ||||
4978 | if (!ReadOneElem(io, &a -> Name, i, BaseOffset)) return FALSE0; | |||
4979 | if (!ReadOneElem(io, &a -> Value, i, BaseOffset)) return FALSE0; | |||
4980 | ||||
4981 | if (Length > 16) { | |||
4982 | ||||
4983 | if (!ReadOneElem(io, &a ->DisplayName, i, BaseOffset)) return FALSE0; | |||
4984 | ||||
4985 | } | |||
4986 | ||||
4987 | if (Length > 24) { | |||
4988 | ||||
4989 | if (!ReadOneElem(io, & a -> DisplayValue, i, BaseOffset)) return FALSE0; | |||
4990 | } | |||
4991 | } | |||
4992 | return TRUE1; | |||
4993 | } | |||
4994 | ||||
4995 | ||||
4996 | // Write one element | |||
4997 | static | |||
4998 | cmsBool WriteOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i) | |||
4999 | { | |||
5000 | if (!_cmsWriteUInt32Number(io, e->Offsets[i])) return FALSE0; | |||
5001 | if (!_cmsWriteUInt32Number(io, e ->Sizes[i])) return FALSE0; | |||
5002 | ||||
5003 | return TRUE1; | |||
5004 | } | |||
5005 | ||||
5006 | static | |||
5007 | cmsBool WriteOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length) | |||
5008 | { | |||
5009 | cmsUInt32Number i; | |||
5010 | ||||
5011 | for (i=0; i < Count; i++) { | |||
5012 | ||||
5013 | if (!WriteOneElem(io, &a -> Name, i)) return FALSE0; | |||
5014 | if (!WriteOneElem(io, &a -> Value, i)) return FALSE0; | |||
5015 | ||||
5016 | if (Length
| |||
5017 | ||||
5018 | if (!WriteOneElem(io, &a -> DisplayName, i)) return FALSE0; | |||
5019 | } | |||
5020 | ||||
5021 | if (Length
| |||
5022 | ||||
5023 | if (!WriteOneElem(io, &a -> DisplayValue, i)) return FALSE0; | |||
5024 | } | |||
5025 | } | |||
5026 | ||||
5027 | return TRUE1; | |||
5028 | } | |||
5029 | ||||
5030 | static | |||
5031 | cmsBool ReadOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, wchar_t ** wcstr) | |||
5032 | { | |||
5033 | ||||
5034 | cmsUInt32Number nChars; | |||
5035 | ||||
5036 | // Special case for undefined strings (see ICC Votable | |||
5037 | // Proposal Submission, Dictionary Type and Metadata TAG Definition) | |||
5038 | if (e -> Offsets[i] == 0) { | |||
5039 | ||||
5040 | *wcstr = NULL((void*)0); | |||
5041 | return TRUE1; | |||
5042 | } | |||
5043 | ||||
5044 | if (!io -> Seek(io, e -> Offsets[i])) return FALSE0; | |||
5045 | ||||
5046 | nChars = e ->Sizes[i] / sizeof(cmsUInt16Number); | |||
5047 | ||||
5048 | ||||
5049 | *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t)); | |||
5050 | if (*wcstr == NULL((void*)0)) return FALSE0; | |||
5051 | ||||
5052 | if (!_cmsReadWCharArray(io, nChars, *wcstr)) { | |||
5053 | _cmsFree(e ->ContextID, *wcstr); | |||
5054 | return FALSE0; | |||
5055 | } | |||
5056 | ||||
5057 | // End of string marker | |||
5058 | (*wcstr)[nChars] = 0; | |||
5059 | return TRUE1; | |||
5060 | } | |||
5061 | ||||
5062 | static | |||
5063 | cmsUInt32Number mywcslen(const wchar_t *s) | |||
5064 | { | |||
5065 | const wchar_t *p; | |||
5066 | ||||
5067 | p = s; | |||
5068 | while (*p) | |||
5069 | p++; | |||
5070 | ||||
5071 | return (cmsUInt32Number)(p - s); | |||
5072 | } | |||
5073 | ||||
5074 | static | |||
5075 | cmsBool WriteOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const wchar_t * wcstr, cmsUInt32Number BaseOffset) | |||
5076 | { | |||
5077 | cmsUInt32Number Before = io ->Tell(io); | |||
5078 | cmsUInt32Number n; | |||
5079 | ||||
5080 | e ->Offsets[i] = Before - BaseOffset; | |||
5081 | ||||
5082 | if (wcstr == NULL((void*)0)) { | |||
5083 | e ->Sizes[i] = 0; | |||
5084 | e ->Offsets[i] = 0; | |||
5085 | return TRUE1; | |||
5086 | } | |||
5087 | ||||
5088 | n = mywcslen(wcstr); | |||
5089 | if (!_cmsWriteWCharArray(io, n, wcstr)) return FALSE0; | |||
5090 | ||||
5091 | e ->Sizes[i] = io ->Tell(io) - Before; | |||
5092 | return TRUE1; | |||
5093 | } | |||
5094 | ||||
5095 | static | |||
5096 | cmsBool ReadOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsMLU** mlu) | |||
5097 | { | |||
5098 | cmsUInt32Number nItems = 0; | |||
5099 | ||||
5100 | // A way to get null MLUCs | |||
5101 | if (e -> Offsets[i] == 0 || e ->Sizes[i] == 0) { | |||
5102 | ||||
5103 | *mlu = NULL((void*)0); | |||
5104 | return TRUE1; | |||
5105 | } | |||
5106 | ||||
5107 | if (!io -> Seek(io, e -> Offsets[i])) return FALSE0; | |||
5108 | ||||
5109 | *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]); | |||
5110 | return *mlu != NULL((void*)0); | |||
5111 | } | |||
5112 | ||||
5113 | static | |||
5114 | cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset) | |||
5115 | { | |||
5116 | cmsUInt32Number Before; | |||
5117 | ||||
5118 | // Special case for undefined strings (see ICC Votable | |||
5119 | // Proposal Submission, Dictionary Type and Metadata TAG Definition) | |||
5120 | if (mlu
| |||
5121 | e ->Sizes[i] = 0; | |||
5122 | e ->Offsets[i] = 0; | |||
5123 | return TRUE1; | |||
5124 | } | |||
5125 | ||||
5126 | Before = io ->Tell(io); | |||
5127 | e ->Offsets[i] = Before - BaseOffset; | |||
| ||||
5128 | ||||
5129 | if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE0; | |||
5130 | ||||
5131 | e ->Sizes[i] = io ->Tell(io) - Before; | |||
5132 | return TRUE1; | |||
5133 | } | |||
5134 | ||||
5135 | ||||
5136 | static | |||
5137 | void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag) | |||
5138 | { | |||
5139 | cmsHANDLE hDict; | |||
5140 | cmsUInt32Number i, Count, Length; | |||
5141 | cmsUInt32Number BaseOffset; | |||
5142 | _cmsDICarray a; | |||
5143 | wchar_t *NameWCS = NULL((void*)0), *ValueWCS = NULL((void*)0); | |||
5144 | cmsMLU *DisplayNameMLU = NULL((void*)0), *DisplayValueMLU=NULL((void*)0); | |||
5145 | cmsBool rc; | |||
5146 | ||||
5147 | *nItems = 0; | |||
5148 | ||||
5149 | // Get actual position as a basis for element offsets | |||
5150 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
5151 | ||||
5152 | // Get name-value record count | |||
5153 | if (!_cmsReadUInt32Number(io, &Count)) return NULL((void*)0); | |||
5154 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
5155 | ||||
5156 | // Get rec length | |||
5157 | if (!_cmsReadUInt32Number(io, &Length)) return NULL((void*)0); | |||
5158 | SizeOfTag -= sizeof(cmsUInt32Number); | |||
5159 | ||||
5160 | // Check for valid lengths | |||
5161 | if (Length != 16 && Length != 24 && Length != 32) { | |||
5162 | cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION8, "Unknown record length in dictionary '%d'", Length); | |||
5163 | return NULL((void*)0); | |||
5164 | } | |||
5165 | ||||
5166 | // Creates an empty dictionary | |||
5167 | hDict = cmsDictAlloc(self -> ContextID); | |||
5168 | if (hDict == NULL((void*)0)) return NULL((void*)0); | |||
5169 | ||||
5170 | // On depending on record size, create column arrays | |||
5171 | if (!AllocArray(self -> ContextID, &a, Count, Length)) goto Error; | |||
5172 | ||||
5173 | // Read column arrays | |||
5174 | if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset)) goto Error; | |||
5175 | ||||
5176 | // Seek to each element and read it | |||
5177 | for (i=0; i < Count; i++) { | |||
5178 | ||||
5179 | if (!ReadOneWChar(io, &a.Name, i, &NameWCS)) goto Error; | |||
5180 | if (!ReadOneWChar(io, &a.Value, i, &ValueWCS)) goto Error; | |||
5181 | ||||
5182 | if (Length > 16) { | |||
5183 | if (!ReadOneMLUC(self, io, &a.DisplayName, i, &DisplayNameMLU)) goto Error; | |||
5184 | } | |||
5185 | ||||
5186 | if (Length > 24) { | |||
5187 | if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error; | |||
5188 | } | |||
5189 | ||||
5190 | if (NameWCS == NULL((void*)0) || ValueWCS == NULL((void*)0)) { | |||
5191 | ||||
5192 | cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED12, "Bad dictionary Name/Value"); | |||
5193 | rc = FALSE0; | |||
5194 | } | |||
5195 | else { | |||
5196 | ||||
5197 | rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU); | |||
5198 | } | |||
5199 | ||||
5200 | if (NameWCS != NULL((void*)0)) _cmsFree(self ->ContextID, NameWCS); | |||
5201 | if (ValueWCS != NULL((void*)0)) _cmsFree(self ->ContextID, ValueWCS); | |||
5202 | if (DisplayNameMLU != NULL((void*)0)) cmsMLUfree(DisplayNameMLU); | |||
5203 | if (DisplayValueMLU != NULL((void*)0)) cmsMLUfree(DisplayValueMLU); | |||
5204 | ||||
5205 | if (!rc) goto Error; | |||
5206 | } | |||
5207 | ||||
5208 | FreeArray(&a); | |||
5209 | *nItems = 1; | |||
5210 | return (void*) hDict; | |||
5211 | ||||
5212 | Error: | |||
5213 | FreeArray(&a); | |||
5214 | cmsDictFree(hDict); | |||
5215 | return NULL((void*)0); | |||
5216 | } | |||
5217 | ||||
5218 | ||||
5219 | static | |||
5220 | cmsBool Type_Dictionary_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems) | |||
5221 | { | |||
5222 | cmsHANDLE hDict = (cmsHANDLE) Ptr; | |||
5223 | const cmsDICTentry* p; | |||
5224 | cmsBool AnyName, AnyValue; | |||
5225 | cmsUInt32Number i, Count, Length; | |||
5226 | cmsUInt32Number DirectoryPos, CurrentPos, BaseOffset; | |||
5227 | _cmsDICarray a; | |||
5228 | ||||
5229 | if (hDict == NULL((void*)0)) return FALSE0; | |||
| ||||
5230 | ||||
5231 | BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase); | |||
5232 | ||||
5233 | // Let's inspect the dictionary | |||
5234 | Count = 0; AnyName = FALSE0; AnyValue = FALSE0; | |||
5235 | for (p = cmsDictGetEntryList(hDict); p != NULL((void*)0); p = cmsDictNextEntry(p)) { | |||
5236 | ||||
5237 | if (p ->DisplayName != NULL((void*)0)) AnyName = TRUE1; | |||
5238 | if (p ->DisplayValue != NULL((void*)0)) AnyValue = TRUE1; | |||
5239 | Count++; | |||
5240 | } | |||
5241 | ||||
5242 | Length = 16; | |||
5243 | if (AnyName
| |||
5244 | if (AnyValue
| |||
5245 | ||||
5246 | if (!_cmsWriteUInt32Number(io, Count)) return FALSE0; | |||
5247 | if (!_cmsWriteUInt32Number(io, Length)) return FALSE0; | |||
5248 | ||||
5249 | // Keep starting position of offsets table | |||
5250 | DirectoryPos = io ->Tell(io); | |||
5251 | ||||
5252 | // Allocate offsets array | |||
5253 | if (!AllocArray(self ->ContextID, &a, Count, Length)) goto Error; | |||
5254 | ||||
5255 | // Write a fake directory to be filled latter on | |||
5256 | if (!WriteOffsetArray(io, &a, Count, Length)) goto Error; | |||
5257 | ||||
5258 | // Write each element. Keep track of the size as well. | |||
5259 | p = cmsDictGetEntryList(hDict); | |||
5260 | for (i=0; i < Count; i++) { | |||
5261 | ||||
5262 | if (!WriteOneWChar(io, &a.Name, i, p ->Name, BaseOffset)) goto Error; | |||
5263 | if (!WriteOneWChar(io, &a.Value, i, p ->Value, BaseOffset)) goto Error; | |||
5264 | ||||
5265 | if (p ->DisplayName != NULL((void*)0)) { | |||
5266 | if (!WriteOneMLUC(self, io, &a.DisplayName, i, p ->DisplayName, BaseOffset)) goto Error; | |||
5267 | } | |||
5268 | ||||
5269 | if (p ->DisplayValue != NULL((void*)0)) { | |||
5270 | if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error; | |||
5271 | } | |||
5272 | ||||
5273 | p = cmsDictNextEntry(p); | |||
5274 | } | |||
5275 | ||||
5276 | // Write the directory | |||
5277 | CurrentPos = io ->Tell(io); | |||
5278 | if (!io ->Seek(io, DirectoryPos)) goto Error; | |||
5279 | ||||
5280 | if (!WriteOffsetArray(io, &a, Count, Length)) goto Error; | |||
5281 | ||||
5282 | if (!io ->Seek(io, CurrentPos)) goto Error; | |||
5283 | ||||
5284 | FreeArray(&a); | |||
5285 | return TRUE1; | |||
5286 | ||||
5287 | Error: | |||
5288 | FreeArray(&a); | |||
5289 | return FALSE0; | |||
5290 | ||||
5291 | cmsUNUSED_PARAMETER(nItems)((void)nItems); | |||
5292 | } | |||
5293 | ||||
5294 | ||||
5295 | static | |||
5296 | void* Type_Dictionary_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n) | |||
5297 | { | |||
5298 | return (void*) cmsDictDup((cmsHANDLE) Ptr); | |||
5299 | ||||
5300 | cmsUNUSED_PARAMETER(n)((void)n); | |||
5301 | cmsUNUSED_PARAMETER(self)((void)self); | |||
5302 | } | |||
5303 | ||||
5304 | ||||
5305 | static | |||
5306 | void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr) | |||
5307 | { | |||
5308 | cmsDictFree((cmsHANDLE) Ptr); | |||
5309 | cmsUNUSED_PARAMETER(self)((void)self); | |||
5310 | } | |||
5311 | ||||
5312 | ||||
5313 | // ******************************************************************************** | |||
5314 | // Type support main routines | |||
5315 | // ******************************************************************************** | |||
5316 | ||||
5317 | ||||
5318 | // This is the list of built-in types | |||
5319 | static const _cmsTagTypeLinkedList SupportedTagTypes[] = { | |||
5320 | ||||
5321 | {TYPE_HANDLER(cmsSigChromaticityType, Chromaticity){ (cmsSigChromaticityType), Type_Chromaticity_Read, Type_Chromaticity_Write , Type_Chromaticity_Dup, Type_Chromaticity_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[1] }, | |||
5322 | {TYPE_HANDLER(cmsSigColorantOrderType, ColorantOrderType){ (cmsSigColorantOrderType), Type_ColorantOrderType_Read, Type_ColorantOrderType_Write , Type_ColorantOrderType_Dup, Type_ColorantOrderType_Free, (( void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[2] }, | |||
5323 | {TYPE_HANDLER(cmsSigS15Fixed16ArrayType, S15Fixed16){ (cmsSigS15Fixed16ArrayType), Type_S15Fixed16_Read, Type_S15Fixed16_Write , Type_S15Fixed16_Dup, Type_S15Fixed16_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[3] }, | |||
5324 | {TYPE_HANDLER(cmsSigU16Fixed16ArrayType, U16Fixed16){ (cmsSigU16Fixed16ArrayType), Type_U16Fixed16_Read, Type_U16Fixed16_Write , Type_U16Fixed16_Dup, Type_U16Fixed16_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[4] }, | |||
5325 | {TYPE_HANDLER(cmsSigTextType, Text){ (cmsSigTextType), Type_Text_Read, Type_Text_Write, Type_Text_Dup , Type_Text_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[5] }, | |||
5326 | {TYPE_HANDLER(cmsSigTextDescriptionType, Text_Description){ (cmsSigTextDescriptionType), Type_Text_Description_Read, Type_Text_Description_Write , Type_Text_Description_Dup, Type_Text_Description_Free, ((void *)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[6] }, | |||
5327 | {TYPE_HANDLER(cmsSigCurveType, Curve){ (cmsSigCurveType), Type_Curve_Read, Type_Curve_Write, Type_Curve_Dup , Type_Curve_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[7] }, | |||
5328 | {TYPE_HANDLER(cmsSigParametricCurveType, ParametricCurve){ (cmsSigParametricCurveType), Type_ParametricCurve_Read, Type_ParametricCurve_Write , Type_ParametricCurve_Dup, Type_ParametricCurve_Free, ((void *)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[8] }, | |||
5329 | {TYPE_HANDLER(cmsSigDateTimeType, DateTime){ (cmsSigDateTimeType), Type_DateTime_Read, Type_DateTime_Write , Type_DateTime_Dup, Type_DateTime_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[9] }, | |||
5330 | {TYPE_HANDLER(cmsSigLut8Type, LUT8){ (cmsSigLut8Type), Type_LUT8_Read, Type_LUT8_Write, Type_LUT8_Dup , Type_LUT8_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[10] }, | |||
5331 | {TYPE_HANDLER(cmsSigLut16Type, LUT16){ (cmsSigLut16Type), Type_LUT16_Read, Type_LUT16_Write, Type_LUT16_Dup , Type_LUT16_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[11] }, | |||
5332 | {TYPE_HANDLER(cmsSigColorantTableType, ColorantTable){ (cmsSigColorantTableType), Type_ColorantTable_Read, Type_ColorantTable_Write , Type_ColorantTable_Dup, Type_ColorantTable_Free, ((void*)0) , 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[12] }, | |||
5333 | {TYPE_HANDLER(cmsSigNamedColor2Type, NamedColor){ (cmsSigNamedColor2Type), Type_NamedColor_Read, Type_NamedColor_Write , Type_NamedColor_Dup, Type_NamedColor_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[13] }, | |||
5334 | {TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU){ (cmsSigMultiLocalizedUnicodeType), Type_MLU_Read, Type_MLU_Write , Type_MLU_Dup, Type_MLU_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[14] }, | |||
5335 | {TYPE_HANDLER(cmsSigProfileSequenceDescType, ProfileSequenceDesc){ (cmsSigProfileSequenceDescType), Type_ProfileSequenceDesc_Read , Type_ProfileSequenceDesc_Write, Type_ProfileSequenceDesc_Dup , Type_ProfileSequenceDesc_Free, ((void*)0), 0 },(_cmsTagTypeLinkedList*) &SupportedTagTypes[15] }, | |||
5336 | {TYPE_HANDLER(cmsSigSignatureType, Signature){ (cmsSigSignatureType), Type_Signature_Read, Type_Signature_Write , Type_Signature_Dup, Type_Signature_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[16] }, | |||
5337 | {TYPE_HANDLER(cmsSigMeasurementType, Measurement){ (cmsSigMeasurementType), Type_Measurement_Read, Type_Measurement_Write , Type_Measurement_Dup, Type_Measurement_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[17] }, | |||
5338 | {TYPE_HANDLER(cmsSigDataType, Data){ (cmsSigDataType), Type_Data_Read, Type_Data_Write, Type_Data_Dup , Type_Data_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[18] }, | |||
5339 | {TYPE_HANDLER(cmsSigLutAtoBType, LUTA2B){ (cmsSigLutAtoBType), Type_LUTA2B_Read, Type_LUTA2B_Write, Type_LUTA2B_Dup , Type_LUTA2B_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[19] }, | |||
5340 | {TYPE_HANDLER(cmsSigLutBtoAType, LUTB2A){ (cmsSigLutBtoAType), Type_LUTB2A_Read, Type_LUTB2A_Write, Type_LUTB2A_Dup , Type_LUTB2A_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[20] }, | |||
5341 | {TYPE_HANDLER(cmsSigUcrBgType, UcrBg){ (cmsSigUcrBgType), Type_UcrBg_Read, Type_UcrBg_Write, Type_UcrBg_Dup , Type_UcrBg_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[21] }, | |||
5342 | {TYPE_HANDLER(cmsSigCrdInfoType, CrdInfo){ (cmsSigCrdInfoType), Type_CrdInfo_Read, Type_CrdInfo_Write, Type_CrdInfo_Dup, Type_CrdInfo_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[22] }, | |||
5343 | {TYPE_HANDLER(cmsSigMultiProcessElementType, MPE){ (cmsSigMultiProcessElementType), Type_MPE_Read, Type_MPE_Write , Type_MPE_Dup, Type_MPE_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[23] }, | |||
5344 | {TYPE_HANDLER(cmsSigScreeningType, Screening){ (cmsSigScreeningType), Type_Screening_Read, Type_Screening_Write , Type_Screening_Dup, Type_Screening_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[24] }, | |||
5345 | {TYPE_HANDLER(cmsSigViewingConditionsType, ViewingConditions){ (cmsSigViewingConditionsType), Type_ViewingConditions_Read, Type_ViewingConditions_Write, Type_ViewingConditions_Dup, Type_ViewingConditions_Free , ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[25] }, | |||
5346 | {TYPE_HANDLER(cmsSigXYZType, XYZ){ (cmsSigXYZType), Type_XYZ_Read, Type_XYZ_Write, Type_XYZ_Dup , Type_XYZ_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[26] }, | |||
5347 | {TYPE_HANDLER(cmsCorbisBrokenXYZtype, XYZ){ (((cmsTagTypeSignature) 0x17A505B8)), Type_XYZ_Read, Type_XYZ_Write , Type_XYZ_Dup, Type_XYZ_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[27] }, | |||
5348 | {TYPE_HANDLER(cmsMonacoBrokenCurveType, Curve){ (((cmsTagTypeSignature) 0x9478ee00)), Type_Curve_Read, Type_Curve_Write , Type_Curve_Dup, Type_Curve_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[28] }, | |||
5349 | {TYPE_HANDLER(cmsSigProfileSequenceIdType, ProfileSequenceId){ (cmsSigProfileSequenceIdType), Type_ProfileSequenceId_Read, Type_ProfileSequenceId_Write, Type_ProfileSequenceId_Dup, Type_ProfileSequenceId_Free , ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[29] }, | |||
5350 | {TYPE_HANDLER(cmsSigDictType, Dictionary){ (cmsSigDictType), Type_Dictionary_Read, Type_Dictionary_Write , Type_Dictionary_Dup, Type_Dictionary_Free, ((void*)0), 0 }, (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] }, | |||
5351 | {TYPE_HANDLER(cmsSigVcgtType, vcgt){ (cmsSigVcgtType), Type_vcgt_Read, Type_vcgt_Write, Type_vcgt_Dup , Type_vcgt_Free, ((void*)0), 0 }, NULL((void*)0) } | |||
5352 | }; | |||
5353 | ||||
5354 | ||||
5355 | _cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL((void*)0) }; | |||
5356 | ||||
5357 | ||||
5358 | ||||
5359 | // Duplicates the zone of memory used by the plug-in in the new context | |||
5360 | static | |||
5361 | void DupTagTypeList(struct _cmsContext_struct* ctx, | |||
5362 | const struct _cmsContext_struct* src, | |||
5363 | int loc) | |||
5364 | { | |||
5365 | _cmsTagTypePluginChunkType newHead = { NULL((void*)0) }; | |||
5366 | _cmsTagTypeLinkedList* entry; | |||
5367 | _cmsTagTypeLinkedList* Anterior = NULL((void*)0); | |||
5368 | _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc]; | |||
5369 | ||||
5370 | // Walk the list copying all nodes | |||
5371 | for (entry = head->TagTypes; | |||
5372 | entry != NULL((void*)0); | |||
5373 | entry = entry ->Next) { | |||
5374 | ||||
5375 | _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList)); | |||
5376 | ||||
5377 | if (newEntry == NULL((void*)0)) | |||
5378 | return; | |||
5379 | ||||
5380 | // We want to keep the linked list order, so this is a little bit tricky | |||
5381 | newEntry -> Next = NULL((void*)0); | |||
5382 | if (Anterior) | |||
5383 | Anterior -> Next = newEntry; | |||
5384 | ||||
5385 | Anterior = newEntry; | |||
5386 | ||||
5387 | if (newHead.TagTypes == NULL((void*)0)) | |||
5388 | newHead.TagTypes = newEntry; | |||
5389 | } | |||
5390 | ||||
5391 | ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType)); | |||
5392 | } | |||
5393 | ||||
5394 | ||||
5395 | void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx, | |||
5396 | const struct _cmsContext_struct* src) | |||
5397 | { | |||
5398 | if (src != NULL((void*)0)) { | |||
5399 | ||||
5400 | // Duplicate the LIST | |||
5401 | DupTagTypeList(ctx, src, TagTypePlugin); | |||
5402 | } | |||
5403 | else { | |||
5404 | static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL((void*)0) }; | |||
5405 | ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType)); | |||
5406 | } | |||
5407 | } | |||
5408 | ||||
5409 | void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx, | |||
5410 | const struct _cmsContext_struct* src) | |||
5411 | { | |||
5412 | if (src != NULL((void*)0)) { | |||
5413 | ||||
5414 | // Duplicate the LIST | |||
5415 | DupTagTypeList(ctx, src, MPEPlugin); | |||
5416 | } | |||
5417 | else { | |||
5418 | static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL((void*)0) }; | |||
5419 | ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType)); | |||
5420 | } | |||
5421 | ||||
5422 | } | |||
5423 | ||||
5424 | ||||
5425 | // Both kind of plug-ins share same structure | |||
5426 | cmsBool _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data) | |||
5427 | { | |||
5428 | return RegisterTypesPlugin(id, Data, TagTypePlugin); | |||
5429 | } | |||
5430 | ||||
5431 | cmsBool _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data) | |||
5432 | { | |||
5433 | return RegisterTypesPlugin(id, Data,MPEPlugin); | |||
5434 | } | |||
5435 | ||||
5436 | ||||
5437 | // Wrapper for tag types | |||
5438 | cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig) | |||
5439 | { | |||
5440 | _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin); | |||
5441 | ||||
5442 | return GetHandler(sig, ctx->TagTypes, (_cmsTagTypeLinkedList*) SupportedTagTypes); | |||
5443 | } | |||
5444 | ||||
5445 | // ******************************************************************************** | |||
5446 | // Tag support main routines | |||
5447 | // ******************************************************************************** | |||
5448 | ||||
5449 | typedef struct _cmsTagLinkedList_st { | |||
5450 | ||||
5451 | cmsTagSignature Signature; | |||
5452 | cmsTagDescriptor Descriptor; | |||
5453 | struct _cmsTagLinkedList_st* Next; | |||
5454 | ||||
5455 | } _cmsTagLinkedList; | |||
5456 | ||||
5457 | // This is the list of built-in tags. The data of this list can be modified by plug-ins | |||
5458 | static _cmsTagLinkedList SupportedTags[] = { | |||
5459 | ||||
5460 | { cmsSigAToB0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]}, | |||
5461 | { cmsSigAToB1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[2]}, | |||
5462 | { cmsSigAToB2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[3]}, | |||
5463 | { cmsSigBToA0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[4]}, | |||
5464 | { cmsSigBToA1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[5]}, | |||
5465 | { cmsSigBToA2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[6]}, | |||
5466 | ||||
5467 | // Allow corbis and its broken XYZ type | |||
5468 | { cmsSigRedColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype((cmsTagTypeSignature) 0x17A505B8) }, DecideXYZtype}, &SupportedTags[7]}, | |||
5469 | { cmsSigGreenColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype((cmsTagTypeSignature) 0x17A505B8) }, DecideXYZtype}, &SupportedTags[8]}, | |||
5470 | { cmsSigBlueColorantTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype((cmsTagTypeSignature) 0x17A505B8) }, DecideXYZtype}, &SupportedTags[9]}, | |||
5471 | ||||
5472 | { cmsSigRedTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType((cmsTagTypeSignature) 0x9478ee00) }, DecideCurveType}, &SupportedTags[10]}, | |||
5473 | { cmsSigGreenTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType((cmsTagTypeSignature) 0x9478ee00) }, DecideCurveType}, &SupportedTags[11]}, | |||
5474 | { cmsSigBlueTRCTag, { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType((cmsTagTypeSignature) 0x9478ee00) }, DecideCurveType}, &SupportedTags[12]}, | |||
5475 | ||||
5476 | { cmsSigCalibrationDateTimeTag, { 1, 1, { cmsSigDateTimeType }, NULL((void*)0)}, &SupportedTags[13]}, | |||
5477 | { cmsSigCharTargetTag, { 1, 1, { cmsSigTextType }, NULL((void*)0)}, &SupportedTags[14]}, | |||
5478 | ||||
5479 | { cmsSigChromaticAdaptationTag, { 9, 1, { cmsSigS15Fixed16ArrayType }, NULL((void*)0)}, &SupportedTags[15]}, | |||
5480 | { cmsSigChromaticityTag, { 1, 1, { cmsSigChromaticityType }, NULL((void*)0)}, &SupportedTags[16]}, | |||
5481 | { cmsSigColorantOrderTag, { 1, 1, { cmsSigColorantOrderType }, NULL((void*)0)}, &SupportedTags[17]}, | |||
5482 | { cmsSigColorantTableTag, { 1, 1, { cmsSigColorantTableType }, NULL((void*)0)}, &SupportedTags[18]}, | |||
5483 | { cmsSigColorantTableOutTag, { 1, 1, { cmsSigColorantTableType }, NULL((void*)0)}, &SupportedTags[19]}, | |||
5484 | ||||
5485 | { cmsSigCopyrightTag, { 1, 3, { cmsSigTextType, cmsSigMultiLocalizedUnicodeType, cmsSigTextDescriptionType}, DecideTextType}, &SupportedTags[20]}, | |||
5486 | { cmsSigDateTimeTag, { 1, 1, { cmsSigDateTimeType }, NULL((void*)0)}, &SupportedTags[21]}, | |||
5487 | ||||
5488 | { cmsSigDeviceMfgDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[22]}, | |||
5489 | { cmsSigDeviceModelDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[23]}, | |||
5490 | ||||
5491 | { cmsSigGamutTag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[24]}, | |||
5492 | ||||
5493 | { cmsSigGrayTRCTag, { 1, 2, { cmsSigCurveType, cmsSigParametricCurveType }, DecideCurveType}, &SupportedTags[25]}, | |||
5494 | { cmsSigLuminanceTag, { 1, 1, { cmsSigXYZType }, NULL((void*)0)}, &SupportedTags[26]}, | |||
5495 | ||||
5496 | { cmsSigMediaBlackPointTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype((cmsTagTypeSignature) 0x17A505B8) }, NULL((void*)0)}, &SupportedTags[27]}, | |||
5497 | { cmsSigMediaWhitePointTag, { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype((cmsTagTypeSignature) 0x17A505B8) }, NULL((void*)0)}, &SupportedTags[28]}, | |||
5498 | ||||
5499 | { cmsSigNamedColor2Tag, { 1, 1, { cmsSigNamedColor2Type }, NULL((void*)0)}, &SupportedTags[29]}, | |||
5500 | ||||
5501 | { cmsSigPreview0Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[30]}, | |||
5502 | { cmsSigPreview1Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[31]}, | |||
5503 | { cmsSigPreview2Tag, { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]}, | |||
5504 | ||||
5505 | { cmsSigProfileDescriptionTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]}, | |||
5506 | { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL((void*)0)}, &SupportedTags[34]}, | |||
5507 | { cmsSigTechnologyTag, { 1, 1, { cmsSigSignatureType }, NULL((void*)0)}, &SupportedTags[35]}, | |||
5508 | ||||
5509 | { cmsSigColorimetricIntentImageStateTag, { 1, 1, { cmsSigSignatureType }, NULL((void*)0)}, &SupportedTags[36]}, | |||
5510 | { cmsSigPerceptualRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL((void*)0)}, &SupportedTags[37]}, | |||
5511 | { cmsSigSaturationRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL((void*)0)}, &SupportedTags[38]}, | |||
5512 | ||||
5513 | { cmsSigMeasurementTag, { 1, 1, { cmsSigMeasurementType }, NULL((void*)0)}, &SupportedTags[39]}, | |||
5514 | ||||
5515 | { cmsSigPs2CRD0Tag, { 1, 1, { cmsSigDataType }, NULL((void*)0)}, &SupportedTags[40]}, | |||
5516 | { cmsSigPs2CRD1Tag, { 1, 1, { cmsSigDataType }, NULL((void*)0)}, &SupportedTags[41]}, | |||
5517 | { cmsSigPs2CRD2Tag, { 1, 1, { cmsSigDataType }, NULL((void*)0)}, &SupportedTags[42]}, | |||
5518 | { cmsSigPs2CRD3Tag, { 1, 1, { cmsSigDataType }, NULL((void*)0)}, &SupportedTags[43]}, | |||
5519 | { cmsSigPs2CSATag, { 1, 1, { cmsSigDataType }, NULL((void*)0)}, &SupportedTags[44]}, | |||
5520 | { cmsSigPs2RenderingIntentTag, { 1, 1, { cmsSigDataType }, NULL((void*)0)}, &SupportedTags[45]}, | |||
5521 | ||||
5522 | { cmsSigViewingCondDescTag, { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[46]}, | |||
5523 | ||||
5524 | { cmsSigUcrBgTag, { 1, 1, { cmsSigUcrBgType}, NULL((void*)0)}, &SupportedTags[47]}, | |||
5525 | { cmsSigCrdInfoTag, { 1, 1, { cmsSigCrdInfoType}, NULL((void*)0)}, &SupportedTags[48]}, | |||
5526 | ||||
5527 | { cmsSigDToB0Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[49]}, | |||
5528 | { cmsSigDToB1Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[50]}, | |||
5529 | { cmsSigDToB2Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[51]}, | |||
5530 | { cmsSigDToB3Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[52]}, | |||
5531 | { cmsSigBToD0Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[53]}, | |||
5532 | { cmsSigBToD1Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[54]}, | |||
5533 | { cmsSigBToD2Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[55]}, | |||
5534 | { cmsSigBToD3Tag, { 1, 1, { cmsSigMultiProcessElementType}, NULL((void*)0)}, &SupportedTags[56]}, | |||
5535 | ||||
5536 | { cmsSigScreeningDescTag, { 1, 1, { cmsSigTextDescriptionType }, NULL((void*)0)}, &SupportedTags[57]}, | |||
5537 | { cmsSigViewingConditionsTag, { 1, 1, { cmsSigViewingConditionsType }, NULL((void*)0)}, &SupportedTags[58]}, | |||
5538 | ||||
5539 | { cmsSigScreeningTag, { 1, 1, { cmsSigScreeningType}, NULL((void*)0) }, &SupportedTags[59]}, | |||
5540 | { cmsSigVcgtTag, { 1, 1, { cmsSigVcgtType}, NULL((void*)0) }, &SupportedTags[60]}, | |||
5541 | { cmsSigMetaTag, { 1, 1, { cmsSigDictType}, NULL((void*)0) }, &SupportedTags[61]}, | |||
5542 | { cmsSigProfileSequenceIdTag, { 1, 1, { cmsSigProfileSequenceIdType}, NULL((void*)0) }, &SupportedTags[62]}, | |||
5543 | ||||
5544 | { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL((void*)0)}, &SupportedTags[63]}, | |||
5545 | { cmsSigArgyllArtsTag, { 9, 1, { cmsSigS15Fixed16ArrayType}, NULL((void*)0)}, NULL((void*)0)} | |||
5546 | ||||
5547 | }; | |||
5548 | ||||
5549 | /* | |||
5550 | Not supported Why | |||
5551 | ======================= ========================================= | |||
5552 | cmsSigOutputResponseTag ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT! | |||
5553 | cmsSigNamedColorTag ==> Deprecated | |||
5554 | cmsSigDataTag ==> Ancient, unused | |||
5555 | cmsSigDeviceSettingsTag ==> Deprecated, useless | |||
5556 | */ | |||
5557 | ||||
5558 | ||||
5559 | _cmsTagPluginChunkType _cmsTagPluginChunk = { NULL((void*)0) }; | |||
5560 | ||||
5561 | ||||
5562 | // Duplicates the zone of memory used by the plug-in in the new context | |||
5563 | static | |||
5564 | void DupTagList(struct _cmsContext_struct* ctx, | |||
5565 | const struct _cmsContext_struct* src) | |||
5566 | { | |||
5567 | _cmsTagPluginChunkType newHead = { NULL((void*)0) }; | |||
5568 | _cmsTagLinkedList* entry; | |||
5569 | _cmsTagLinkedList* Anterior = NULL((void*)0); | |||
5570 | _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin]; | |||
5571 | ||||
5572 | // Walk the list copying all nodes | |||
5573 | for (entry = head->Tag; | |||
5574 | entry != NULL((void*)0); | |||
5575 | entry = entry ->Next) { | |||
5576 | ||||
5577 | _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList)); | |||
5578 | ||||
5579 | if (newEntry == NULL((void*)0)) | |||
5580 | return; | |||
5581 | ||||
5582 | // We want to keep the linked list order, so this is a little bit tricky | |||
5583 | newEntry -> Next = NULL((void*)0); | |||
5584 | if (Anterior) | |||
5585 | Anterior -> Next = newEntry; | |||
5586 | ||||
5587 | Anterior = newEntry; | |||
5588 | ||||
5589 | if (newHead.Tag == NULL((void*)0)) | |||
5590 | newHead.Tag = newEntry; | |||
5591 | } | |||
5592 | ||||
5593 | ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType)); | |||
5594 | } | |||
5595 | ||||
5596 | void _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx, | |||
5597 | const struct _cmsContext_struct* src) | |||
5598 | { | |||
5599 | if (src != NULL((void*)0)) { | |||
5600 | ||||
5601 | DupTagList(ctx, src); | |||
5602 | } | |||
5603 | else { | |||
5604 | static _cmsTagPluginChunkType TagPluginChunk = { NULL((void*)0) }; | |||
5605 | ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagPluginChunk, sizeof(_cmsTagPluginChunkType)); | |||
5606 | } | |||
5607 | ||||
5608 | } | |||
5609 | ||||
5610 | cmsBool _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data) | |||
5611 | { | |||
5612 | cmsPluginTag* Plugin = (cmsPluginTag*) Data; | |||
5613 | _cmsTagLinkedList *pt; | |||
5614 | _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(id, TagPlugin); | |||
5615 | ||||
5616 | if (Data == NULL((void*)0)) { | |||
5617 | ||||
5618 | TagPluginChunk->Tag = NULL((void*)0); | |||
5619 | return TRUE1; | |||
5620 | } | |||
5621 | ||||
5622 | pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList)); | |||
5623 | if (pt == NULL((void*)0)) return FALSE0; | |||
5624 | ||||
5625 | pt ->Signature = Plugin ->Signature; | |||
5626 | pt ->Descriptor = Plugin ->Descriptor; | |||
5627 | pt ->Next = TagPluginChunk ->Tag; | |||
5628 | ||||
5629 | TagPluginChunk ->Tag = pt; | |||
5630 | ||||
5631 | return TRUE1; | |||
5632 | } | |||
5633 | ||||
5634 | // Return a descriptor for a given tag or NULL | |||
5635 | cmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig) | |||
5636 | { | |||
5637 | _cmsTagLinkedList* pt; | |||
5638 | _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(ContextID, TagPlugin); | |||
5639 | ||||
5640 | for (pt = TagPluginChunk->Tag; | |||
5641 | pt != NULL((void*)0); | |||
5642 | pt = pt ->Next) { | |||
5643 | ||||
5644 | if (sig == pt -> Signature) return &pt ->Descriptor; | |||
5645 | } | |||
5646 | ||||
5647 | for (pt = SupportedTags; | |||
5648 | pt != NULL((void*)0); | |||
5649 | pt = pt ->Next) { | |||
5650 | ||||
5651 | if (sig == pt -> Signature) return &pt ->Descriptor; | |||
5652 | } | |||
5653 | ||||
5654 | return NULL((void*)0); | |||
5655 | } | |||
5656 |