1 /*
2 Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization
3 dedicated to making software imaging solutions freely available.
4
5 You may not use this file except in compliance with the License. You may
6 obtain a copy of the License at
7
8 https://imagemagick.org/script/license.php
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15
16 MagickCore quantum inline methods.
17 */
18 #ifndef MAGICKCORE_QUANTUM_PRIVATE_H
19 #define MAGICKCORE_QUANTUM_PRIVATE_H
20
21 #include "MagickCore/memory_.h"
22 #include "MagickCore/cache.h"
23 #include "MagickCore/image-private.h"
24 #include "MagickCore/pixel-accessor.h"
25
26 #if defined(__cplusplus) || defined(c_plusplus)
27 extern "C" {
28 #endif
29
30 typedef struct _QuantumState
31 {
32 double
33 inverse_scale;
34
35 unsigned int
36 pixel;
37
38 size_t
39 bits;
40
41 const unsigned int
42 *mask;
43 } QuantumState;
44
45 struct _QuantumInfo
46 {
47 size_t
48 depth,
49 quantum;
50
51 QuantumFormatType
52 format;
53
54 double
55 minimum,
56 maximum,
57 scale;
58
59 size_t
60 pad;
61
62 MagickBooleanType
63 min_is_white,
64 pack;
65
66 QuantumAlphaType
67 alpha_type;
68
69 size_t
70 number_threads;
71
72 MemoryInfo
73 **pixels;
74
75 size_t
76 extent;
77
78 EndianType
79 endian;
80
81 QuantumState
82 state;
83
84 SemaphoreInfo
85 *semaphore;
86
87 size_t
88 signature;
89 };
90
91 extern MagickPrivate void
92 ResetQuantumState(QuantumInfo *);
93
GetQuantumRange(const size_t depth)94 static inline MagickSizeType GetQuantumRange(const size_t depth)
95 {
96 MagickSizeType
97 one;
98
99 size_t
100 max_depth;
101
102 if (depth == 0)
103 return(0);
104 one=1;
105 max_depth=8*sizeof(MagickSizeType);
106 return((MagickSizeType) ((one << (MagickMin(depth,max_depth)-1))+
107 ((one << (MagickMin(depth,max_depth)-1))-1)));
108 }
109
HalfToSinglePrecision(const unsigned short half)110 static inline float HalfToSinglePrecision(const unsigned short half)
111 {
112 #define ExponentBias (127-15)
113 #define ExponentMask 0x7c00
114 #define ExponentShift 23
115 #define SignBitShift 31
116 #define SignificandShift 13
117 #define SignificandMask 0x00000400
118
119 typedef union _SinglePrecision
120 {
121 unsigned int
122 fixed_point;
123
124 float
125 single_precision;
126 } SinglePrecision;
127
128 unsigned int
129 exponent,
130 significand,
131 sign_bit;
132
133 SinglePrecision
134 map;
135
136 unsigned int
137 value;
138
139 /*
140 The IEEE 754 standard specifies half precision as having:
141
142 Sign bit: 1 bit
143 Exponent width: 5 bits
144 Significand precision: 11 (10 explicitly stored)
145 */
146 sign_bit=(unsigned int) ((half >> 15) & 0x00000001);
147 exponent=(unsigned int) ((half >> 10) & 0x0000001f);
148 significand=(unsigned int) (half & 0x000003ff);
149 if (exponent == 0)
150 {
151 if (significand == 0)
152 value=sign_bit << SignBitShift;
153 else
154 {
155 while ((significand & SignificandMask) == 0)
156 {
157 significand<<=1;
158 exponent--;
159 }
160 exponent++;
161 significand&=(~SignificandMask);
162 exponent+=ExponentBias;
163 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
164 (significand << SignificandShift);
165 }
166 }
167 else
168 if (exponent == SignBitShift)
169 {
170 value=(sign_bit << SignBitShift) | 0x7f800000;
171 if (significand != 0)
172 value|=(significand << SignificandShift);
173 }
174 else
175 {
176 exponent+=ExponentBias;
177 significand<<=SignificandShift;
178 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
179 significand;
180 }
181 map.fixed_point=value;
182 return(map.single_precision);
183 }
184
PopCharPixel(const unsigned char pixel,unsigned char * magick_restrict pixels)185 static inline unsigned char *PopCharPixel(const unsigned char pixel,
186 unsigned char *magick_restrict pixels)
187 {
188 *pixels++=pixel;
189 return(pixels);
190 }
191
PopLongPixel(const EndianType endian,const unsigned int pixel,unsigned char * magick_restrict pixels)192 static inline unsigned char *PopLongPixel(const EndianType endian,
193 const unsigned int pixel,unsigned char *magick_restrict pixels)
194 {
195 unsigned int
196 quantum;
197
198 quantum=(unsigned int) pixel;
199 if (endian == LSBEndian)
200 {
201 *pixels++=(unsigned char) (quantum);
202 *pixels++=(unsigned char) (quantum >> 8);
203 *pixels++=(unsigned char) (quantum >> 16);
204 *pixels++=(unsigned char) (quantum >> 24);
205 return(pixels);
206 }
207 *pixels++=(unsigned char) (quantum >> 24);
208 *pixels++=(unsigned char) (quantum >> 16);
209 *pixels++=(unsigned char) (quantum >> 8);
210 *pixels++=(unsigned char) (quantum);
211 return(pixels);
212 }
213
PopShortPixel(const EndianType endian,const unsigned short pixel,unsigned char * magick_restrict pixels)214 static inline unsigned char *PopShortPixel(const EndianType endian,
215 const unsigned short pixel,unsigned char *magick_restrict pixels)
216 {
217 unsigned int
218 quantum;
219
220 quantum=pixel;
221 if (endian == LSBEndian)
222 {
223 *pixels++=(unsigned char) (quantum);
224 *pixels++=(unsigned char) (quantum >> 8);
225 return(pixels);
226 }
227 *pixels++=(unsigned char) (quantum >> 8);
228 *pixels++=(unsigned char) (quantum);
229 return(pixels);
230 }
231
PushCharPixel(const unsigned char * magick_restrict pixels,unsigned char * magick_restrict pixel)232 static inline const unsigned char *PushCharPixel(
233 const unsigned char *magick_restrict pixels,
234 unsigned char *magick_restrict pixel)
235 {
236 *pixel=(*pixels++);
237 return(pixels);
238 }
239
PushLongPixel(const EndianType endian,const unsigned char * magick_restrict pixels,unsigned int * magick_restrict pixel)240 static inline const unsigned char *PushLongPixel(const EndianType endian,
241 const unsigned char *magick_restrict pixels,
242 unsigned int *magick_restrict pixel)
243 {
244 unsigned int
245 quantum;
246
247 if (endian == LSBEndian)
248 {
249 quantum=((unsigned int) *pixels++);
250 quantum|=((unsigned int) *pixels++ << 8);
251 quantum|=((unsigned int) *pixels++ << 16);
252 quantum|=((unsigned int) *pixels++ << 24);
253 *pixel=quantum;
254 return(pixels);
255 }
256 quantum=((unsigned int) *pixels++ << 24);
257 quantum|=((unsigned int) *pixels++ << 16);
258 quantum|=((unsigned int) *pixels++ << 8);
259 quantum|=((unsigned int) *pixels++);
260 *pixel=quantum;
261 return(pixels);
262 }
263
PushShortPixel(const EndianType endian,const unsigned char * magick_restrict pixels,unsigned short * magick_restrict pixel)264 static inline const unsigned char *PushShortPixel(const EndianType endian,
265 const unsigned char *magick_restrict pixels,
266 unsigned short *magick_restrict pixel)
267 {
268 unsigned int
269 quantum;
270
271 if (endian == LSBEndian)
272 {
273 quantum=(unsigned int) *pixels++;
274 quantum|=(unsigned int) (*pixels++ << 8);
275 *pixel=(unsigned short) (quantum & 0xffff);
276 return(pixels);
277 }
278 quantum=(unsigned int) (*pixels++ << 8);
279 quantum|=(unsigned int) *pixels++;
280 *pixel=(unsigned short) (quantum & 0xffff);
281 return(pixels);
282 }
283
PushFloatPixel(const EndianType endian,const unsigned char * magick_restrict pixels,MagickFloatType * magick_restrict pixel)284 static inline const unsigned char *PushFloatPixel(const EndianType endian,
285 const unsigned char *magick_restrict pixels,
286 MagickFloatType *magick_restrict pixel)
287 {
288 union
289 {
290 unsigned int
291 unsigned_value;
292
293 MagickFloatType
294 float_value;
295 } quantum;
296
297 if (endian == LSBEndian)
298 {
299 quantum.unsigned_value=((unsigned int) *pixels++);
300 quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
301 quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
302 quantum.unsigned_value|=((unsigned int) *pixels++ << 24);
303 *pixel=quantum.float_value;
304 return(pixels);
305 }
306 quantum.unsigned_value=((unsigned int) *pixels++ << 24);
307 quantum.unsigned_value|=((unsigned int) *pixels++ << 16);
308 quantum.unsigned_value|=((unsigned int) *pixels++ << 8);
309 quantum.unsigned_value|=((unsigned int) *pixels++);
310 *pixel=quantum.float_value;
311 return(pixels);
312 }
313
ScaleAnyToQuantum(const QuantumAny quantum,const QuantumAny range)314 static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
315 const QuantumAny range)
316 {
317 if (quantum > range)
318 return(QuantumRange);
319 #if !defined(MAGICKCORE_HDRI_SUPPORT)
320 return((Quantum) ((double) QuantumRange*(quantum*
321 PerceptibleReciprocal((double) range))+0.5));
322 #else
323 return((Quantum) ((double) QuantumRange*(quantum*
324 PerceptibleReciprocal((double) range))));
325 #endif
326 }
327
ScaleQuantumToAny(const Quantum quantum,const QuantumAny range)328 static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
329 const QuantumAny range)
330 {
331 #if !defined(MAGICKCORE_HDRI_SUPPORT)
332 return((QuantumAny) ((double) range*quantum/QuantumRange));
333 #else
334 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
335 return((QuantumAny) 0UL);
336 if (((double) range*quantum/QuantumRange) >= 18446744073709551615.0)
337 return((QuantumAny) MagickULLConstant(18446744073709551615));
338 return((QuantumAny) ((double) range*quantum/QuantumRange+0.5));
339 #endif
340 }
341
342 #if (MAGICKCORE_QUANTUM_DEPTH == 8)
ScaleCharToQuantum(const unsigned char value)343 static inline Quantum ScaleCharToQuantum(const unsigned char value)
344 {
345 return((Quantum) value);
346 }
347
ScaleLongToQuantum(const unsigned int value)348 static inline Quantum ScaleLongToQuantum(const unsigned int value)
349 {
350 #if !defined(MAGICKCORE_HDRI_SUPPORT)
351 return((Quantum) ((value)/16843009UL));
352 #else
353 return((Quantum) (value/16843009.0));
354 #endif
355 }
356
ScaleLongLongToQuantum(const MagickSizeType value)357 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
358 {
359 #if !defined(MAGICKCORE_HDRI_SUPPORT)
360 return((Quantum) (value/MagickULLConstant(72340172838076673)));
361 #else
362 return((Quantum) (value/72340172838076673.0));
363 #endif
364 }
365
ScaleMapToQuantum(const MagickRealType value)366 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
367 {
368 if (value <= 0.0)
369 return((Quantum) 0);
370 if (value >= MaxMap)
371 return(QuantumRange);
372 #if !defined(MAGICKCORE_HDRI_SUPPORT)
373 return((Quantum) (value+0.5));
374 #else
375 return((Quantum) value);
376 #endif
377 }
378
ScaleQuantumToLong(const Quantum quantum)379 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
380 {
381 #if !defined(MAGICKCORE_HDRI_SUPPORT)
382 return((unsigned int) (16843009UL*quantum));
383 #else
384 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
385 return(0U);
386 if ((16843009.0*quantum) >= 4294967295.0)
387 return(4294967295UL);
388 return((unsigned int) (16843009.0*quantum+0.5));
389 #endif
390 }
391
ScaleQuantumToLongLong(const Quantum quantum)392 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
393 {
394 #if !defined(MAGICKCORE_HDRI_SUPPORT)
395 return((MagickSizeType) (MagickULLConstant(72340172838076673)*quantum));
396 #else
397 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
398 return(0UL);
399 if ((72340172838076673.0*quantum) >= 18446744073709551615.0)
400 return(MagickULLConstant(18446744073709551615));
401 return((MagickSizeType) (72340172838076673*quantum+0.5));
402 #endif
403 }
404
ScaleQuantumToMap(const Quantum quantum)405 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
406 {
407 if (quantum >= (Quantum) MaxMap)
408 return((unsigned int) MaxMap);
409 #if !defined(MAGICKCORE_HDRI_SUPPORT)
410 return((unsigned int) quantum);
411 #else
412 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
413 return(0U);
414 return((unsigned int) (quantum+0.5));
415 #endif
416 }
417
ScaleQuantumToShort(const Quantum quantum)418 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
419 {
420 #if !defined(MAGICKCORE_HDRI_SUPPORT)
421 return((unsigned short) (257UL*quantum));
422 #else
423 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
424 return(0);
425 if ((257.0*quantum) >= 65535.0)
426 return(65535);
427 return((unsigned short) (257.0*quantum+0.5));
428 #endif
429 }
430
ScaleShortToQuantum(const unsigned short value)431 static inline Quantum ScaleShortToQuantum(const unsigned short value)
432 {
433 #if !defined(MAGICKCORE_HDRI_SUPPORT)
434 return((Quantum) ((value+128U)/257U));
435 #else
436 return((Quantum) (value/257.0));
437 #endif
438 }
439 #elif (MAGICKCORE_QUANTUM_DEPTH == 16)
ScaleCharToQuantum(const unsigned char value)440 static inline Quantum ScaleCharToQuantum(const unsigned char value)
441 {
442 #if !defined(MAGICKCORE_HDRI_SUPPORT)
443 return((Quantum) (257U*value));
444 #else
445 return((Quantum) (257.0*value));
446 #endif
447 }
448
ScaleLongToQuantum(const unsigned int value)449 static inline Quantum ScaleLongToQuantum(const unsigned int value)
450 {
451 #if !defined(MAGICKCORE_HDRI_SUPPORT)
452 return((Quantum) ((value)/MagickULLConstant(65537)));
453 #else
454 return((Quantum) (value/65537.0));
455 #endif
456 }
457
ScaleLongLongToQuantum(const MagickSizeType value)458 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
459 {
460 #if !defined(MAGICKCORE_HDRI_SUPPORT)
461 return((Quantum) ((value)/MagickULLConstant(281479271743489)));
462 #else
463 return((Quantum) (value/281479271743489.0));
464 #endif
465 }
466
ScaleMapToQuantum(const MagickRealType value)467 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
468 {
469 if (value <= 0.0)
470 return((Quantum) 0);
471 if (value >= MaxMap)
472 return(QuantumRange);
473 #if !defined(MAGICKCORE_HDRI_SUPPORT)
474 return((Quantum) (value+0.5));
475 #else
476 return((Quantum) value);
477 #endif
478 }
479
ScaleQuantumToLong(const Quantum quantum)480 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
481 {
482 #if !defined(MAGICKCORE_HDRI_SUPPORT)
483 return((unsigned int) (65537UL*quantum));
484 #else
485 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
486 return(0U);
487 if ((65537.0*quantum) >= 4294967295.0)
488 return(4294967295U);
489 return((unsigned int) (65537.0*quantum+0.5));
490 #endif
491 }
492
ScaleQuantumToLongLong(const Quantum quantum)493 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
494 {
495 #if !defined(MAGICKCORE_HDRI_SUPPORT)
496 return((MagickSizeType) (MagickULLConstant(281479271743489)*quantum));
497 #else
498 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
499 return(0UL);
500 if ((281479271743489.0*quantum) >= 18446744073709551615.0)
501 return(MagickULLConstant(18446744073709551615));
502 return((MagickSizeType) (281479271743489.0*quantum+0.5));
503 #endif
504 }
505
ScaleQuantumToMap(const Quantum quantum)506 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
507 {
508 if (quantum >= (Quantum) MaxMap)
509 return((unsigned int) MaxMap);
510 #if !defined(MAGICKCORE_HDRI_SUPPORT)
511 return((unsigned int) quantum);
512 #else
513 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
514 return(0U);
515 return((unsigned int) (quantum+0.5));
516 #endif
517 }
518
ScaleQuantumToShort(const Quantum quantum)519 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
520 {
521 #if !defined(MAGICKCORE_HDRI_SUPPORT)
522 return((unsigned short) quantum);
523 #else
524 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
525 return(0);
526 if (quantum >= 65535.0)
527 return(65535);
528 return((unsigned short) (quantum+0.5));
529 #endif
530 }
531
ScaleShortToQuantum(const unsigned short value)532 static inline Quantum ScaleShortToQuantum(const unsigned short value)
533 {
534 return((Quantum) value);
535 }
536 #elif (MAGICKCORE_QUANTUM_DEPTH == 32)
ScaleCharToQuantum(const unsigned char value)537 static inline Quantum ScaleCharToQuantum(const unsigned char value)
538 {
539 #if !defined(MAGICKCORE_HDRI_SUPPORT)
540 return((Quantum) (16843009UL*value));
541 #else
542 return((Quantum) (16843009.0*value));
543 #endif
544 }
545
ScaleLongToQuantum(const unsigned int value)546 static inline Quantum ScaleLongToQuantum(const unsigned int value)
547 {
548 return((Quantum) value);
549 }
550
ScaleLongLongToQuantum(const MagickSizeType value)551 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
552 {
553 #if !defined(MAGICKCORE_HDRI_SUPPORT)
554 return((Quantum) ((value)/MagickULLConstant(4294967297)));
555 #else
556 return((Quantum) (value/4294967297.0));
557 #endif
558 }
559
ScaleMapToQuantum(const MagickRealType value)560 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
561 {
562 if (value <= 0.0)
563 return((Quantum) 0);
564 if (value >= (Quantum) MaxMap)
565 return(QuantumRange);
566 #if !defined(MAGICKCORE_HDRI_SUPPORT)
567 return((Quantum) (65537.0*value+0.5));
568 #else
569 return((Quantum) (65537.0*value));
570 #endif
571 }
572
ScaleQuantumToLong(const Quantum quantum)573 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
574 {
575 #if !defined(MAGICKCORE_HDRI_SUPPORT)
576 return((unsigned int) quantum);
577 #else
578 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
579 return(0U);
580 if ((quantum) >= 4294967295.0)
581 return(4294967295);
582 return((unsigned int) (quantum+0.5));
583 #endif
584 }
585
ScaleQuantumToLongLong(const Quantum quantum)586 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
587 {
588 #if !defined(MAGICKCORE_HDRI_SUPPORT)
589 return((MagickSizeType) (MagickULLConstant(4294967297)*quantum));
590 #else
591 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
592 return(0UL);
593 if ((4294967297.0*quantum) >= 18446744073709551615.0)
594 return(MagickULLConstant(18446744073709551615));
595 return((MagickSizeType) (4294967297.0*quantum+0.5));
596 #endif
597 }
598
ScaleQuantumToMap(const Quantum quantum)599 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
600 {
601 if ((quantum/65537) >= (Quantum) MaxMap)
602 return((unsigned int) MaxMap);
603 #if !defined(MAGICKCORE_HDRI_SUPPORT)
604 return((unsigned int) ((quantum+MagickULLConstant(32768))/
605 MagickULLConstant(65537)));
606 #else
607 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
608 return(0U);
609 return((unsigned int) (quantum/65537.0+0.5));
610 #endif
611 }
612
ScaleQuantumToShort(const Quantum quantum)613 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
614 {
615 #if !defined(MAGICKCORE_HDRI_SUPPORT)
616 return((unsigned short) ((quantum+MagickULLConstant(32768))/
617 MagickULLConstant(65537)));
618 #else
619 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
620 return(0);
621 if ((quantum/65537.0) >= 65535.0)
622 return(65535);
623 return((unsigned short) (quantum/65537.0+0.5));
624 #endif
625 }
626
ScaleShortToQuantum(const unsigned short value)627 static inline Quantum ScaleShortToQuantum(const unsigned short value)
628 {
629 #if !defined(MAGICKCORE_HDRI_SUPPORT)
630 return((Quantum) (65537UL*value));
631 #else
632 return((Quantum) (65537.0*value));
633 #endif
634 }
635 #elif (MAGICKCORE_QUANTUM_DEPTH == 64)
ScaleCharToQuantum(const unsigned char value)636 static inline Quantum ScaleCharToQuantum(const unsigned char value)
637 {
638 return((Quantum) (72340172838076673.0*value));
639 }
640
ScaleLongToQuantum(const unsigned int value)641 static inline Quantum ScaleLongToQuantum(const unsigned int value)
642 {
643 return((Quantum) (4294967297.0*value));
644 }
645
ScaleLongLongToQuantum(const MagickSizeType value)646 static inline Quantum ScaleLongLongToQuantum(const MagickSizeType value)
647 {
648 return((Quantum) (value));
649 }
650
ScaleMapToQuantum(const MagickRealType value)651 static inline Quantum ScaleMapToQuantum(const MagickRealType value)
652 {
653 if (value <= 0.0)
654 return((Quantum) 0);
655 if (value >= MaxMap)
656 return(QuantumRange);
657 return((Quantum) (281479271743489.0*value));
658 }
659
ScaleQuantumToLong(const Quantum quantum)660 static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
661 {
662 return((unsigned int) (quantum/4294967297.0+0.5));
663 }
664
ScaleQuantumToLongLong(const Quantum quantum)665 static inline MagickSizeType ScaleQuantumToLongLong(const Quantum quantum)
666 {
667 #if !defined(MAGICKCORE_HDRI_SUPPORT)
668 return((MagickSizeType) quantum);
669 #else
670 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
671 return(0UL);
672 if (quantum >= 18446744073709551615.0)
673 return(MagickULLConstant(18446744073709551615));
674 return((MagickSizeType) (quantum+0.5));
675 #endif
676 }
677
ScaleQuantumToMap(const Quantum quantum)678 static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
679 {
680 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
681 return(0U);
682 if ((quantum/281479271743489.0) >= MaxMap)
683 return((unsigned int) MaxMap);
684 return((unsigned int) (quantum/281479271743489.0+0.5));
685 }
686
ScaleQuantumToShort(const Quantum quantum)687 static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
688 {
689 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
690 return(0);
691 if ((quantum/281479271743489.0) >= 65535.0)
692 return(65535);
693 return((unsigned short) (quantum/281479271743489.0+0.5));
694 }
695
ScaleShortToQuantum(const unsigned short value)696 static inline Quantum ScaleShortToQuantum(const unsigned short value)
697 {
698 return((Quantum) (281479271743489.0*value));
699 }
700 #endif
701
SinglePrecisionToHalf(const float value)702 static inline unsigned short SinglePrecisionToHalf(const float value)
703 {
704 typedef union _SinglePrecision
705 {
706 unsigned int
707 fixed_point;
708
709 float
710 single_precision;
711 } SinglePrecision;
712
713 int
714 exponent;
715
716 unsigned int
717 significand,
718 sign_bit;
719
720 SinglePrecision
721 map;
722
723 unsigned short
724 half;
725
726 /*
727 The IEEE 754 standard specifies half precision as having:
728
729 Sign bit: 1 bit
730 Exponent width: 5 bits
731 Significand precision: 11 (10 explicitly stored)
732 */
733 map.single_precision=value;
734 sign_bit=(map.fixed_point >> 16) & 0x00008000;
735 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
736 significand=map.fixed_point & 0x007fffff;
737 if (exponent <= 0)
738 {
739 int
740 shift;
741
742 if (exponent < -10)
743 return((unsigned short) sign_bit);
744 significand=significand | 0x00800000;
745 shift=(int) (14-exponent);
746 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
747 ((significand >> shift) & 0x01)) >> shift);
748 return((unsigned short) (sign_bit | significand));
749 }
750 else
751 if (exponent == (0xff-ExponentBias))
752 {
753 if (significand == 0)
754 return((unsigned short) (sign_bit | ExponentMask));
755 else
756 {
757 significand>>=SignificandShift;
758 half=(unsigned short) (sign_bit | significand |
759 (significand == 0) | ExponentMask);
760 return(half);
761 }
762 }
763 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
764 if ((significand & 0x00800000) != 0)
765 {
766 significand=0;
767 exponent++;
768 }
769 if (exponent > 30)
770 {
771 float
772 alpha;
773
774 int
775 i;
776
777 /*
778 Float overflow.
779 */
780 alpha=1.0e10;
781 for (i=0; i < 10; i++)
782 alpha*=alpha;
783 return((unsigned short) (sign_bit | ExponentMask));
784 }
785 half=(unsigned short) (sign_bit | (exponent << 10) |
786 (significand >> SignificandShift));
787 return(half);
788 }
789
790 #if defined(__cplusplus) || defined(c_plusplus)
791 }
792 #endif
793
794 #endif
795