blob: 3c319a873fed61b74cb0c83285ad1ece32556cce [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
cristy4cb162a2010-05-30 03:04:47 +000037 unsigned int
cristy6b825f92010-06-04 02:01:10 +000038 pixel;
39
40 size_t
cristy3ed852e2009-09-05 21:47:34 +000041 bits;
42
cristy4cb162a2010-05-30 03:04:47 +000043 const unsigned int
cristy3ed852e2009-09-05 21:47:34 +000044 *mask;
45} QuantumState;
46
47struct _QuantumInfo
48{
cristybb503372010-05-27 20:51:26 +000049 size_t
cristy3ed852e2009-09-05 21:47:34 +000050 depth,
51 quantum;
52
53 QuantumFormatType
54 format;
55
56 double
57 minimum,
58 maximum,
59 scale;
60
61 size_t
62 pad;
63
64 MagickBooleanType
65 min_is_white,
66 pack;
67
68 QuantumAlphaType
69 alpha_type;
70
cristybb503372010-05-27 20:51:26 +000071 size_t
cristy3ed852e2009-09-05 21:47:34 +000072 number_threads;
73
74 unsigned char
75 **pixels;
76
77 size_t
78 extent;
79
80 SemaphoreInfo
81 *semaphore;
82
cristybb503372010-05-27 20:51:26 +000083 size_t
cristy3ed852e2009-09-05 21:47:34 +000084 signature;
85};
86
cristybb503372010-05-27 20:51:26 +000087static inline MagickSizeType GetQuantumRange(const size_t depth)
cristy2a4d01c2010-01-10 21:14:51 +000088{
cristy4cb162a2010-05-30 03:04:47 +000089 MagickSizeType
90 one;
91
92 one=1;
93 return((MagickSizeType) ((one << (depth-1))+((one << (depth-1))-1)));
cristy2a4d01c2010-01-10 21:14:51 +000094}
95
96static inline float HalfToSinglePrecision(const unsigned short half)
cristy5ab5fc82010-01-05 20:52:48 +000097{
cristy8a6a9802010-04-14 13:22:18 +000098#define ExponentBias (127-15)
cristy24fb7dc2010-01-10 20:15:51 +000099#define ExponentMask 0x7c00
100#define ExponentShift 23
cristybccb64f2010-01-10 21:16:36 +0000101#define SignBitShift 31
cristy24fb7dc2010-01-10 20:15:51 +0000102#define SignificandShift 13
103#define SignificandMask 0x00000400
cristy5ab5fc82010-01-05 20:52:48 +0000104
cristy24fb7dc2010-01-10 20:15:51 +0000105 typedef union _SinglePrecision
106 {
107 unsigned int
108 fixed_point;
109
110 float
111 single_precision;
112 } SinglePrecision;
113
114 register unsigned int
115 exponent,
116 significand,
117 sign_bit;
118
119 SinglePrecision
120 map;
121
122 unsigned int
123 value;
124
125 /*
cristybccb64f2010-01-10 21:16:36 +0000126 The IEEE 754 standard specifies half precision as having:
cristy24fb7dc2010-01-10 20:15:51 +0000127
128 Sign bit: 1 bit
129 Exponent width: 5 bits
130 Significand precision: 11 (10 explicitly stored)
131 */
cristy2a4d01c2010-01-10 21:14:51 +0000132 sign_bit=(unsigned int) ((half >> 15) & 0x00000001);
133 exponent=(unsigned int) ((half >> 10) & 0x0000001f);
134 significand=(unsigned int) (half & 0x000003ff);
cristy24fb7dc2010-01-10 20:15:51 +0000135 if (exponent == 0)
136 {
cristy92caafa2010-05-10 12:56:29 +0000137 if (significand == 0)
cristy24fb7dc2010-01-10 20:15:51 +0000138 value=sign_bit << SignBitShift;
cristy92caafa2010-05-10 12:56:29 +0000139 else
140 {
cristy24fb7dc2010-01-10 20:15:51 +0000141 while ((significand & SignificandMask) == 0)
142 {
143 significand<<=1;
144 exponent--;
145 }
cristy92caafa2010-05-10 12:56:29 +0000146 exponent++;
cristy24fb7dc2010-01-10 20:15:51 +0000147 significand&=(~SignificandMask);
148 exponent+=ExponentBias;
149 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
150 (significand << SignificandShift);
cristy92caafa2010-05-10 12:56:29 +0000151 }
cristy24fb7dc2010-01-10 20:15:51 +0000152 }
153 else
154 if (exponent == SignBitShift)
155 {
156 value=(sign_bit << SignBitShift) | 0x7f800000;
157 if (significand != 0)
158 value|=(significand << SignificandShift);
159 }
160 else
161 {
162 exponent+=ExponentBias;
163 significand<<=SignificandShift;
164 value=(sign_bit << SignBitShift) | (exponent << ExponentShift) |
165 significand;
166 }
167 map.fixed_point=value;
168 return(map.single_precision);
169}
cristy5ab5fc82010-01-05 20:52:48 +0000170
cristy3ed852e2009-09-05 21:47:34 +0000171static inline void InitializeQuantumState(const QuantumInfo *quantum_info,
172 const EndianType endian,QuantumState *quantum_state)
173{
cristy4cb162a2010-05-30 03:04:47 +0000174 static const unsigned int mask[32] =
cristy3ed852e2009-09-05 21:47:34 +0000175 {
cristy4cb162a2010-05-30 03:04:47 +0000176 0x00000000U, 0x00000001U, 0x00000003U, 0x00000007U, 0x0000000fU,
177 0x0000001fU, 0x0000003fU, 0x0000007fU, 0x000000ffU, 0x000001ffU,
178 0x000003ffU, 0x000007ffU, 0x00000fffU, 0x00001fffU, 0x00003fffU,
179 0x00007fffU, 0x0000ffffU, 0x0001ffffU, 0x0003ffffU, 0x0007ffffU,
180 0x000fffffU, 0x001fffffU, 0x003fffffU, 0x007fffffU, 0x00ffffffU,
181 0x01ffffffU, 0x03ffffffU, 0x07ffffffU, 0x0fffffffU, 0x1fffffffU,
182 0x3fffffffU, 0x7fffffffU
cristy3ed852e2009-09-05 21:47:34 +0000183 };
184
cristy3ed852e2009-09-05 21:47:34 +0000185 quantum_state->endian=endian;
186 quantum_state->minimum=quantum_info->minimum;
187 quantum_state->scale=quantum_info->scale;
cristy842f8822010-03-10 20:41:27 +0000188 quantum_state->inverse_scale=1.0;
cristy3ed852e2009-09-05 21:47:34 +0000189 if (quantum_state->scale != 0.0)
cristy09bee022010-03-10 20:45:09 +0000190 quantum_state->inverse_scale/=quantum_state->scale;
cristy4cb162a2010-05-30 03:04:47 +0000191 quantum_state->pixel=0U;
192 quantum_state->bits=0U;
cristy3ed852e2009-09-05 21:47:34 +0000193 quantum_state->mask=mask;
194}
195
cristy3ed852e2009-09-05 21:47:34 +0000196static inline unsigned char *PopCharPixel(const unsigned char pixel,
197 unsigned char *pixels)
198{
199 *pixels++=pixel;
200 return(pixels);
201}
202
203static inline unsigned char *PopLongPixel(const EndianType endian,
cristy4cb162a2010-05-30 03:04:47 +0000204 const unsigned int pixel,unsigned char *pixels)
cristy3ed852e2009-09-05 21:47:34 +0000205{
206 register unsigned int
207 quantum;
208
209 quantum=(unsigned int) pixel;
210 if (endian != LSBEndian)
211 {
212 *pixels++=(unsigned char) (quantum >> 24);
213 *pixels++=(unsigned char) (quantum >> 16);
214 *pixels++=(unsigned char) (quantum >> 8);
215 *pixels++=(unsigned char) (quantum);
216 return(pixels);
217 }
218 *pixels++=(unsigned char) (quantum);
219 *pixels++=(unsigned char) (quantum >> 8);
220 *pixels++=(unsigned char) (quantum >> 16);
221 *pixels++=(unsigned char) (quantum >> 24);
222 return(pixels);
223}
224
225static inline unsigned char *PopShortPixel(const EndianType endian,
226 const unsigned short pixel,unsigned char *pixels)
227{
228 register unsigned int
229 quantum;
230
231 quantum=pixel;
232 if (endian != LSBEndian)
233 {
234 *pixels++=(unsigned char) (quantum >> 8);
235 *pixels++=(unsigned char) (quantum);
236 return(pixels);
237 }
238 *pixels++=(unsigned char) (quantum);
239 *pixels++=(unsigned char) (quantum >> 8);
240 return(pixels);
241}
242
243static inline const unsigned char *PushCharPixel(const unsigned char *pixels,
244 unsigned char *pixel)
245{
246 *pixel=(*pixels++);
247 return(pixels);
248}
249
250static inline const unsigned char *PushLongPixel(const EndianType endian,
cristy4cb162a2010-05-30 03:04:47 +0000251 const unsigned char *pixels,unsigned int *pixel)
cristy3ed852e2009-09-05 21:47:34 +0000252{
253 register unsigned int
254 quantum;
255
256 if (endian != LSBEndian)
257 {
258 quantum=(unsigned int) (*pixels++ << 24);
259 quantum|=(unsigned int) (*pixels++ << 16);
260 quantum|=(unsigned int) (*pixels++ << 8);
261 quantum|=(unsigned int) (*pixels++);
262 }
263 else
264 {
265 quantum=(unsigned int) (*pixels++);
266 quantum|=(unsigned int) (*pixels++ << 8);
267 quantum|=(unsigned int) (*pixels++ << 16);
268 quantum|=(unsigned int) (*pixels++ << 24);
269 }
cristy4cb162a2010-05-30 03:04:47 +0000270 *pixel=(unsigned int) (quantum & 0xffffffff);
cristy3ed852e2009-09-05 21:47:34 +0000271 return(pixels);
272}
273
274static inline const unsigned char *PushShortPixel(const EndianType endian,
275 const unsigned char *pixels,unsigned short *pixel)
276{
277 register unsigned int
278 quantum;
279
280 if (endian != LSBEndian)
281 {
282 quantum=(unsigned int) (*pixels++ << 8);
283 quantum|=(unsigned int) *pixels++;
284 }
285 else
286 {
287 quantum=(unsigned int) *pixels++;
288 quantum|=(unsigned int) (*pixels++ << 8);
289 }
290 *pixel=(unsigned short) (quantum & 0xffff);
291 return(pixels);
292}
293
294static inline Quantum ScaleAnyToQuantum(const QuantumAny quantum,
295 const QuantumAny range)
296{
cristyb3963e62010-05-09 21:36:40 +0000297#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000298 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range+0.5));
cristyb3963e62010-05-09 21:36:40 +0000299#else
cristydd2fd9f2010-05-10 01:43:37 +0000300 return((Quantum) (((MagickRealType) QuantumRange*quantum)/range));
cristyb3963e62010-05-09 21:36:40 +0000301#endif
cristy3ed852e2009-09-05 21:47:34 +0000302}
303
cristy3ed852e2009-09-05 21:47:34 +0000304static inline QuantumAny ScaleQuantumToAny(const Quantum quantum,
305 const QuantumAny range)
306{
cristye6b6ece2010-05-29 13:25:01 +0000307 return((QuantumAny) (((MagickRealType) range*quantum)/QuantumRange+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000308}
309
310#if (MAGICKCORE_QUANTUM_DEPTH == 8)
311static inline Quantum ScaleCharToQuantum(const unsigned char value)
312{
313 return((Quantum) value);
314}
315
cristy4cb162a2010-05-30 03:04:47 +0000316static inline Quantum ScaleLongToQuantum(const unsigned int value)
cristy3ed852e2009-09-05 21:47:34 +0000317{
318#if !defined(MAGICKCORE_HDRI_SUPPORT)
319 return((Quantum) ((value+8421504UL)/16843009UL));
320#else
321 return((Quantum) (value/16843009.0));
322#endif
323}
324
325static inline Quantum ScaleMapToQuantum(const MagickRealType value)
326{
cristya45da3b2010-03-31 02:06:45 +0000327 if (value <= 0.0)
328 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000329 if (value >= MaxMap)
330 return((Quantum) QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000331#if !defined(MAGICKCORE_HDRI_SUPPORT)
332 return((Quantum) (value+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000333#else
cristydd2fd9f2010-05-10 01:43:37 +0000334 return((Quantum) value);
cristy3ed852e2009-09-05 21:47:34 +0000335#endif
336}
337
cristy4cb162a2010-05-30 03:04:47 +0000338static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000339{
340#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy4cb162a2010-05-30 03:04:47 +0000341 return((unsigned int) (16843009UL*quantum));
cristy3ed852e2009-09-05 21:47:34 +0000342#else
343 if (quantum <= 0.0)
344 return(0UL);
345 if ((16843009.0*quantum) >= 4294967295.0)
346 return(4294967295UL);
cristy4cb162a2010-05-30 03:04:47 +0000347 return((unsigned int) (16843009.0*quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000348#endif
349}
350
cristy4cb162a2010-05-30 03:04:47 +0000351static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000352{
353 if (quantum >= (Quantum) MaxMap)
cristy4cb162a2010-05-30 03:04:47 +0000354 return((unsigned int) MaxMap);
cristy3ed852e2009-09-05 21:47:34 +0000355#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy4cb162a2010-05-30 03:04:47 +0000356 return((unsigned int) quantum);
cristy3ed852e2009-09-05 21:47:34 +0000357#else
cristydd2fd9f2010-05-10 01:43:37 +0000358 if (quantum < 0.0)
359 return(0UL);
cristy4cb162a2010-05-30 03:04:47 +0000360 return((unsigned int) (quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000361#endif
362}
363
364static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
365{
366#if !defined(MAGICKCORE_HDRI_SUPPORT)
367 return((unsigned short) (257UL*quantum));
368#else
369 if (quantum <= 0.0)
370 return(0);
cristycd817db2010-05-09 03:05:41 +0000371 if ((257.0*quantum) >= 65535.0)
cristy3ed852e2009-09-05 21:47:34 +0000372 return(65535);
cristycd817db2010-05-09 03:05:41 +0000373 return((unsigned short) (257.0*quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000374#endif
375}
376
377static inline Quantum ScaleShortToQuantum(const unsigned short value)
378{
379#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristye90d7402010-03-14 18:21:29 +0000380 return((Quantum) ((value+128U)/257U));
cristy3ed852e2009-09-05 21:47:34 +0000381#else
cristydd2fd9f2010-05-10 01:43:37 +0000382 return((Quantum) (value/257.0));
cristy3ed852e2009-09-05 21:47:34 +0000383#endif
384}
385#elif (MAGICKCORE_QUANTUM_DEPTH == 16)
386static inline Quantum ScaleCharToQuantum(const unsigned char value)
387{
388#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristye90d7402010-03-14 18:21:29 +0000389 return((Quantum) (257U*value));
cristy3ed852e2009-09-05 21:47:34 +0000390#else
cristydd2fd9f2010-05-10 01:43:37 +0000391 return((Quantum) (257.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000392#endif
393}
394
cristy4cb162a2010-05-30 03:04:47 +0000395static inline Quantum ScaleLongToQuantum(const unsigned int value)
cristy3ed852e2009-09-05 21:47:34 +0000396{
397#if !defined(MAGICKCORE_HDRI_SUPPORT)
398 return((Quantum) ((value+MagickULLConstant(32768))/
399 MagickULLConstant(65537)));
400#else
cristydd2fd9f2010-05-10 01:43:37 +0000401 return((Quantum) (value/65537.0));
cristy3ed852e2009-09-05 21:47:34 +0000402#endif
403}
404
405static inline Quantum ScaleMapToQuantum(const MagickRealType value)
406{
cristya45da3b2010-03-31 02:06:45 +0000407 if (value <= 0.0)
408 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000409 if (value >= MaxMap)
410 return((Quantum) QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000411#if !defined(MAGICKCORE_HDRI_SUPPORT)
412 return((Quantum) (value+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000413#else
cristydd2fd9f2010-05-10 01:43:37 +0000414 return((Quantum) value);
cristy3ed852e2009-09-05 21:47:34 +0000415#endif
416}
417
cristy4cb162a2010-05-30 03:04:47 +0000418static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000419{
420#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy4cb162a2010-05-30 03:04:47 +0000421 return((unsigned int) (65537UL*quantum));
cristy3ed852e2009-09-05 21:47:34 +0000422#else
423 if (quantum <= 0.0)
424 return(0UL);
cristycd817db2010-05-09 03:05:41 +0000425 if ((65537.0*quantum) >= 4294967295.0)
cristy9f48ca62010-11-25 03:06:31 +0000426 return(4294967295U);
cristy4cb162a2010-05-30 03:04:47 +0000427 return((unsigned int) (65537.0*quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000428#endif
429}
430
cristy4cb162a2010-05-30 03:04:47 +0000431static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000432{
433 if (quantum >= (Quantum) MaxMap)
cristy4cb162a2010-05-30 03:04:47 +0000434 return((unsigned int) MaxMap);
cristy3ed852e2009-09-05 21:47:34 +0000435#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy4cb162a2010-05-30 03:04:47 +0000436 return((unsigned int) quantum);
cristy3ed852e2009-09-05 21:47:34 +0000437#else
cristya8307572010-03-31 14:24:19 +0000438 if (quantum < 0.0)
439 return(0UL);
cristy4cb162a2010-05-30 03:04:47 +0000440 return((unsigned int) (quantum+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000441#endif
442}
443
444static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
445{
446#if !defined(MAGICKCORE_HDRI_SUPPORT)
447 return((unsigned short) quantum);
448#else
449 if (quantum <= 0.0)
450 return(0);
451 if (quantum >= 65535.0)
452 return(65535);
453 return((unsigned short) (quantum+0.5));
454#endif
455}
456
457static inline Quantum ScaleShortToQuantum(const unsigned short value)
458{
459 return((Quantum) value);
460}
461#elif (MAGICKCORE_QUANTUM_DEPTH == 32)
462static inline Quantum ScaleCharToQuantum(const unsigned char value)
463{
464#if !defined(MAGICKCORE_HDRI_SUPPORT)
465 return((Quantum) (16843009UL*value));
466#else
cristydd2fd9f2010-05-10 01:43:37 +0000467 return((Quantum) (16843009.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000468#endif
469}
470
cristy4cb162a2010-05-30 03:04:47 +0000471static inline Quantum ScaleLongToQuantum(const unsigned int value)
cristy3ed852e2009-09-05 21:47:34 +0000472{
473 return((Quantum) value);
474}
475
476static inline Quantum ScaleMapToQuantum(const MagickRealType value)
477{
cristya45da3b2010-03-31 02:06:45 +0000478 if (value <= 0.0)
479 return((Quantum) 0);
cristydd2fd9f2010-05-10 01:43:37 +0000480 if (value >= (Quantum) MaxMap)
cristya45da3b2010-03-31 02:06:45 +0000481 return(QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000482#if !defined(MAGICKCORE_HDRI_SUPPORT)
483 return((Quantum) (65537.0*value+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000484#else
cristydd2fd9f2010-05-10 01:43:37 +0000485 return((Quantum) (65537.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000486#endif
487}
488
cristy4cb162a2010-05-30 03:04:47 +0000489static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000490{
cristy0402ad32010-05-11 13:57:55 +0000491#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy4cb162a2010-05-30 03:04:47 +0000492 return((unsigned int) quantum);
cristy0402ad32010-05-11 13:57:55 +0000493#else
cristy4cb162a2010-05-30 03:04:47 +0000494 return((unsigned int) (quantum+0.5));
cristy0402ad32010-05-11 13:57:55 +0000495#endif
cristy3ed852e2009-09-05 21:47:34 +0000496}
497
cristy4cb162a2010-05-30 03:04:47 +0000498static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000499{
cristya45da3b2010-03-31 02:06:45 +0000500 if (quantum < 0.0)
501 return(0UL);
cristydd2fd9f2010-05-10 01:43:37 +0000502 if ((quantum/65537) >= (Quantum) MaxMap)
cristy4cb162a2010-05-30 03:04:47 +0000503 return((unsigned int) MaxMap);
cristy3ed852e2009-09-05 21:47:34 +0000504#if !defined(MAGICKCORE_HDRI_SUPPORT)
cristy4cb162a2010-05-30 03:04:47 +0000505 return((unsigned int) ((quantum+MagickULLConstant(32768))/
cristy3ed852e2009-09-05 21:47:34 +0000506 MagickULLConstant(65537)));
507#else
cristy4cb162a2010-05-30 03:04:47 +0000508 return((unsigned int) (quantum/65537.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000509#endif
510}
511
512static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
513{
514#if !defined(MAGICKCORE_HDRI_SUPPORT)
515 return((unsigned short) ((quantum+MagickULLConstant(32768))/
516 MagickULLConstant(65537)));
517#else
518 if (quantum <= 0.0)
519 return(0);
cristycd817db2010-05-09 03:05:41 +0000520 if ((quantum/65537.0) >= 65535.0)
cristy3ed852e2009-09-05 21:47:34 +0000521 return(65535);
cristycd817db2010-05-09 03:05:41 +0000522 return((unsigned short) (quantum/65537.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000523#endif
524}
525
526static inline Quantum ScaleShortToQuantum(const unsigned short value)
527{
528#if !defined(MAGICKCORE_HDRI_SUPPORT)
529 return((Quantum) (65537UL*value));
530#else
cristy41f82a62010-05-10 13:05:18 +0000531 return((Quantum) (65537.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000532#endif
533}
534#elif (MAGICKCORE_QUANTUM_DEPTH == 64)
535static inline Quantum ScaleCharToQuantum(const unsigned char value)
536{
cristydd2fd9f2010-05-10 01:43:37 +0000537 return((Quantum) (72340172838076673.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000538}
539
cristy4cb162a2010-05-30 03:04:47 +0000540static inline Quantum ScaleLongToQuantum(const unsigned int value)
cristy3ed852e2009-09-05 21:47:34 +0000541{
cristyff2c0252010-05-11 14:00:48 +0000542 return((Quantum) (4294967297.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000543}
544
545static inline Quantum ScaleMapToQuantum(const MagickRealType value)
546{
cristya45da3b2010-03-31 02:06:45 +0000547 if (value <= 0.0)
548 return((Quantum) 0);
cristya45da3b2010-03-31 02:06:45 +0000549 if (value >= MaxMap)
550 return(QuantumRange);
cristydd2fd9f2010-05-10 01:43:37 +0000551 return((Quantum) (281479271743489.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000552}
553
cristy4cb162a2010-05-30 03:04:47 +0000554static inline unsigned int ScaleQuantumToLong(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000555{
cristy4cb162a2010-05-30 03:04:47 +0000556 return((unsigned int) (quantum/4294967297.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000557}
558
cristy4cb162a2010-05-30 03:04:47 +0000559static inline unsigned int ScaleQuantumToMap(const Quantum quantum)
cristy3ed852e2009-09-05 21:47:34 +0000560{
cristy41f82a62010-05-10 13:05:18 +0000561 if (quantum <= 0.0)
cristydd2fd9f2010-05-10 01:43:37 +0000562 return(0UL);
cristy43513522010-05-11 13:46:36 +0000563 if ((quantum/281479271743489.0) >= MaxMap)
cristy4cb162a2010-05-30 03:04:47 +0000564 return((unsigned int) MaxMap);
565 return((unsigned int) (quantum/281479271743489.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000566}
567
568static inline unsigned short ScaleQuantumToShort(const Quantum quantum)
569{
cristy5f54f2b2010-05-11 14:29:17 +0000570 if (quantum <= 0.0)
571 return(0);
cristyf4ad8d92010-05-12 17:58:41 +0000572 if ((quantum/281479271743489.0) >= 65535.0)
cristy5f54f2b2010-05-11 14:29:17 +0000573 return(65535);
cristy43513522010-05-11 13:46:36 +0000574 return((unsigned short) (quantum/281479271743489.0+0.5));
cristy3ed852e2009-09-05 21:47:34 +0000575}
576
577static inline Quantum ScaleShortToQuantum(const unsigned short value)
578{
cristyb3963e62010-05-09 21:36:40 +0000579 return((Quantum) (281479271743489.0*value));
cristy3ed852e2009-09-05 21:47:34 +0000580}
581#endif
582
cristy2a4d01c2010-01-10 21:14:51 +0000583static inline unsigned short SinglePrecisionToHalf(const float value)
cristy24fb7dc2010-01-10 20:15:51 +0000584{
585 typedef union _SinglePrecision
586 {
587 unsigned int
588 fixed_point;
589
590 float
591 single_precision;
592 } SinglePrecision;
593
594 register int
595 exponent;
596
597 register unsigned int
598 significand,
599 sign_bit;
600
601 SinglePrecision
602 map;
603
604 unsigned short
cristy2a4d01c2010-01-10 21:14:51 +0000605 half;
cristy24fb7dc2010-01-10 20:15:51 +0000606
607 /*
cristybccb64f2010-01-10 21:16:36 +0000608 The IEEE 754 standard specifies half precision as having:
cristy24fb7dc2010-01-10 20:15:51 +0000609
610 Sign bit: 1 bit
611 Exponent width: 5 bits
612 Significand precision: 11 (10 explicitly stored)
613 */
614 map.single_precision=value;
615 sign_bit=(map.fixed_point >> 16) & 0x00008000;
616 exponent=(int) ((map.fixed_point >> ExponentShift) & 0x000000ff)-ExponentBias;
617 significand=map.fixed_point & 0x007fffff;
618 if (exponent <= 0)
619 {
cristy4cb162a2010-05-30 03:04:47 +0000620 int
cristy24fb7dc2010-01-10 20:15:51 +0000621 shift;
622
623 if (exponent < -10)
624 return((unsigned short) sign_bit);
625 significand=significand | 0x00800000;
cristy4cb162a2010-05-30 03:04:47 +0000626 shift=(int) (14-exponent);
cristy24fb7dc2010-01-10 20:15:51 +0000627 significand=(unsigned int) ((significand+((1 << (shift-1))-1)+
628 ((significand >> shift) & 0x01)) >> shift);
629 return((unsigned short) (sign_bit | significand));
630 }
631 else
632 if (exponent == (0xff-ExponentBias))
633 {
634 if (significand == 0)
635 return((unsigned short) (sign_bit | ExponentMask));
636 else
637 {
638 significand>>=SignificandShift;
cristy2a4d01c2010-01-10 21:14:51 +0000639 half=(unsigned short) (sign_bit | significand |
cristy24fb7dc2010-01-10 20:15:51 +0000640 (significand == 0) | ExponentMask);
cristy2a4d01c2010-01-10 21:14:51 +0000641 return(half);
cristy24fb7dc2010-01-10 20:15:51 +0000642 }
643 }
644 significand=significand+((significand >> SignificandShift) & 0x01)+0x00000fff;
645 if ((significand & 0x00800000) != 0)
646 {
647 significand=0;
648 exponent++;
649 }
650 if (exponent > 30)
651 {
652 float
653 alpha;
654
cristy4cb162a2010-05-30 03:04:47 +0000655 register int
cristy24fb7dc2010-01-10 20:15:51 +0000656 i;
657
658 /*
659 Float overflow.
660 */
661 alpha=1.0e10;
662 for (i=0; i < 10; i++)
663 alpha*=alpha;
664 return((unsigned short) (sign_bit | ExponentMask));
665 }
cristy2a4d01c2010-01-10 21:14:51 +0000666 half=(unsigned short) (sign_bit | (exponent << 10) |
cristy24fb7dc2010-01-10 20:15:51 +0000667 (significand >> SignificandShift));
cristy2a4d01c2010-01-10 21:14:51 +0000668 return(half);
cristy24fb7dc2010-01-10 20:15:51 +0000669}
670
cristy3ed852e2009-09-05 21:47:34 +0000671#if defined(__cplusplus) || defined(c_plusplus)
672}
673#endif
674
675#endif