blob: 2d08b015c965a00cec18726ffe85783a63725b1d [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
cristyc9672a92010-01-06 00:57:45 +000085typedef union _HalfFloat
cristy5ab5fc82010-01-05 20:52:48 +000086{
87 unsigned int
88 cf_uint;
89
90 float
91 cf_float;
cristyc9672a92010-01-06 00:57:45 +000092} HalfFloat;
cristy5ab5fc82010-01-05 20:52:48 +000093
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
cristy3ed852e2009-09-05 21:47:34 +0000125static inline unsigned char *PopCharPixel(const unsigned char pixel,
126 unsigned char *pixels)
127{
128 *pixels++=pixel;
129 return(pixels);
130}
131
132static inline unsigned char *PopLongPixel(const EndianType endian,
133 const unsigned long pixel,unsigned char *pixels)
134{
135 register unsigned int
136 quantum;
137
138 quantum=(unsigned int) pixel;
139 if (endian != LSBEndian)
140 {
141 *pixels++=(unsigned char) (quantum >> 24);
142 *pixels++=(unsigned char) (quantum >> 16);
143 *pixels++=(unsigned char) (quantum >> 8);
144 *pixels++=(unsigned char) (quantum);
145 return(pixels);
146 }
147 *pixels++=(unsigned char) (quantum);
148 *pixels++=(unsigned char) (quantum >> 8);
149 *pixels++=(unsigned char) (quantum >> 16);
150 *pixels++=(unsigned char) (quantum >> 24);
151 return(pixels);
152}
153
154static inline unsigned char *PopShortPixel(const EndianType endian,
155 const unsigned short pixel,unsigned char *pixels)
156{
157 register unsigned int
158 quantum;
159
160 quantum=pixel;
161 if (endian != LSBEndian)
162 {
163 *pixels++=(unsigned char) (quantum >> 8);
164 *pixels++=(unsigned char) (quantum);
165 return(pixels);
166 }
167 *pixels++=(unsigned char) (quantum);
168 *pixels++=(unsigned char) (quantum >> 8);
169 return(pixels);
170}
171
172static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
173 unsigned char *pixel)
174{
175 *pixel=(*pixels++);
176 return(pixels);
177}
178
179static inline const unsigned char *PushLongPixel(const EndianType endian,
180 const unsigned char *pixels,unsigned long *pixel)
181{
182 register unsigned int
183 quantum;
184
185 if (endian != LSBEndian)
186 {
187 quantum=(unsigned int) (*pixels++ << 24);
188 quantum|=(unsigned int) (*pixels++ << 16);
189 quantum|=(unsigned int) (*pixels++ << 8);
190 quantum|=(unsigned int) (*pixels++);
191 }
192 else
193 {
194 quantum=(unsigned int) (*pixels++);
195 quantum|=(unsigned int) (*pixels++ << 8);
196 quantum|=(unsigned int) (*pixels++ << 16);
197 quantum|=(unsigned int) (*pixels++ << 24);
198 }
199 *pixel=(unsigned long) (quantum & 0xffffffff);
200 return(pixels);
201}
202
203static inline const unsigned char *PushShortPixel(const EndianType endian,
204 const unsigned char *pixels,unsigned short *pixel)
205{
206 register unsigned int
207 quantum;
208
209 if (endian != LSBEndian)
210 {
211 quantum=(unsigned int) (*pixels++ << 8);
212 quantum|=(unsigned int) *pixels++;
213 }
214 else
215 {
216 quantum=(unsigned int) *pixels++;
217 quantum|=(unsigned int) (*pixels++ << 8);
218 }
219 *pixel=(unsigned short) (quantum & 0xffff);
220 return(pixels);
221}
222
223static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
224 const QuantumAny range)
225{
226#if !defined(MAGICKCORE_HDRI_SUPPORT)
227 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range+0.5));
228#else
229 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range));
230#endif
231}
232
cristyc9672a92010-01-06 00:57:45 +0000233static inline unsigned short ScaleFloatToHalf(const float value)
234{
235#define ExponentBias (127-15)
236#define ExponentMask 0x7c00
237#define ExponentShift 23
238#define MantissaShift 13
239
240 HalfFloat
241 pixel;
242
243 register int
244 exponent;
245
246 register unsigned int
247 mantissa,
248 sign;
249
250 unsigned short
251 half;
252
253 pixel.cf_float=value;
254 sign=(pixel.cf_uint >> 16) & 0x00008000;
255 exponent=(int) ((pixel.cf_uint >> ExponentShift) & 0x000000ff)-
256 ExponentBias;
257 mantissa=pixel.cf_uint & 0x007fffff;
258 if (exponent <= 0)
259 {
260 long
261 shift;
262
263 if (exponent < -10)
264 return((unsigned short) sign);
265 mantissa=mantissa | 0x00800000;
266 shift=14-exponent;
267 mantissa=(unsigned int) ((mantissa+((1 << (shift-1))-1)+
268 ((mantissa >> shift) & 0x01)) >> shift);
269 return((unsigned short) (sign | mantissa));
270 }
271 else
272 if (exponent == (0xff-ExponentBias))
273 {
274 if (mantissa == 0)
275 return((unsigned short) (sign | ExponentMask));
276 else
277 {
278 mantissa>>=MantissaShift;
279 half=(unsigned short) (sign | mantissa | (mantissa == 0) |
280 ExponentMask);
281 return(half);
282 }
283 }
284 mantissa=mantissa+((mantissa >> MantissaShift) & 0x01)+0x00000fff;
285 if ((mantissa & 0x00800000) != 0)
286 {
287 mantissa=0;
288 exponent++;
289 }
290 if (exponent > 30)
291 {
292 float
293 alpha;
294
295 register long
296 i;
297
298 /*
299 Float overflow.
300 */
301 alpha=1e10;
302 for (i=0; i < 10; i++)
303 alpha*=alpha;
304 return((unsigned short) (sign | ExponentMask));
305 }
306 half=(unsigned short) (sign | (exponent << 10) |
307 (mantissa >> MantissaShift));
308 return(half);
309}
310
311static inline float ScaleHalfToFloat(const unsigned short quantum)
312{
313#define MantissaMask 0x00000400
314#define SignShift 31
315
316 HalfFloat
317 pixel;
318
319 register unsigned int
320 exponent,
321 mantissa,
322 sign;
323
324 unsigned int
325 value;
326
327 sign=(unsigned int) ((quantum >> 15) & 0x00000001);
328 exponent=(unsigned int) ((quantum >> 10) & 0x0000001f);
329 mantissa=(unsigned int) (quantum & 0x000003ff);
330 if (exponent == 0)
331 {
332 if (mantissa == 0)
333 value=sign << SignShift;
334 else
335 {
336 while ((mantissa & MantissaMask) == 0)
337 {
338 mantissa<<=1;
339 exponent--;
340 }
341 exponent++;
342 mantissa&=(~MantissaMask);
343 exponent+=ExponentBias;
344 value=(sign << SignShift) | (exponent << ExponentShift) |
345 (mantissa << MantissaShift);
346 }
347 }
348 else
349 if (exponent == SignShift)
350 {
351 value=(sign << SignShift) | 0x7f800000;
352 if (mantissa != 0)
353 value|=(mantissa << MantissaShift);
354 }
355 else
356 {
357 exponent+=ExponentBias;
358 mantissa=mantissa << MantissaShift;
359 value=(sign << SignShift) | (exponent << ExponentShift) | mantissa;
360 }
361 pixel.cf_uint=value;
362 return(pixel.cf_float);
363}
364
cristy3ed852e2009-09-05 21:47:34 +0000365static 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