blob: d1f0af513c6b0db1192f659b6e3358b12114b281 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2 Copyright 1999-2008 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.
6 obtain a copy of the License at
7
8 http://www.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#if defined(__cplusplus) || defined(c_plusplus)
22extern "C" {
23#endif
24
25#include "magick/cache.h"
26
27typedef struct _QuantumState
28{
29 EndianType
30 endian;
31
32 double
33 minimum,
34 scale,
35 inverse_scale;
36
37 unsigned long
38 pixel,
39 bits;
40
41 const unsigned long
42 *mask;
43} QuantumState;
44
45struct _QuantumInfo
46{
47 unsigned long
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 unsigned long
70 number_threads;
71
72 unsigned char
73 **pixels;
74
75 size_t
76 extent;
77
78 SemaphoreInfo
79 *semaphore;
80
81 unsigned long
82 signature;
83};
84
cristy24fb7dc2010-01-10 20:15:51 +000085static inline float Binary16ToSinglePrecision(const unsigned short binary16)
cristy5ab5fc82010-01-05 20:52:48 +000086{
cristy24fb7dc2010-01-10 20:15:51 +000087#define ExponentBias (127-15)
88#define ExponentMask 0x7c00
89#define ExponentShift 23
90#define SignificandShift 13
91#define SignificandMask 0x00000400
92#define SignBitShift 31
cristy5ab5fc82010-01-05 20:52:48 +000093
cristy24fb7dc2010-01-10 20:15:51 +000094 typedef union _SinglePrecision
95 {
96 unsigned int
97 fixed_point;
98
99 float
100 single_precision;
101 } SinglePrecision;
102
103 register unsigned int
104 exponent,
105 significand,
106 sign_bit;
107
108 SinglePrecision
109 map;
110
111 unsigned int
112 value;
113
114 /*
115 The IEEE 754 standard specifies a binary16 as having:
116
117 Sign bit: 1 bit
118 Exponent width: 5 bits
119 Significand precision: 11 (10 explicitly stored)
120 */
121 sign_bit=(unsigned int) ((binary16 >> 15) & 0x00000001);
122 exponent=(unsigned int) ((binary16 >> 10) & 0x0000001f);
123 significand=(unsigned int) (binary16 & 0x000003ff);
124 if (exponent == 0)
125 {
126 if (significand == 0)
127 value=sign_bit << SignBitShift;
128 else
129 {
130 while ((significand & SignificandMask) == 0)
131 {
132 significand<<=1;
133 exponent--;
134 }
135 exponent++;
136 significand&=(~SignificandMask);
137 exponent+=ExponentBias;
138 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
139 (significand << SignificandShift);
140 }
141 }
142 else
143 if (exponent == SignBitShift)
144 {
145 value=(sign_bit << SignBitShift) | 0x7f800000;
146 if (significand != 0)
147 value|=(significand << SignificandShift);
148 }
149 else
150 {
151 exponent+=ExponentBias;
152 significand<<=SignificandShift;
153 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
154 significand;
155 }
156 map.fixed_point=value;
157 return(map.single_precision);
158}
cristy5ab5fc82010-01-05 20:52:48 +0000159
cristy3ed852e2009-09-05 21:47:34 +0000160static inline MagickSizeType GetQuantumRange(const unsigned long depth)
161{
162 return((MagickSizeType) ((MagickULLConstant(1) << (depth-1))+
163 ((MagickULLConstant(1) << (depth-1))-1)));
164}
165
166static inline void InitializeQuantumState(const QuantumInfo *quantum_info,
167 const EndianType endian,QuantumState *quantum_state)
168{
169 static const unsigned long mask[32] =
170 {
171 0x00000000UL, 0x00000001UL, 0x00000003UL, 0x00000007UL, 0x0000000fUL,
172 0x0000001fUL, 0x0000003fUL, 0x0000007fUL, 0x000000ffUL, 0x000001ffUL,
173 0x000003ffUL, 0x000007ffUL, 0x00000fffUL, 0x00001fffUL, 0x00003fffUL,
174 0x00007fffUL, 0x0000ffffUL, 0x0001ffffUL, 0x0003ffffUL, 0x0007ffffUL,
175 0x000fffffUL, 0x001fffffUL, 0x003fffffUL, 0x007fffffUL, 0x00ffffffUL,
176 0x01ffffffUL, 0x03ffffffUL, 0x07ffffffUL, 0x0fffffffUL, 0x1fffffffUL,
177 0x3fffffffUL, 0x7fffffffUL
178 };
179
180 (void) ResetMagickMemory(quantum_state,0,sizeof(&quantum_state));
181 quantum_state->endian=endian;
182 quantum_state->minimum=quantum_info->minimum;
183 quantum_state->scale=quantum_info->scale;
184 quantum_state->inverse_scale=0.0;
185 if (quantum_state->scale != 0.0)
186 quantum_state->inverse_scale=1.0/quantum_state->scale;
187 quantum_state->bits=0;
188 quantum_state->mask=mask;
189}
190
cristy3ed852e2009-09-05 21:47:34 +0000191static inline unsigned char *PopCharPixel(const unsigned char pixel,
192 unsigned char *pixels)
193{
194 *pixels++=pixel;
195 return(pixels);
196}
197
198static inline unsigned char *PopLongPixel(const EndianType endian,
199 const unsigned long pixel,unsigned char *pixels)
200{
201 register unsigned int
202 quantum;
203
204 quantum=(unsigned int) pixel;
205 if (endian != LSBEndian)
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 *pixels++=(unsigned char) (quantum);
214 *pixels++=(unsigned char) (quantum >> 8);
215 *pixels++=(unsigned char) (quantum >> 16);
216 *pixels++=(unsigned char) (quantum >> 24);
217 return(pixels);
218}
219
220static inline unsigned char *PopShortPixel(const EndianType endian,
221 const unsigned short pixel,unsigned char *pixels)
222{
223 register unsigned int
224 quantum;
225
226 quantum=pixel;
227 if (endian != LSBEndian)
228 {
229 *pixels++=(unsigned char) (quantum >> 8);
230 *pixels++=(unsigned char) (quantum);
231 return(pixels);
232 }
233 *pixels++=(unsigned char) (quantum);
234 *pixels++=(unsigned char) (quantum >> 8);
235 return(pixels);
236}
237
238static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
239 unsigned char *pixel)
240{
241 *pixel=(*pixels++);
242 return(pixels);
243}
244
245static inline const unsigned char *PushLongPixel(const EndianType endian,
246 const unsigned char *pixels,unsigned long *pixel)
247{
248 register unsigned int
249 quantum;
250
251 if (endian != LSBEndian)
252 {
253 quantum=(unsigned int) (*pixels++ << 24);
254 quantum|=(unsigned int) (*pixels++ << 16);
255 quantum|=(unsigned int) (*pixels++ << 8);
256 quantum|=(unsigned int) (*pixels++);
257 }
258 else
259 {
260 quantum=(unsigned int) (*pixels++);
261 quantum|=(unsigned int) (*pixels++ << 8);
262 quantum|=(unsigned int) (*pixels++ << 16);
263 quantum|=(unsigned int) (*pixels++ << 24);
264 }
265 *pixel=(unsigned long) (quantum & 0xffffffff);
266 return(pixels);
267}
268
269static inline const unsigned char *PushShortPixel(const EndianType endian,
270 const unsigned char *pixels,unsigned short *pixel)
271{
272 register unsigned int
273 quantum;
274
275 if (endian != LSBEndian)
276 {
277 quantum=(unsigned int) (*pixels++ << 8);
278 quantum|=(unsigned int) *pixels++;
279 }
280 else
281 {
282 quantum=(unsigned int) *pixels++;
283 quantum|=(unsigned int) (*pixels++ << 8);
284 }
285 *pixel=(unsigned short) (quantum & 0xffff);
286 return(pixels);
287}
288
289static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
290 const QuantumAny range)
291{
292#if !defined(MAGICKCORE_HDRI_SUPPORT)
293 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range+0.5));
294#else
295 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range));
296#endif
297}
298
cristy3ed852e2009-09-05 21:47:34 +0000299static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
300 const QuantumAny range)
301{
302#if !defined(MAGICKCORE_HDRI_SUPPORT)
303 return((QuantumAny) (((MagickRealType) range*quantum)/QuantumRange+0.5));
304#else
305 return((QuantumAny) (((MagickRealType) range*quantum)/QuantumRange));
306#endif
307}
308
309#if (MAGICKCORE_QUANTUM_DEPTH == 8)
310static inline Quantum ScaleCharToQuantum(const unsigned char value)
311{
312 return((Quantum) value);
313}
314
315static inline Quantum ScaleLongToQuantum(const unsigned long value)
316{
317#if !defined(MAGICKCORE_HDRI_SUPPORT)
318 return((Quantum) ((value+8421504UL)/16843009UL));
319#else
320 return((Quantum) (value/16843009.0));
321#endif
322}
323
324static inline Quantum ScaleMapToQuantum(const MagickRealType value)
325{
326#if defined(MAGICKCORE_HDRI_SUPPORT)
327 return((Quantum) value);
328#else
329 if (value <= 0.0)
330 return(0);
331 if ((value+0.5) >= MaxMap)
332 return((Quantum) QuantumRange);
333 return((Quantum) (value+0.5));
334#endif
335}
336
337static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
338{
339#if !defined(MAGICKCORE_HDRI_SUPPORT)
340 return((unsigned long) (16843009UL*quantum));
341#else
342 if (quantum <= 0.0)
343 return(0UL);
344 if ((16843009.0*quantum) >= 4294967295.0)
345 return(4294967295UL);
346 return((unsigned long) (16843009.0*quantum+0.5));
347#endif
348}
349
350static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
351{
352 if (quantum >= (Quantum) MaxMap)
353 return((unsigned long) MaxMap);
354#if !defined(MAGICKCORE_HDRI_SUPPORT)
355 return((unsigned long) quantum);
356#else
357 if (quantum < 0.0)
358 return(0UL);
359 return((unsigned long) (quantum+0.5));
360#endif
361}
362
363static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
364{
365#if !defined(MAGICKCORE_HDRI_SUPPORT)
366 return((unsigned short) (257UL*quantum));
367#else
368 if (quantum <= 0.0)
369 return(0);
370 if ((257.0*quantum) >= 65535.0)
371 return(65535);
372 return((unsigned short) (257.0*quantum+0.5));
373#endif
374}
375
376static inline Quantum ScaleShortToQuantum(const unsigned short value)
377{
378#if !defined(MAGICKCORE_HDRI_SUPPORT)
379 return((Quantum) ((value+128UL)/257UL));
380#else
381 return((Quantum) (value/257.0));
382#endif
383}
384#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
385static inline Quantum ScaleCharToQuantum(const unsigned char value)
386{
387#if !defined(MAGICKCORE_HDRI_SUPPORT)
388 return((Quantum) (257UL*value));
389#else
390 return((Quantum) (257.0*value));
391#endif
392}
393
394static inline Quantum ScaleLongToQuantum(const unsigned long value)
395{
396#if !defined(MAGICKCORE_HDRI_SUPPORT)
397 return((Quantum) ((value+MagickULLConstant(32768))/
398 MagickULLConstant(65537)));
399#else
400 return((Quantum) (value/65537.0));
401#endif
402}
403
404static inline Quantum ScaleMapToQuantum(const MagickRealType value)
405{
406#if defined(MAGICKCORE_HDRI_SUPPORT)
407 return((Quantum) value);
408#else
409 if (value <= 0.0)
410 return(0);
411 if ((value+0.5) >= MaxMap)
412 return((Quantum) QuantumRange);
413 return((Quantum) (value+0.5));
414#endif
415}
416
417static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
418{
419#if !defined(MAGICKCORE_HDRI_SUPPORT)
420 return((unsigned long) (65537UL*quantum));
421#else
422 if (quantum <= 0.0)
423 return(0UL);
424 if ((65537.0*quantum) >= 4294967295.0)
425 return(4294967295UL);
426 return((unsigned long) (65537.0*quantum+0.5));
427#endif
428}
429
430static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
431{
432 if (quantum >= (Quantum) MaxMap)
433 return((unsigned long) MaxMap);
434#if !defined(MAGICKCORE_HDRI_SUPPORT)
435 return((unsigned long) quantum);
436#else
437 if (quantum < 0.0)
438 return(0UL);
439 return((unsigned long) (quantum+0.5));
440#endif
441}
442
443static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
444{
445#if !defined(MAGICKCORE_HDRI_SUPPORT)
446 return((unsigned short) quantum);
447#else
448 if (quantum <= 0.0)
449 return(0);
450 if (quantum >= 65535.0)
451 return(65535);
452 return((unsigned short) (quantum+0.5));
453#endif
454}
455
456static inline Quantum ScaleShortToQuantum(const unsigned short value)
457{
458 return((Quantum) value);
459}
460#elif (MAGICKCORE_QUANTUM_DEPTH == 32)
461static inline Quantum ScaleCharToQuantum(const unsigned char value)
462{
463#if !defined(MAGICKCORE_HDRI_SUPPORT)
464 return((Quantum) (16843009UL*value));
465#else
466 return((Quantum) (16843009.0*value));
467#endif
468}
469
470static inline Quantum ScaleLongToQuantum(const unsigned long value)
471{
472 return((Quantum) value);
473}
474
475static inline Quantum ScaleMapToQuantum(const MagickRealType value)
476{
477#if defined(MAGICKCORE_HDRI_SUPPORT)
478 return((Quantum) (65537.0*value));
479#else
480 if (value <= 0.0)
481 return(0);
482 if ((value+0.5) >= MaxMap)
483 return(QuantumRange);
484 return((Quantum) (65537UL*value));
485#endif
486}
487
488static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
489{
490 return((unsigned long) quantum);
491}
492
493static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
494{
495 if ((quantum/65537) >= MaxMap)
496 return((unsigned long) MaxMap);
497#if !defined(MAGICKCORE_HDRI_SUPPORT)
498 return((unsigned long) ((quantum+MagickULLConstant(32768))/
499 MagickULLConstant(65537)));
500#else
501 if (quantum < 0.0)
502 return(0UL);
503 return((unsigned long) (quantum/65537.0)+0.5);
504#endif
505}
506
507static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
508{
509#if !defined(MAGICKCORE_HDRI_SUPPORT)
510 return((unsigned short) ((quantum+MagickULLConstant(32768))/
511 MagickULLConstant(65537)));
512#else
513 if (quantum <= 0.0)
514 return(0);
515 if ((quantum/65537.0) >= 65535.0)
516 return(65535);
517 return((unsigned short) (quantum/65537.0+0.5));
518#endif
519}
520
521static inline Quantum ScaleShortToQuantum(const unsigned short value)
522{
523#if !defined(MAGICKCORE_HDRI_SUPPORT)
524 return((Quantum) (65537UL*value));
525#else
526 return((Quantum) (65537.0*value));
527#endif
528}
529#elif (MAGICKCORE_QUANTUM_DEPTH == 64)
530static inline Quantum ScaleCharToQuantum(const unsigned char value)
531{
532#if !defined(MAGICKCORE_HDRI_SUPPORT)
533 return((Quantum) (MagickULLConstant(71777214294589695)*value));
534#else
535 return((Quantum) (71777214294589695.0*value));
536#endif
537}
538
539static inline Quantum ScaleLongToQuantum(const unsigned long value)
540{
541#if !defined(MAGICKCORE_HDRI_SUPPORT)
542 return((Quantum) (4294967295UL*value));
543#else
544 return((Quantum) (4294967295.0*value));
545#endif
546}
547
548static inline Quantum ScaleMapToQuantum(const MagickRealType value)
549{
550#if defined(MAGICKCORE_HDRI_SUPPORT)
551 return((Quantum) (281479271612415.0*value));
552#else
553 if (value <= 0.0)
554 return(0);
555 if ((value+0.5) >= MaxMap)
556 return(QuantumRange);
557 return((Quantum) (MagickULLConstant(281479271612415)*value));
558#endif
559}
560
561static inline unsigned long ScaleQuantumToLong(const Quantum quantum)
562{
563#if !defined(MAGICKCORE_HDRI_SUPPORT)
564 return((unsigned long) ((quantum+2147483648.0)/4294967297.0));
565#else
566 return((unsigned long) (quantum/4294967297.0+0.5));
567#endif
568}
569
570static inline unsigned long ScaleQuantumToMap(const Quantum quantum)
571{
572 if ((quantum/281479271612415.0) >= MaxMap)
573 return((unsigned long) MaxMap);
574#if !defined(MAGICKCORE_HDRI_SUPPORT)
575 return((unsigned long) ((quantum+2147450879.0)/281479271612415.0));
576#else
577 if (quantum < 0.0)
578 return(0UL);
579 return((unsigned long) (quantum/281479271612415.0)+0.5);
580#endif
581}
582
583static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
584{
585#if !defined(MAGICKCORE_HDRI_SUPPORT)
586 return((unsigned short) ((quantum+2147450879.0)/281479271612415.0));
587#else
588 return((unsigned short) (quantum/281479271612415.0+0.5));
589#endif
590}
591
592static inline Quantum ScaleShortToQuantum(const unsigned short value)
593{
594#if !defined(MAGICKCORE_HDRI_SUPPORT)
595 return((Quantum) (MagickULLConstant(281479271612415)*value));
596#else
597 return((Quantum) (281479271612415.0*value));
598#endif
599}
600#endif
601
cristy24fb7dc2010-01-10 20:15:51 +0000602static inline unsigned short SinglePrecisionToBinary16(const float value)
603{
604 typedef union _SinglePrecision
605 {
606 unsigned int
607 fixed_point;
608
609 float
610 single_precision;
611 } SinglePrecision;
612
613 register int
614 exponent;
615
616 register unsigned int
617 significand,
618 sign_bit;
619
620 SinglePrecision
621 map;
622
623 unsigned short
624 binary16;
625
626 /*
627 The IEEE 754 standard specifies a binary16 as having:
628
629 Sign bit: 1 bit
630 Exponent width: 5 bits
631 Significand precision: 11 (10 explicitly stored)
632 */
633 map.single_precision=value;
634 sign_bit=(map.fixed_point >> 16) & 0x00008000;
635 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
636 significand=map.fixed_point & 0x007fffff;
637 if (exponent <= 0)
638 {
639 long
640 shift;
641
642 if (exponent < -10)
643 return((unsigned short) sign_bit);
644 significand=significand | 0x00800000;
645 shift=14-exponent;
646 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
647 ((significand >> shift) & 0x01)) >> shift);
648 return((unsigned short) (sign_bit | significand));
649 }
650 else
651 if (exponent == (0xff-ExponentBias))
652 {
653 if (significand == 0)
654 return((unsigned short) (sign_bit | ExponentMask));
655 else
656 {
657 significand>>=SignificandShift;
658 binary16=(unsigned short) (sign_bit | significand |
659 (significand == 0) | ExponentMask);
660 return(binary16);
661 }
662 }
663 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
664 if ((significand & 0x00800000) != 0)
665 {
666 significand=0;
667 exponent++;
668 }
669 if (exponent > 30)
670 {
671 float
672 alpha;
673
674 register long
675 i;
676
677 /*
678 Float overflow.
679 */
680 alpha=1.0e10;
681 for (i=0; i < 10; i++)
682 alpha*=alpha;
683 return((unsigned short) (sign_bit | ExponentMask));
684 }
685 binary16=(unsigned short) (sign_bit | (exponent << 10) |
686 (significand >> SignificandShift));
687 return(binary16);
688}
689
cristy3ed852e2009-09-05 21:47:34 +0000690#if defined(__cplusplus) || defined(c_plusplus)
691}
692#endif
693
694#endif