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