MagickCore 6.9.13
Loading...
Searching...
No Matches
quantum-private.h
1/*
2 Copyright 1999 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 "magick/memory_.h"
22#include "magick/cache.h"
23#include "magick/image-private.h"
24#include "magick/pixel-accessor.h"
25
26#if defined(__cplusplus) || defined(c_plusplus)
27extern "C" {
28#endif
29
30typedef 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;
44
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
73 **pixels;
74
75 size_t
76 extent;
77
78 EndianType
79 endian;
80
82 state;
83
85 *semaphore;
86
87 size_t
88 signature;
89};
90
91extern MagickPrivate void
92 ResetQuantumState(QuantumInfo *);
93
94static 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
110static inline float HalfToSinglePrecision(const unsigned short half)
111{
112#define ExponentBias (127-15)
113#define ExponentMask (0x7c00U)
114#define ExponentShift 23
115#define SignBitShift 31
116#define SignificandShift 13
117#define SignificandMask (0x00000400U)
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
185static inline unsigned char *PopCharPixel(const unsigned char pixel,
186 unsigned char *magick_restrict pixels)
187{
188 *pixels++=pixel;
189 return(pixels);
190}
191
192static 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
214static 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
232static 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
240static 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
264static 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
284static 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
314static 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
328static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
329 const QuantumAny range)
330{
331#if !defined(MAGICKCORE_HDRI_SUPPORT)
332 return((QuantumAny) ((MagickRealType) range*quantum/QuantumRange));
333#else
334 if ((IsNaN(quantum) != 0) || (quantum <= 0.0f))
335 return((QuantumAny) 0UL);
336 if ((range*(MagickRealType) quantum/(MagickRealType) QuantumRange) >= 18446744073709551615.0)
337 return((QuantumAny) MagickULLConstant(18446744073709551615));
338 return((QuantumAny) (range*(MagickRealType) quantum/(MagickRealType) QuantumRange+0.5));
339#endif
340}
341
342#if (MAGICKCORE_QUANTUM_DEPTH == 8)
343static inline Quantum ScaleCharToQuantum(const unsigned char value)
344{
345 return((Quantum) value);
346}
347
348static 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
357static inline Quantum ScaleMapToQuantum(const MagickRealType value)
358{
359 if (value <= 0.0)
360 return((Quantum) 0);
361 if (value >= MaxMap)
362 return(QuantumRange);
363#if !defined(MAGICKCORE_HDRI_SUPPORT)
364 return((Quantum) (value+0.5));
365#else
366 return((Quantum) value);
367#endif
368}
369
370static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
371{
372#if !defined(MAGICKCORE_HDRI_SUPPORT)
373 return((unsigned int) (16843009UL*quantum));
374#else
375 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
376 return(0U);
377 if ((16843009.0*quantum) >= 4294967295.0)
378 return(4294967295UL);
379 return((unsigned int) (16843009.0*quantum+0.5));
380#endif
381}
382
383static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
384{
385 if (quantum >= (Quantum) MaxMap)
386 return((unsigned int) MaxMap);
387#if !defined(MAGICKCORE_HDRI_SUPPORT)
388 return((unsigned int) quantum);
389#else
390 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
391 return(0U);
392 return((unsigned int) (quantum+0.5));
393#endif
394}
395
396static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
397{
398#if !defined(MAGICKCORE_HDRI_SUPPORT)
399 return((unsigned short) (257UL*quantum));
400#else
401 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
402 return(0);
403 if ((257.0*quantum) >= 65535.0)
404 return(65535);
405 return((unsigned short) (257.0*quantum+0.5));
406#endif
407}
408
409static inline Quantum ScaleShortToQuantum(const unsigned short value)
410{
411#if !defined(MAGICKCORE_HDRI_SUPPORT)
412 return((Quantum) ((value+128U)/257U));
413#else
414 return((Quantum) (value/257.0));
415#endif
416}
417#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
418static inline Quantum ScaleCharToQuantum(const unsigned char value)
419{
420#if !defined(MAGICKCORE_HDRI_SUPPORT)
421 return((Quantum) (257U*value));
422#else
423 return((Quantum) (257.0*value));
424#endif
425}
426
427static inline Quantum ScaleLongToQuantum(const unsigned int value)
428{
429#if !defined(MAGICKCORE_HDRI_SUPPORT)
430 return((Quantum) ((value)/MagickULLConstant(65537)));
431#else
432 return((Quantum) (value/65537.0));
433#endif
434}
435
436static inline Quantum ScaleMapToQuantum(const MagickRealType value)
437{
438 if (value <= 0.0)
439 return((Quantum) 0);
440 if (value >= MaxMap)
441 return(QuantumRange);
442#if !defined(MAGICKCORE_HDRI_SUPPORT)
443 return((Quantum) (value+0.5));
444#else
445 return((Quantum) value);
446#endif
447}
448
449static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
450{
451#if !defined(MAGICKCORE_HDRI_SUPPORT)
452 return((unsigned int) (65537UL*quantum));
453#else
454 if ((IsNaN(quantum) != 0) || (quantum <= 0.0f))
455 return(0U);
456 if ((65537.0f*quantum) >= 4294967295.0f)
457 return(4294967295U);
458 return((unsigned int) (65537.0f*quantum+0.5f));
459#endif
460}
461
462static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
463{
464 if (quantum >= (Quantum) MaxMap)
465 return((unsigned int) MaxMap);
466#if !defined(MAGICKCORE_HDRI_SUPPORT)
467 return((unsigned int) quantum);
468#else
469 if ((IsNaN(quantum) != 0) || (quantum <= 0.0f))
470 return(0U);
471 return((unsigned int) (quantum+0.5f));
472#endif
473}
474
475static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
476{
477#if !defined(MAGICKCORE_HDRI_SUPPORT)
478 return((unsigned short) quantum);
479#else
480 if ((IsNaN(quantum) != 0) || (quantum <= 0.0f))
481 return(0);
482 if (quantum >= 65535.0f)
483 return(65535);
484 return((unsigned short) (quantum+0.5f));
485#endif
486}
487
488static inline Quantum ScaleShortToQuantum(const unsigned short value)
489{
490 return((Quantum) value);
491}
492#elif (MAGICKCORE_QUANTUM_DEPTH == 32)
493static inline Quantum ScaleCharToQuantum(const unsigned char value)
494{
495#if !defined(MAGICKCORE_HDRI_SUPPORT)
496 return((Quantum) (16843009UL*value));
497#else
498 return((Quantum) (16843009.0*value));
499#endif
500}
501
502static inline Quantum ScaleLongToQuantum(const unsigned int value)
503{
504 return((Quantum) value);
505}
506
507static inline Quantum ScaleMapToQuantum(const MagickRealType value)
508{
509 if (value <= 0.0)
510 return((Quantum) 0);
511 if (value >= (Quantum) MaxMap)
512 return(QuantumRange);
513#if !defined(MAGICKCORE_HDRI_SUPPORT)
514 return((Quantum) (65537.0f*value+0.5f));
515#else
516 return((Quantum) (65537.0f*value));
517#endif
518}
519
520static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
521{
522#if !defined(MAGICKCORE_HDRI_SUPPORT)
523 return((unsigned int) quantum);
524#else
525 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
526 return(0U);
527 if ((quantum) >= 4294967295.0)
528 return(4294967295);
529 return((unsigned int) (quantum+0.5));
530#endif
531}
532
533static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
534{
535 if ((quantum/65537) >= (Quantum) MaxMap)
536 return((unsigned int) MaxMap);
537#if !defined(MAGICKCORE_HDRI_SUPPORT)
538 return((unsigned int) ((quantum+MagickULLConstant(32768))/
539 MagickULLConstant(65537)));
540#else
541 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
542 return(0U);
543 return((unsigned int) (quantum/65537.0+0.5));
544#endif
545}
546
547static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
548{
549#if !defined(MAGICKCORE_HDRI_SUPPORT)
550 return((unsigned short) ((quantum+MagickULLConstant(32768))/
551 MagickULLConstant(65537)));
552#else
553 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
554 return(0);
555 if ((quantum/65537.0) >= 65535.0)
556 return(65535);
557 return((unsigned short) (quantum/65537.0+0.5));
558#endif
559}
560
561static inline Quantum ScaleShortToQuantum(const unsigned short value)
562{
563#if !defined(MAGICKCORE_HDRI_SUPPORT)
564 return((Quantum) (65537UL*value));
565#else
566 return((Quantum) (65537.0*value));
567#endif
568}
569#elif (MAGICKCORE_QUANTUM_DEPTH == 64)
570static inline Quantum ScaleCharToQuantum(const unsigned char value)
571{
572 return((Quantum) (72340172838076673.0*value));
573}
574
575static inline Quantum ScaleLongToQuantum(const unsigned int value)
576{
577 return((Quantum) (4294967297.0*value));
578}
579
580static inline Quantum ScaleMapToQuantum(const MagickRealType value)
581{
582 if (value <= 0.0)
583 return((Quantum) 0);
584 if (value >= MaxMap)
585 return(QuantumRange);
586 return((Quantum) (281479271743489.0*value));
587}
588
589static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
590{
591 return((unsigned int) (quantum/4294967297.0+0.5));
592}
593
594static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
595{
596 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
597 return(0U);
598 if ((quantum/281479271743489.0) >= MaxMap)
599 return((unsigned int) MaxMap);
600 return((unsigned int) (quantum/281479271743489.0+0.5));
601}
602
603static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
604{
605 if ((IsNaN(quantum) != 0) || (quantum <= 0.0))
606 return(0);
607 if ((quantum/281479271743489.0) >= 65535.0)
608 return(65535);
609 return((unsigned short) (quantum/281479271743489.0+0.5));
610}
611
612static inline Quantum ScaleShortToQuantum(const unsigned short value)
613{
614 return((Quantum) (281479271743489.0*value));
615}
616#endif
617
618static inline unsigned short SinglePrecisionToHalf(const float value)
619{
620 typedef union _SinglePrecision
621 {
622 unsigned int
623 fixed_point;
624
625 float
626 single_precision;
627 } SinglePrecision;
628
629 int
630 exponent;
631
632 unsigned int
633 significand,
634 sign_bit;
635
636 SinglePrecision
637 map;
638
639 unsigned short
640 half;
641
642 /*
643 The IEEE 754 standard specifies half precision as having:
644
645 Sign bit: 1 bit
646 Exponent width: 5 bits
647 Significand precision: 11 (10 explicitly stored)
648 */
649 map.single_precision=value;
650 sign_bit=(map.fixed_point >> 16) & 0x00008000;
651 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
652 significand=map.fixed_point & 0x007fffff;
653 if (exponent <= 0)
654 {
655 int
656 shift;
657
658 if (exponent < -10)
659 return((unsigned short) sign_bit);
660 significand=significand | 0x00800000;
661 shift=(int) (14-exponent);
662 significand=(unsigned int) ((significand+((1U << (shift-1))-1)+
663 ((significand >> shift) & 0x01)) >> shift);
664 return((unsigned short) (sign_bit | significand));
665 }
666 else
667 if (exponent == (0xff-ExponentBias))
668 {
669 if (significand == 0)
670 return((unsigned short) (sign_bit | ExponentMask));
671 else
672 {
673 significand>>=SignificandShift;
674 half=(unsigned short) (sign_bit | significand |
675 (significand == 0) | ExponentMask);
676 return(half);
677 }
678 }
679 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
680 if ((significand & 0x00800000) != 0)
681 {
682 significand=0;
683 exponent++;
684 }
685 if (exponent > 30)
686 {
687 float
688 alpha;
689
690 int
691 i;
692
693 /*
694 Float overflow.
695 */
696 alpha=1.0e10;
697 for (i=0; i < 10; i++)
698 alpha*=alpha;
699 return((unsigned short) (sign_bit | ExponentMask));
700 }
701 half=(unsigned short) (sign_bit | ((unsigned int) exponent << 10) |
702 (significand >> SignificandShift));
703 return(half);
704}
705
706#if defined(__cplusplus) || defined(c_plusplus)
707}
708#endif
709
710#endif