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