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-2017 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 // Alpha copy ------------------------------------------------------------------------------------------------------------------
59
60 // Floor to byte, taking care of saturation
61 cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d)
62 {
63 d += 0.5;
64 if (d <= 0) return 0;
65 if (d >= 255.0) return 255;
66
67 return (cmsUInt8Number) _cmsQuickFloorWord(d);
68 }
69
70
71 // Return the size in bytes of a given formatter
72 static
73 cmsUInt32Number trueBytesSize(cmsUInt32Number Format)
74 {
75 cmsUInt32Number fmt_bytes = T_BYTES(Format);
76
77 // For double, the T_BYTES field returns zero
78 if (fmt_bytes == 0)
79 return sizeof(double);
87
88 typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src);
89
90
91 // From 8
92
93 static
94 void copy8(void* dst, const void* src)
95 {
96 memmove(dst, src, 1);
97 }
98
99 static
100 void from8to16(void* dst, const void* src)
101 {
102 cmsUInt8Number n = *(cmsUInt8Number*)src;
103 *(cmsUInt16Number*) dst = FROM_8_TO_16(n);
104 }
105
106 static
107 void from8toFLT(void* dst, const void* src)
108 {
109 *(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f;
110 }
111
112 static
113 void from8toDBL(void* dst, const void* src)
114 {
115 *(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0;
116 }
117
118 static
119 void from8toHLF(void* dst, const void* src)
120 {
121 #ifndef CMS_NO_HALF_SUPPORT
122 cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f;
123 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
124 #else
125 cmsUNUSED_PARAMETER(dst);
126 cmsUNUSED_PARAMETER(src);
127 #endif
128 }
129
130 // From 16
131
132 static
133 void from16to8(void* dst, const void* src)
134 {
135 cmsUInt16Number n = *(cmsUInt16Number*)src;
136 *(cmsUInt8Number*) dst = FROM_16_TO_8(n);
137 }
138
139 static
140 void copy16(void* dst, const void* src)
141 {
142 memmove(dst, src, 2);
143 }
144
145 void from16toFLT(void* dst, const void* src)
146 {
147 *(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
148 }
149
150 void from16toDBL(void* dst, const void* src)
151 {
152 *(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
153 }
154
155 static
156 void from16toHLF(void* dst, const void* src)
157 {
158 #ifndef CMS_NO_HALF_SUPPORT
159 cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f;
160 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
161 #else
162 cmsUNUSED_PARAMETER(dst);
163 cmsUNUSED_PARAMETER(src);
164 #endif
165 }
166
167 // From Float
168
169 static
170 void fromFLTto8(void* dst, const void* src)
171 {
172 cmsFloat32Number n = *(cmsFloat32Number*)src;
173 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
174 }
175
176 static
177 void fromFLTto16(void* dst, const void* src)
178 {
179 cmsFloat32Number n = *(cmsFloat32Number*)src;
180 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
181 }
182
183 static
184 void copy32(void* dst, const void* src)
185 {
186 memmove(dst, src, sizeof(cmsFloat32Number));
187 }
188
189 static
190 void fromFLTtoDBL(void* dst, const void* src)
191 {
192 cmsFloat32Number n = *(cmsFloat32Number*)src;
193 *(cmsFloat64Number*)dst = (cmsFloat64Number)n;
194 }
195
196 static
197 void fromFLTtoHLF(void* dst, const void* src)
198 {
199 #ifndef CMS_NO_HALF_SUPPORT
200 cmsFloat32Number n = *(cmsFloat32Number*)src;
201 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
202 #else
203 cmsUNUSED_PARAMETER(dst);
217 #else
218 cmsUNUSED_PARAMETER(dst);
219 cmsUNUSED_PARAMETER(src);
220 #endif
221
222 }
223
224 static
225 void fromHLFto16(void* dst, const void* src)
226 {
227 #ifndef CMS_NO_HALF_SUPPORT
228 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
229 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
230 #else
231 cmsUNUSED_PARAMETER(dst);
232 cmsUNUSED_PARAMETER(src);
233 #endif
234 }
235
236 static
237 void fromHLFtoFLT(void* dst, const void* src)
238 {
239 #ifndef CMS_NO_HALF_SUPPORT
240 *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src);
241 #else
242 cmsUNUSED_PARAMETER(dst);
243 cmsUNUSED_PARAMETER(src);
244 #endif
245 }
246
247 static
248 void fromHLFtoDBL(void* dst, const void* src)
249 {
250 #ifndef CMS_NO_HALF_SUPPORT
251 *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src);
252 #else
253 cmsUNUSED_PARAMETER(dst);
254 cmsUNUSED_PARAMETER(src);
255 #endif
256 }
257
258 // From double
259 static
260 void fromDBLto8(void* dst, const void* src)
261 {
262 cmsFloat64Number n = *(cmsFloat64Number*)src;
263 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
264 }
265
266 static
267 void fromDBLto16(void* dst, const void* src)
268 {
269 cmsFloat64Number n = *(cmsFloat64Number*)src;
270 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
271 }
272
273 static
274 void fromDBLtoFLT(void* dst, const void* src)
275 {
276 cmsFloat64Number n = *(cmsFloat64Number*)src;
277 *(cmsFloat32Number*)dst = (cmsFloat32Number) n;
278 }
279
280 static
281 void fromDBLtoHLF(void* dst, const void* src)
282 {
283 #ifndef CMS_NO_HALF_SUPPORT
284 cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src;
285 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
286 #else
287 cmsUNUSED_PARAMETER(dst);
288 cmsUNUSED_PARAMETER(src);
289 #endif
290 }
291
292 static
293 void copy64(void* dst, const void* src)
294 {
295 memmove(dst, src, sizeof(cmsFloat64Number));
296 }
297
298
299 // Returns the position (x or y) of the formatter in the table of functions
300 static
301 int FormatterPos(cmsUInt32Number frm)
302 {
303 cmsUInt32Number b = T_BYTES(frm);
304
305 if (b == 0 && T_FLOAT(frm))
306 return 4; // DBL
307 #ifndef CMS_NO_HALF_SUPPORT
308 if (b == 2 && T_FLOAT(frm))
309 return 2; // HLF
310 #endif
311 if (b == 4 && T_FLOAT(frm))
312 return 3; // FLT
313 if (b == 2 && !T_FLOAT(frm))
314 return 1; // 16
315 if (b == 1 && !T_FLOAT(frm))
316 return 0; // 8
317
318 return -1; // not recognized
319 }
320
321 // Obtains a alpha-to-alpha funmction formatter
322 static
323 cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out)
324 {
325 static cmsFormatterAlphaFn FormattersAlpha[5][5] = {
326
327 /* from 8 */ { copy8, from8to16, from8toHLF, from8toFLT, from8toDBL },
328 /* from 16*/ { from16to8, copy16, from16toHLF, from16toFLT, from16toDBL },
329 /* from HLF*/ { fromHLFto8, fromHLFto16, copy16, fromHLFtoFLT, fromHLFtoDBL },
330 /* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTtoHLF, copy32, fromFLTtoDBL },
331 /* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLtoHLF, fromDBLtoFLT, copy64 }};
332
333 int in_n = FormatterPos(in);
334 int out_n = FormatterPos(out);
335
336 if (in_n < 0 || out_n < 0 || in_n > 4 || out_n > 4) {
337
338 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width");
339 return NULL;
340 }
341
342 return FormattersAlpha[in_n][out_n];
343 }
344
345
346
347 // This function computes the distance from each component to the next one in bytes.
348 static
349 void ComputeIncrementsForChunky(cmsUInt32Number Format,
350 cmsUInt32Number ComponentStartingOrder[],
351 cmsUInt32Number ComponentPointerIncrements[])
352 {
353 cmsUInt32Number channels[cmsMAXCHANNELS];
354 cmsUInt32Number extra = T_EXTRA(Format);
355 cmsUInt32Number nchannels = T_CHANNELS(Format);
356 cmsUInt32Number total_chans = nchannels + extra;
498
499 // Exit early if in-place color-management is occurring - no need to copy extra channels to themselves.
500 if (p->InputFormat == p->OutputFormat && in == out)
501 return;
502
503 // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time.
504 nExtra = T_EXTRA(p->InputFormat);
505 if (nExtra != T_EXTRA(p->OutputFormat))
506 return;
507
508 // Anything to do?
509 if (nExtra == 0)
510 return;
511
512 // Compute the increments
513 ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements);
514 ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements);
515
516 // Check for conversions 8, 16, half, float, dbl
517 copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
518
519 if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly
520
521 cmsUInt8Number* SourcePtr;
522 cmsUInt8Number* DestPtr;
523
524 cmsUInt32Number SourceStrideIncrement = 0;
525 cmsUInt32Number DestStrideIncrement = 0;
526
527 // The loop itself
528 for (i = 0; i < LineCount; i++) {
529
530 // Prepare pointers for the loop
531 SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement;
532 DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement;
533
534 for (j = 0; j < PixelsPerLine; j++) {
535
536 copyValueFn(DestPtr, SourcePtr);
537
|
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 // Alpha copy ------------------------------------------------------------------------------------------------------------------
59
60 // This macro return words stored as big endian
61 #define CHANGE_ENDIAN(w) (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))
62
63
64 // Floor to byte, taking care of saturation
65 cmsINLINE cmsUInt8Number _cmsQuickSaturateByte(cmsFloat64Number d)
66 {
67 d += 0.5;
68 if (d <= 0) return 0;
69 if (d >= 255.0) return 255;
70
71 return (cmsUInt8Number) _cmsQuickFloorWord(d);
72 }
73
74
75 // Return the size in bytes of a given formatter
76 static
77 cmsUInt32Number trueBytesSize(cmsUInt32Number Format)
78 {
79 cmsUInt32Number fmt_bytes = T_BYTES(Format);
80
81 // For double, the T_BYTES field returns zero
82 if (fmt_bytes == 0)
83 return sizeof(double);
91
92 typedef void(*cmsFormatterAlphaFn)(void* dst, const void* src);
93
94
95 // From 8
96
97 static
98 void copy8(void* dst, const void* src)
99 {
100 memmove(dst, src, 1);
101 }
102
103 static
104 void from8to16(void* dst, const void* src)
105 {
106 cmsUInt8Number n = *(cmsUInt8Number*)src;
107 *(cmsUInt16Number*) dst = FROM_8_TO_16(n);
108 }
109
110 static
111 void from8to16SE(void* dst, const void* src)
112 {
113 cmsUInt8Number n = *(cmsUInt8Number*)src;
114 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(FROM_8_TO_16(n));
115 }
116
117 static
118 void from8toFLT(void* dst, const void* src)
119 {
120 *(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f;
121 }
122
123 static
124 void from8toDBL(void* dst, const void* src)
125 {
126 *(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0;
127 }
128
129 static
130 void from8toHLF(void* dst, const void* src)
131 {
132 #ifndef CMS_NO_HALF_SUPPORT
133 cmsFloat32Number n = (*(cmsUInt8Number*)src) / 255.0f;
134 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
135 #else
136 cmsUNUSED_PARAMETER(dst);
137 cmsUNUSED_PARAMETER(src);
138 #endif
139 }
140
141 // From 16
142
143 static
144 void from16to8(void* dst, const void* src)
145 {
146 cmsUInt16Number n = *(cmsUInt16Number*)src;
147 *(cmsUInt8Number*) dst = FROM_16_TO_8(n);
148 }
149
150 static
151 void from16SEto8(void* dst, const void* src)
152 {
153 cmsUInt16Number n = *(cmsUInt16Number*)src;
154 *(cmsUInt8Number*)dst = FROM_16_TO_8(CHANGE_ENDIAN(n));
155 }
156
157 static
158 void copy16(void* dst, const void* src)
159 {
160 memmove(dst, src, 2);
161 }
162
163 static
164 void from16to16(void* dst, const void* src)
165 {
166 cmsUInt16Number n = *(cmsUInt16Number*)src;
167 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(n);
168 }
169
170 static
171 void from16toFLT(void* dst, const void* src)
172 {
173 *(cmsFloat32Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
174 }
175
176 static
177 void from16SEtoFLT(void* dst, const void* src)
178 {
179 *(cmsFloat32Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
180 }
181
182 static
183 void from16toDBL(void* dst, const void* src)
184 {
185 *(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
186 }
187
188 static
189 void from16SEtoDBL(void* dst, const void* src)
190 {
191 *(cmsFloat64Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
192 }
193
194 static
195 void from16toHLF(void* dst, const void* src)
196 {
197 #ifndef CMS_NO_HALF_SUPPORT
198 cmsFloat32Number n = (*(cmsUInt16Number*)src) / 65535.0f;
199 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
200 #else
201 cmsUNUSED_PARAMETER(dst);
202 cmsUNUSED_PARAMETER(src);
203 #endif
204 }
205
206 static
207 void from16SEtoHLF(void* dst, const void* src)
208 {
209 #ifndef CMS_NO_HALF_SUPPORT
210 cmsFloat32Number n = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
211 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
212 #else
213 cmsUNUSED_PARAMETER(dst);
214 cmsUNUSED_PARAMETER(src);
215 #endif
216 }
217 // From Float
218
219 static
220 void fromFLTto8(void* dst, const void* src)
221 {
222 cmsFloat32Number n = *(cmsFloat32Number*)src;
223 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0f);
224 }
225
226 static
227 void fromFLTto16(void* dst, const void* src)
228 {
229 cmsFloat32Number n = *(cmsFloat32Number*)src;
230 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
231 }
232
233 static
234 void fromFLTto16SE(void* dst, const void* src)
235 {
236 cmsFloat32Number n = *(cmsFloat32Number*)src;
237 cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
238
239 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
240 }
241
242 static
243 void copy32(void* dst, const void* src)
244 {
245 memmove(dst, src, sizeof(cmsFloat32Number));
246 }
247
248 static
249 void fromFLTtoDBL(void* dst, const void* src)
250 {
251 cmsFloat32Number n = *(cmsFloat32Number*)src;
252 *(cmsFloat64Number*)dst = (cmsFloat64Number)n;
253 }
254
255 static
256 void fromFLTtoHLF(void* dst, const void* src)
257 {
258 #ifndef CMS_NO_HALF_SUPPORT
259 cmsFloat32Number n = *(cmsFloat32Number*)src;
260 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
261 #else
262 cmsUNUSED_PARAMETER(dst);
276 #else
277 cmsUNUSED_PARAMETER(dst);
278 cmsUNUSED_PARAMETER(src);
279 #endif
280
281 }
282
283 static
284 void fromHLFto16(void* dst, const void* src)
285 {
286 #ifndef CMS_NO_HALF_SUPPORT
287 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
288 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
289 #else
290 cmsUNUSED_PARAMETER(dst);
291 cmsUNUSED_PARAMETER(src);
292 #endif
293 }
294
295 static
296 void fromHLFto16SE(void* dst, const void* src)
297 {
298 #ifndef CMS_NO_HALF_SUPPORT
299 cmsFloat32Number n = _cmsHalf2Float(*(cmsUInt16Number*)src);
300 cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
301 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
302 #else
303 cmsUNUSED_PARAMETER(dst);
304 cmsUNUSED_PARAMETER(src);
305 #endif
306 }
307
308 static
309 void fromHLFtoFLT(void* dst, const void* src)
310 {
311 #ifndef CMS_NO_HALF_SUPPORT
312 *(cmsFloat32Number*)dst = _cmsHalf2Float(*(cmsUInt16Number*)src);
313 #else
314 cmsUNUSED_PARAMETER(dst);
315 cmsUNUSED_PARAMETER(src);
316 #endif
317 }
318
319 static
320 void fromHLFtoDBL(void* dst, const void* src)
321 {
322 #ifndef CMS_NO_HALF_SUPPORT
323 *(cmsFloat64Number*)dst = (cmsFloat64Number)_cmsHalf2Float(*(cmsUInt16Number*)src);
324 #else
325 cmsUNUSED_PARAMETER(dst);
326 cmsUNUSED_PARAMETER(src);
327 #endif
328 }
329
330 // From double
331 static
332 void fromDBLto8(void* dst, const void* src)
333 {
334 cmsFloat64Number n = *(cmsFloat64Number*)src;
335 *(cmsUInt8Number*)dst = _cmsQuickSaturateByte(n * 255.0);
336 }
337
338 static
339 void fromDBLto16(void* dst, const void* src)
340 {
341 cmsFloat64Number n = *(cmsFloat64Number*)src;
342 *(cmsUInt16Number*)dst = _cmsQuickSaturateWord(n * 65535.0f);
343 }
344
345 static
346 void fromDBLto16SE(void* dst, const void* src)
347 {
348 cmsFloat64Number n = *(cmsFloat64Number*)src;
349 cmsUInt16Number i = _cmsQuickSaturateWord(n * 65535.0f);
350 *(cmsUInt16Number*)dst = CHANGE_ENDIAN(i);
351 }
352
353 static
354 void fromDBLtoFLT(void* dst, const void* src)
355 {
356 cmsFloat64Number n = *(cmsFloat64Number*)src;
357 *(cmsFloat32Number*)dst = (cmsFloat32Number) n;
358 }
359
360 static
361 void fromDBLtoHLF(void* dst, const void* src)
362 {
363 #ifndef CMS_NO_HALF_SUPPORT
364 cmsFloat32Number n = (cmsFloat32Number) *(cmsFloat64Number*)src;
365 *(cmsUInt16Number*)dst = _cmsFloat2Half(n);
366 #else
367 cmsUNUSED_PARAMETER(dst);
368 cmsUNUSED_PARAMETER(src);
369 #endif
370 }
371
372 static
373 void copy64(void* dst, const void* src)
374 {
375 memmove(dst, src, sizeof(cmsFloat64Number));
376 }
377
378
379 // Returns the position (x or y) of the formatter in the table of functions
380 static
381 int FormatterPos(cmsUInt32Number frm)
382 {
383 cmsUInt32Number b = T_BYTES(frm);
384
385 if (b == 0 && T_FLOAT(frm))
386 return 5; // DBL
387 #ifndef CMS_NO_HALF_SUPPORT
388 if (b == 2 && T_FLOAT(frm))
389 return 3; // HLF
390 #endif
391 if (b == 4 && T_FLOAT(frm))
392 return 4; // FLT
393 if (b == 2 && !T_FLOAT(frm))
394 {
395 if (T_ENDIAN16(frm))
396 return 2; // 16SE
397 else
398 return 1; // 16
399 }
400 if (b == 1 && !T_FLOAT(frm))
401 return 0; // 8
402 return -1; // not recognized
403 }
404
405 // Obtains an alpha-to-alpha function formatter
406 static
407 cmsFormatterAlphaFn _cmsGetFormatterAlpha(cmsContext id, cmsUInt32Number in, cmsUInt32Number out)
408 {
409 static cmsFormatterAlphaFn FormattersAlpha[6][6] = {
410
411 /* from 8 */ { copy8, from8to16, from8to16SE, from8toHLF, from8toFLT, from8toDBL },
412 /* from 16*/ { from16to8, copy16, from16to16, from16toHLF, from16toFLT, from16toDBL },
413 /* from 16SE*/{ from16SEto8, from16to16, copy16, from16SEtoHLF,from16SEtoFLT, from16SEtoDBL },
414 /* from HLF*/ { fromHLFto8, fromHLFto16, fromHLFto16SE, copy16, fromHLFtoFLT, fromHLFtoDBL },
415 /* from FLT*/ { fromFLTto8, fromFLTto16, fromFLTto16SE, fromFLTtoHLF, copy32, fromFLTtoDBL },
416 /* from DBL*/ { fromDBLto8, fromDBLto16, fromDBLto16SE, fromDBLtoHLF, fromDBLtoFLT, copy64 }};
417
418 int in_n = FormatterPos(in);
419 int out_n = FormatterPos(out);
420
421 if (in_n < 0 || out_n < 0 || in_n > 5 || out_n > 5) {
422
423 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized alpha channel width");
424 return NULL;
425 }
426
427 return FormattersAlpha[in_n][out_n];
428 }
429
430
431
432 // This function computes the distance from each component to the next one in bytes.
433 static
434 void ComputeIncrementsForChunky(cmsUInt32Number Format,
435 cmsUInt32Number ComponentStartingOrder[],
436 cmsUInt32Number ComponentPointerIncrements[])
437 {
438 cmsUInt32Number channels[cmsMAXCHANNELS];
439 cmsUInt32Number extra = T_EXTRA(Format);
440 cmsUInt32Number nchannels = T_CHANNELS(Format);
441 cmsUInt32Number total_chans = nchannels + extra;
583
584 // Exit early if in-place color-management is occurring - no need to copy extra channels to themselves.
585 if (p->InputFormat == p->OutputFormat && in == out)
586 return;
587
588 // Make sure we have same number of alpha channels. If not, just return as this should be checked at transform creation time.
589 nExtra = T_EXTRA(p->InputFormat);
590 if (nExtra != T_EXTRA(p->OutputFormat))
591 return;
592
593 // Anything to do?
594 if (nExtra == 0)
595 return;
596
597 // Compute the increments
598 ComputeComponentIncrements(p->InputFormat, Stride->BytesPerPlaneIn, SourceStartingOrder, SourceIncrements);
599 ComputeComponentIncrements(p->OutputFormat, Stride->BytesPerPlaneOut, DestStartingOrder, DestIncrements);
600
601 // Check for conversions 8, 16, half, float, dbl
602 copyValueFn = _cmsGetFormatterAlpha(p->ContextID, p->InputFormat, p->OutputFormat);
603 if (copyValueFn == NULL)
604 return;
605
606 if (nExtra == 1) { // Optimized routine for copying a single extra channel quickly
607
608 cmsUInt8Number* SourcePtr;
609 cmsUInt8Number* DestPtr;
610
611 cmsUInt32Number SourceStrideIncrement = 0;
612 cmsUInt32Number DestStrideIncrement = 0;
613
614 // The loop itself
615 for (i = 0; i < LineCount; i++) {
616
617 // Prepare pointers for the loop
618 SourcePtr = (cmsUInt8Number*)in + SourceStartingOrder[0] + SourceStrideIncrement;
619 DestPtr = (cmsUInt8Number*)out + DestStartingOrder[0] + DestStrideIncrement;
620
621 for (j = 0; j < PixelsPerLine; j++) {
622
623 copyValueFn(DestPtr, SourcePtr);
624
|