/src/dng_sdk/source/dng_utils.h
Line | Count | Source |
1 | | /*****************************************************************************/ |
2 | | // Copyright 2006-2012 Adobe Systems Incorporated |
3 | | // All Rights Reserved. |
4 | | // |
5 | | // NOTICE: Adobe permits you to use, modify, and distribute this file in |
6 | | // accordance with the terms of the Adobe license agreement accompanying it. |
7 | | /*****************************************************************************/ |
8 | | |
9 | | /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_utils.h#3 $ */ |
10 | | /* $DateTime: 2012/06/14 20:24:41 $ */ |
11 | | /* $Change: 835078 $ */ |
12 | | /* $Author: tknoll $ */ |
13 | | |
14 | | /*****************************************************************************/ |
15 | | |
16 | | #ifndef __dng_utils__ |
17 | | #define __dng_utils__ |
18 | | |
19 | | /*****************************************************************************/ |
20 | | |
21 | | #include <cmath> |
22 | | #include <limits> |
23 | | |
24 | | #include "dng_classes.h" |
25 | | #include "dng_flags.h" |
26 | | #include "dng_memory.h" |
27 | | #include "dng_safe_arithmetic.h" |
28 | | #include "dng_types.h" |
29 | | |
30 | | /*****************************************************************************/ |
31 | | |
32 | | // The unsigned integer overflow is intended here since a wrap around is used to |
33 | | // calculate the abs() in the branchless version. |
34 | | #if defined(__clang__) && defined(__has_attribute) |
35 | | #if __has_attribute(no_sanitize) |
36 | | __attribute__((no_sanitize("unsigned-integer-overflow"))) |
37 | | #endif |
38 | | #endif |
39 | | inline uint32 Abs_int32 (int32 x) |
40 | 21.8M | { |
41 | | |
42 | | #if 0 |
43 | | |
44 | | // Reference version. |
45 | | |
46 | | return (uint32) (x < 0 ? -x : x); |
47 | | |
48 | | #else |
49 | | |
50 | | // Branchless version. |
51 | | |
52 | 21.8M | uint32 mask = (uint32) (x >> 31); |
53 | | |
54 | 21.8M | return (uint32) (((uint32) x + mask) ^ mask); |
55 | | |
56 | 21.8M | #endif |
57 | | |
58 | 21.8M | } |
59 | | |
60 | | inline int32 Min_int32 (int32 x, int32 y) |
61 | 1.25G | { |
62 | | |
63 | 1.25G | return (x <= y ? x : y); |
64 | | |
65 | 1.25G | } |
66 | | |
67 | | inline int32 Max_int32 (int32 x, int32 y) |
68 | 1.25G | { |
69 | | |
70 | 1.25G | return (x >= y ? x : y); |
71 | | |
72 | 1.25G | } |
73 | | |
74 | | inline int32 Pin_int32 (int32 min, int32 x, int32 max) |
75 | 1.22G | { |
76 | | |
77 | 1.22G | return Max_int32 (min, Min_int32 (x, max)); |
78 | | |
79 | 1.22G | } |
80 | | |
81 | | inline int32 Pin_int32_between (int32 a, int32 x, int32 b) |
82 | 0 | { |
83 | 0 | |
84 | 0 | int32 min, max; |
85 | 0 | if (a < b) { min = a; max = b; } |
86 | 0 | else { min = b; max = a; } |
87 | 0 | |
88 | 0 | return Pin_int32 (min, x, max); |
89 | 0 | |
90 | 0 | } |
91 | | |
92 | | /*****************************************************************************/ |
93 | | |
94 | | inline uint16 Min_uint16 (uint16 x, uint16 y) |
95 | 0 | { |
96 | 0 | |
97 | 0 | return (x <= y ? x : y); |
98 | 0 | |
99 | 0 | } |
100 | | |
101 | | inline uint16 Max_uint16 (uint16 x, uint16 y) |
102 | 0 | { |
103 | 0 | |
104 | 0 | return (x >= y ? x : y); |
105 | 0 | |
106 | 0 | } |
107 | | |
108 | | inline int16 Pin_int16 (int32 x) |
109 | 0 | { |
110 | 0 | |
111 | 0 | x = Pin_int32 (-32768, x, 32767); |
112 | 0 | |
113 | 0 | return (int16) x; |
114 | 0 | |
115 | 0 | } |
116 | | |
117 | | /*****************************************************************************/ |
118 | | |
119 | | inline uint32 Min_uint32 (uint32 x, uint32 y) |
120 | 309M | { |
121 | | |
122 | 309M | return (x <= y ? x : y); |
123 | | |
124 | 309M | } |
125 | | |
126 | | inline uint32 Min_uint32 (uint32 x, uint32 y, uint32 z) |
127 | 0 | { |
128 | 0 | |
129 | 0 | return Min_uint32 (x, Min_uint32 (y, z)); |
130 | 0 | |
131 | 0 | } |
132 | | |
133 | | inline uint32 Max_uint32 (uint32 x, uint32 y) |
134 | 592k | { |
135 | | |
136 | 592k | return (x >= y ? x : y); |
137 | | |
138 | 592k | } |
139 | | |
140 | | inline uint32 Max_uint32 (uint32 x, uint32 y, uint32 z) |
141 | 0 | { |
142 | 0 | |
143 | 0 | return Max_uint32 (x, Max_uint32 (y, z)); |
144 | 0 | |
145 | 0 | } |
146 | | |
147 | | inline uint32 Pin_uint32 (uint32 min, uint32 x, uint32 max) |
148 | 471k | { |
149 | | |
150 | 471k | return Max_uint32 (min, Min_uint32 (x, max)); |
151 | | |
152 | 471k | } |
153 | | |
154 | | /*****************************************************************************/ |
155 | | |
156 | | inline uint16 Pin_uint16 (int32 x) |
157 | 166M | { |
158 | | |
159 | | #if 0 |
160 | | |
161 | | // Reference version. |
162 | | |
163 | | x = Pin_int32 (0, x, 0x0FFFF); |
164 | | |
165 | | #else |
166 | | |
167 | | // Single branch version. |
168 | | |
169 | 166M | if (x & ~65535) |
170 | 117M | { |
171 | | |
172 | 117M | x = ~x >> 31; |
173 | | |
174 | 117M | } |
175 | | |
176 | 166M | #endif |
177 | | |
178 | 166M | return (uint16) x; |
179 | | |
180 | 166M | } |
181 | | |
182 | | /*****************************************************************************/ |
183 | | |
184 | | inline uint32 RoundDown2 (uint32 x) |
185 | 0 | { |
186 | 0 | |
187 | 0 | return x & (uint32) ~1; |
188 | 0 | |
189 | 0 | } |
190 | | |
191 | | inline uint32 RoundDown4 (uint32 x) |
192 | 0 | { |
193 | 0 | |
194 | 0 | return x & (uint32) ~3; |
195 | 0 | |
196 | 0 | } |
197 | | |
198 | | inline uint32 RoundDown8 (uint32 x) |
199 | 0 | { |
200 | 0 | |
201 | 0 | return x & (uint32) ~7; |
202 | 0 | |
203 | 0 | } |
204 | | |
205 | | inline uint32 RoundDown16 (uint32 x) |
206 | 0 | { |
207 | 0 | |
208 | 0 | return x & (uint32) ~15; |
209 | 0 | |
210 | 0 | } |
211 | | |
212 | | /******************************************************************************/ |
213 | | |
214 | | inline bool RoundUpForPixelSize (uint32 x, uint32 pixelSize, uint32 *result) |
215 | 1.69M | { |
216 | | |
217 | 1.69M | uint32 multiple; |
218 | 1.69M | switch (pixelSize) |
219 | 1.69M | { |
220 | | |
221 | 29.1k | case 1: |
222 | 485k | case 2: |
223 | 1.69M | case 4: |
224 | 1.69M | case 8: |
225 | 1.69M | multiple = 16 / pixelSize; |
226 | 1.69M | break; |
227 | | |
228 | 0 | default: |
229 | 0 | multiple = 16; |
230 | 0 | break; |
231 | | |
232 | 1.69M | } |
233 | | |
234 | 1.69M | return RoundUpUint32ToMultiple(x, multiple, result); |
235 | | |
236 | 1.69M | } |
237 | | |
238 | | /******************************************************************************/ |
239 | | |
240 | | // Type of padding to be performed by ComputeBufferSize(). |
241 | | enum PaddingType |
242 | | { |
243 | | // Don't perform any padding. |
244 | | padNone, |
245 | | // Pad each scanline to an integer multiple of 16 bytes (in the same way |
246 | | // that RoundUpForPixelSize() does). |
247 | | pad16Bytes |
248 | | }; |
249 | | |
250 | | // Returns the number of bytes required for an image tile with the given pixel |
251 | | // type, tile size, number of image planes, and desired padding. Throws a |
252 | | // dng_exception with dng_error_memory error code if one of the components of |
253 | | // tileSize is negative or if arithmetic overflow occurs during the computation. |
254 | | uint32 ComputeBufferSize(uint32 pixelType, const dng_point &tileSize, |
255 | | uint32 numPlanes, PaddingType paddingType); |
256 | | |
257 | | /******************************************************************************/ |
258 | | |
259 | | inline uint64 Abs_int64 (int64 x) |
260 | 0 | { |
261 | 0 | |
262 | 0 | return (uint64) (x < 0 ? -x : x); |
263 | 0 |
|
264 | 0 | } |
265 | | |
266 | | inline int64 Min_int64 (int64 x, int64 y) |
267 | 0 | { |
268 | 0 | |
269 | 0 | return (x <= y ? x : y); |
270 | 0 | |
271 | 0 | } |
272 | | |
273 | | inline int64 Max_int64 (int64 x, int64 y) |
274 | 0 | { |
275 | 0 | |
276 | 0 | return (x >= y ? x : y); |
277 | 0 | |
278 | 0 | } |
279 | | |
280 | | inline int64 Pin_int64 (int64 min, int64 x, int64 max) |
281 | 0 | { |
282 | 0 | |
283 | 0 | return Max_int64 (min, Min_int64 (x, max)); |
284 | 0 | |
285 | 0 | } |
286 | | |
287 | | /******************************************************************************/ |
288 | | |
289 | | inline uint64 Min_uint64 (uint64 x, uint64 y) |
290 | 19.3M | { |
291 | | |
292 | 19.3M | return (x <= y ? x : y); |
293 | | |
294 | 19.3M | } |
295 | | |
296 | | inline uint64 Max_uint64 (uint64 x, uint64 y) |
297 | 1.03G | { |
298 | | |
299 | 1.03G | return (x >= y ? x : y); |
300 | | |
301 | 1.03G | } |
302 | | |
303 | | inline uint64 Pin_uint64 (uint64 min, uint64 x, uint64 max) |
304 | 0 | { |
305 | 0 | |
306 | 0 | return Max_uint64 (min, Min_uint64 (x, max)); |
307 | 0 | |
308 | 0 | } |
309 | | |
310 | | /*****************************************************************************/ |
311 | | |
312 | | inline real32 Abs_real32 (real32 x) |
313 | 0 | { |
314 | | |
315 | 0 | return (x < 0.0f ? -x : x); |
316 | | |
317 | 0 | } |
318 | | |
319 | | inline real32 Min_real32 (real32 x, real32 y) |
320 | 5.48G | { |
321 | | |
322 | 5.48G | return (x < y ? x : y); |
323 | | |
324 | 5.48G | } |
325 | | |
326 | | inline real32 Max_real32 (real32 x, real32 y) |
327 | 5.25G | { |
328 | | |
329 | 5.25G | return (x > y ? x : y); |
330 | | |
331 | 5.25G | } |
332 | | |
333 | | inline real32 Pin_real32 (real32 min, real32 x, real32 max) |
334 | 5.25G | { |
335 | | |
336 | 5.25G | return Max_real32 (min, Min_real32 (x, max)); |
337 | | |
338 | 5.25G | } |
339 | | |
340 | | inline real32 Pin_real32 (real32 x) |
341 | 0 | { |
342 | |
|
343 | 0 | return Pin_real32 (0.0f, x, 1.0f); |
344 | |
|
345 | 0 | } |
346 | | |
347 | | inline real32 Pin_real32_Overrange (real32 min, |
348 | | real32 x, |
349 | | real32 max) |
350 | 0 | { |
351 | 0 | |
352 | 0 | // Normal numbers in (min,max). No change. |
353 | 0 | |
354 | 0 | if (x > min && x < max) |
355 | 0 | { |
356 | 0 | return x; |
357 | 0 | } |
358 | 0 | |
359 | 0 | // Map large numbers (including positive infinity) to max. |
360 | 0 | |
361 | 0 | else if (x > min) |
362 | 0 | { |
363 | 0 | return max; |
364 | 0 | } |
365 | 0 | |
366 | 0 | // Map everything else (including negative infinity and all NaNs) to min. |
367 | 0 | |
368 | 0 | return min; |
369 | 0 | |
370 | 0 | } |
371 | | |
372 | | inline real32 Pin_Overrange (real32 x) |
373 | 3.13G | { |
374 | | |
375 | | // Normal in-range numbers, except for plus and minus zero. |
376 | | |
377 | 3.13G | if (x > 0.0f && x <= 1.0f) |
378 | 2.04G | { |
379 | 2.04G | return x; |
380 | 2.04G | } |
381 | | |
382 | | // Large numbers, including positive infinity. |
383 | | |
384 | 1.09G | else if (x > 0.5f) |
385 | 1.59k | { |
386 | 1.59k | return 1.0f; |
387 | 1.59k | } |
388 | | |
389 | | // Plus and minus zero, negative numbers, negative infinity, and all NaNs. |
390 | | |
391 | 1.09G | return 0.0f; |
392 | | |
393 | 3.13G | } |
394 | | |
395 | | inline real32 Lerp_real32 (real32 a, real32 b, real32 t) |
396 | 0 | { |
397 | 0 | |
398 | 0 | return a + t * (b - a); |
399 | 0 | |
400 | 0 | } |
401 | | |
402 | | /*****************************************************************************/ |
403 | | |
404 | | inline real64 Abs_real64 (real64 x) |
405 | 4.99G | { |
406 | | |
407 | 4.99G | return (x < 0.0 ? -x : x); |
408 | | |
409 | 4.99G | } |
410 | | |
411 | | inline real64 Min_real64 (real64 x, real64 y) |
412 | 1.11G | { |
413 | | |
414 | 1.11G | return (x < y ? x : y); |
415 | | |
416 | 1.11G | } |
417 | | |
418 | | inline real64 Max_real64 (real64 x, real64 y) |
419 | 2.11G | { |
420 | | |
421 | 2.11G | return (x > y ? x : y); |
422 | | |
423 | 2.11G | } |
424 | | |
425 | | inline real64 Pin_real64 (real64 min, real64 x, real64 max) |
426 | 1.08G | { |
427 | | |
428 | 1.08G | return Max_real64 (min, Min_real64 (x, max)); |
429 | | |
430 | 1.08G | } |
431 | | |
432 | | inline real64 Pin_real64 (real64 x) |
433 | 0 | { |
434 | 0 | |
435 | 0 | return Pin_real64 (0.0, x, 1.0); |
436 | 0 | |
437 | 0 | } |
438 | | |
439 | | inline real64 Pin_real64_Overrange (real64 min, |
440 | | real64 x, |
441 | | real64 max) |
442 | 0 | { |
443 | 0 | |
444 | 0 | // Normal numbers in (min,max). No change. |
445 | 0 | |
446 | 0 | if (x > min && x < max) |
447 | 0 | { |
448 | 0 | return x; |
449 | 0 | } |
450 | 0 | |
451 | 0 | // Map large numbers (including positive infinity) to max. |
452 | 0 | |
453 | 0 | else if (x > min) |
454 | 0 | { |
455 | 0 | return max; |
456 | 0 | } |
457 | 0 | |
458 | 0 | // Map everything else (including negative infinity and all NaNs) to min. |
459 | 0 | |
460 | 0 | return min; |
461 | 0 | |
462 | 0 | } |
463 | | |
464 | | inline real64 Lerp_real64 (real64 a, real64 b, real64 t) |
465 | 0 | { |
466 | | |
467 | 0 | return a + t * (b - a); |
468 | | |
469 | 0 | } |
470 | | |
471 | | /*****************************************************************************/ |
472 | | |
473 | | inline int32 Round_int32 (real32 x) |
474 | 0 | { |
475 | 0 | |
476 | 0 | return (int32) (x > 0.0f ? x + 0.5f : x - 0.5f); |
477 | 0 | |
478 | 0 | } |
479 | | |
480 | | inline int32 Round_int32 (real64 x) |
481 | 5.26G | { |
482 | | |
483 | 5.26G | const real64 temp = x > 0.0 ? x + 0.5 : x - 0.5; |
484 | | |
485 | | // NaNs will fail this test (because NaNs compare false against |
486 | | // everything) and will therefore also take the else branch. |
487 | 5.26G | if (temp > real64(std::numeric_limits<int32>::min()) - 1.0 && |
488 | 5.26G | temp < real64(std::numeric_limits<int32>::max()) + 1.0) |
489 | 5.26G | { |
490 | 5.26G | return (int32) temp; |
491 | 5.26G | } |
492 | | |
493 | 5.66k | else |
494 | 5.66k | { |
495 | 5.66k | ThrowProgramError("Overflow in Round_int32"); |
496 | | // Dummy return. |
497 | 5.66k | return 0; |
498 | 5.66k | } |
499 | | |
500 | 5.26G | } |
501 | | |
502 | | inline uint32 Floor_uint32 (real32 x) |
503 | 0 | { |
504 | | |
505 | 0 | return (uint32) Max_real32 (0.0f, x); |
506 | | |
507 | 0 | } |
508 | | |
509 | | inline uint32 Floor_uint32 (real64 x) |
510 | 1.02G | { |
511 | | |
512 | 1.02G | const real64 temp = Max_real64 (0.0, x); |
513 | | |
514 | | // NaNs will fail this test (because NaNs compare false against |
515 | | // everything) and will therefore also take the else branch. |
516 | 1.02G | if (temp < real64(std::numeric_limits<uint32>::max()) + 1.0) |
517 | 1.02G | { |
518 | 1.02G | return (uint32) temp; |
519 | 1.02G | } |
520 | | |
521 | 299 | else |
522 | 299 | { |
523 | 299 | ThrowProgramError("Overflow in Floor_uint32"); |
524 | | // Dummy return. |
525 | 299 | return 0; |
526 | 299 | } |
527 | | |
528 | 1.02G | } |
529 | | |
530 | | inline uint32 Round_uint32 (real32 x) |
531 | 0 | { |
532 | | |
533 | 0 | return Floor_uint32 (x + 0.5f); |
534 | | |
535 | 0 | } |
536 | | |
537 | | inline uint32 Round_uint32 (real64 x) |
538 | 1.02G | { |
539 | | |
540 | 1.02G | return Floor_uint32 (x + 0.5); |
541 | | |
542 | 1.02G | } |
543 | | |
544 | | /******************************************************************************/ |
545 | | |
546 | | inline int64 Round_int64 (real64 x) |
547 | 0 | { |
548 | | |
549 | 0 | return (int64) (x >= 0.0 ? x + 0.5 : x - 0.5); |
550 | | |
551 | 0 | } |
552 | | |
553 | | /*****************************************************************************/ |
554 | | |
555 | | const int64 kFixed64_One = (((int64) 1) << 32); |
556 | | const int64 kFixed64_Half = (((int64) 1) << 31); |
557 | | |
558 | | /******************************************************************************/ |
559 | | |
560 | | inline int64 Real64ToFixed64 (real64 x) |
561 | 0 | { |
562 | | |
563 | 0 | return Round_int64 (x * (real64) kFixed64_One); |
564 | | |
565 | 0 | } |
566 | | |
567 | | /******************************************************************************/ |
568 | | |
569 | | inline real64 Fixed64ToReal64 (int64 x) |
570 | 0 | { |
571 | 0 | |
572 | 0 | return x * (1.0 / (real64) kFixed64_One); |
573 | 0 | |
574 | 0 | } |
575 | | |
576 | | /*****************************************************************************/ |
577 | | |
578 | | inline char ForceUppercase (char c) |
579 | 254k | { |
580 | | |
581 | 254k | if (c >= 'a' && c <= 'z') |
582 | 60.1k | { |
583 | | |
584 | 60.1k | c -= 'a' - 'A'; |
585 | | |
586 | 60.1k | } |
587 | | |
588 | 254k | return c; |
589 | | |
590 | 254k | } |
591 | | |
592 | | /*****************************************************************************/ |
593 | | |
594 | | inline uint16 SwapBytes16 (uint16 x) |
595 | 58.2M | { |
596 | | |
597 | 58.2M | return (uint16) ((x << 8) | |
598 | 58.2M | (x >> 8)); |
599 | | |
600 | 58.2M | } |
601 | | |
602 | | inline uint32 SwapBytes32 (uint32 x) |
603 | 54.4M | { |
604 | | |
605 | 54.4M | return (x << 24) + |
606 | 54.4M | ((x << 8) & 0x00FF0000) + |
607 | 54.4M | ((x >> 8) & 0x0000FF00) + |
608 | 54.4M | (x >> 24); |
609 | | |
610 | 54.4M | } |
611 | | |
612 | | /*****************************************************************************/ |
613 | | |
614 | | inline bool IsAligned16 (const void *p) |
615 | 0 | { |
616 | 0 | |
617 | 0 | return (((uintptr) p) & 1) == 0; |
618 | 0 | |
619 | 0 | } |
620 | | |
621 | | inline bool IsAligned32 (const void *p) |
622 | 0 | { |
623 | | |
624 | 0 | return (((uintptr) p) & 3) == 0; |
625 | | |
626 | 0 | } |
627 | | |
628 | | inline bool IsAligned64 (const void *p) |
629 | 0 | { |
630 | 0 | |
631 | 0 | return (((uintptr) p) & 7) == 0; |
632 | 0 | |
633 | 0 | } |
634 | | |
635 | | inline bool IsAligned128 (const void *p) |
636 | 0 | { |
637 | 0 | |
638 | 0 | return (((uintptr) p) & 15) == 0; |
639 | 0 | |
640 | 0 | } |
641 | | |
642 | | /******************************************************************************/ |
643 | | |
644 | | // Converts from RGB values (range 0.0 to 1.0) to HSV values (range 0.0 to |
645 | | // 6.0 for hue, and 0.0 to 1.0 for saturation and value). |
646 | | |
647 | | inline void DNG_RGBtoHSV (real32 r, |
648 | | real32 g, |
649 | | real32 b, |
650 | | real32 &h, |
651 | | real32 &s, |
652 | | real32 &v) |
653 | 0 | { |
654 | | |
655 | 0 | v = Max_real32 (r, Max_real32 (g, b)); |
656 | |
|
657 | 0 | real32 gap = v - Min_real32 (r, Min_real32 (g, b)); |
658 | | |
659 | 0 | if (gap > 0.0f) |
660 | 0 | { |
661 | |
|
662 | 0 | if (r == v) |
663 | 0 | { |
664 | | |
665 | 0 | h = (g - b) / gap; |
666 | | |
667 | 0 | if (h < 0.0f) |
668 | 0 | { |
669 | 0 | h += 6.0f; |
670 | 0 | } |
671 | | |
672 | 0 | } |
673 | | |
674 | 0 | else if (g == v) |
675 | 0 | { |
676 | 0 | h = 2.0f + (b - r) / gap; |
677 | 0 | } |
678 | | |
679 | 0 | else |
680 | 0 | { |
681 | 0 | h = 4.0f + (r - g) / gap; |
682 | 0 | } |
683 | | |
684 | 0 | s = gap / v; |
685 | | |
686 | 0 | } |
687 | | |
688 | 0 | else |
689 | 0 | { |
690 | 0 | h = 0.0f; |
691 | 0 | s = 0.0f; |
692 | 0 | } |
693 | | |
694 | 0 | } |
695 | | |
696 | | /*****************************************************************************/ |
697 | | |
698 | | // Converts from HSV values (range 0.0 to 6.0 for hue, and 0.0 to 1.0 for |
699 | | // saturation and value) to RGB values (range 0.0 to 1.0). |
700 | | |
701 | | inline void DNG_HSVtoRGB (real32 h, |
702 | | real32 s, |
703 | | real32 v, |
704 | | real32 &r, |
705 | | real32 &g, |
706 | | real32 &b) |
707 | 0 | { |
708 | | |
709 | 0 | if (s > 0.0f) |
710 | 0 | { |
711 | | |
712 | 0 | if (!std::isfinite(h)) |
713 | 0 | ThrowProgramError("Unexpected NaN or Inf"); |
714 | 0 | h = std::fmod(h, 6.0f); |
715 | 0 | if (h < 0.0f) |
716 | 0 | h += 6.0f; |
717 | | |
718 | 0 | int32 i = (int32) h; |
719 | 0 | real32 f = h - (real32) i; |
720 | | |
721 | 0 | real32 p = v * (1.0f - s); |
722 | | |
723 | 0 | #define q (v * (1.0f - s * f)) |
724 | 0 | #define t (v * (1.0f - s * (1.0f - f))) |
725 | | |
726 | 0 | switch (i) |
727 | 0 | { |
728 | 0 | case 0: r = v; g = t; b = p; break; |
729 | 0 | case 1: r = q; g = v; b = p; break; |
730 | 0 | case 2: r = p; g = v; b = t; break; |
731 | 0 | case 3: r = p; g = q; b = v; break; |
732 | 0 | case 4: r = t; g = p; b = v; break; |
733 | 0 | case 5: r = v; g = p; b = q; break; |
734 | 0 | } |
735 | | |
736 | 0 | #undef q |
737 | 0 | #undef t |
738 | | |
739 | 0 | } |
740 | | |
741 | 0 | else |
742 | 0 | { |
743 | 0 | r = v; |
744 | 0 | g = v; |
745 | 0 | b = v; |
746 | 0 | } |
747 | | |
748 | 0 | } |
749 | | |
750 | | /******************************************************************************/ |
751 | | |
752 | | // High resolution timer, for code profiling. |
753 | | |
754 | | real64 TickTimeInSeconds (); |
755 | | |
756 | | // Lower resolution timer, but more stable. |
757 | | |
758 | | real64 TickCountInSeconds (); |
759 | | |
760 | | /******************************************************************************/ |
761 | | |
762 | | class dng_timer |
763 | | { |
764 | | |
765 | | public: |
766 | | |
767 | | dng_timer (const char *message); |
768 | | |
769 | | ~dng_timer (); |
770 | | |
771 | | private: |
772 | | |
773 | | // Hidden copy constructor and assignment operator. |
774 | | |
775 | | dng_timer (const dng_timer &timer); |
776 | | |
777 | | dng_timer & operator= (const dng_timer &timer); |
778 | | |
779 | | private: |
780 | | |
781 | | const char *fMessage; |
782 | | |
783 | | real64 fStartTime; |
784 | | |
785 | | }; |
786 | | |
787 | | /*****************************************************************************/ |
788 | | |
789 | | // Returns the maximum squared Euclidean distance from the specified point to the |
790 | | // specified rectangle rect. |
791 | | |
792 | | real64 MaxSquaredDistancePointToRect (const dng_point_real64 &point, |
793 | | const dng_rect_real64 &rect); |
794 | | |
795 | | /*****************************************************************************/ |
796 | | |
797 | | // Returns the maximum Euclidean distance from the specified point to the specified |
798 | | // rectangle rect. |
799 | | |
800 | | real64 MaxDistancePointToRect (const dng_point_real64 &point, |
801 | | const dng_rect_real64 &rect); |
802 | | |
803 | | /*****************************************************************************/ |
804 | | |
805 | | inline uint32 DNG_HalfToFloat (uint16 halfValue) |
806 | 269M | { |
807 | | |
808 | 269M | int32 sign = (halfValue >> 15) & 0x00000001; |
809 | 269M | int32 exponent = (halfValue >> 10) & 0x0000001f; |
810 | 269M | int32 mantissa = halfValue & 0x000003ff; |
811 | | |
812 | 269M | if (exponent == 0) |
813 | 187M | { |
814 | | |
815 | 187M | if (mantissa == 0) |
816 | 186M | { |
817 | | |
818 | | // Plus or minus zero |
819 | | |
820 | 186M | return (uint32) (sign << 31); |
821 | | |
822 | 186M | } |
823 | | |
824 | 903k | else |
825 | 903k | { |
826 | | |
827 | | // Denormalized number -- renormalize it |
828 | | |
829 | 5.05M | while (!(mantissa & 0x00000400)) |
830 | 4.14M | { |
831 | 4.14M | mantissa <<= 1; |
832 | 4.14M | exponent -= 1; |
833 | 4.14M | } |
834 | | |
835 | 903k | exponent += 1; |
836 | 903k | mantissa &= ~0x00000400; |
837 | | |
838 | 903k | } |
839 | | |
840 | 187M | } |
841 | | |
842 | 81.1M | else if (exponent == 31) |
843 | 7.68M | { |
844 | | |
845 | 7.68M | if (mantissa == 0) |
846 | 6.86M | { |
847 | | |
848 | | // Positive or negative infinity, convert to maximum (16 bit) values. |
849 | | |
850 | 6.86M | return (uint32) ((sign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13)); |
851 | | |
852 | 6.86M | } |
853 | | |
854 | 815k | else |
855 | 815k | { |
856 | | |
857 | | // Nan -- Just set to zero. |
858 | | |
859 | 815k | return 0; |
860 | | |
861 | 815k | } |
862 | | |
863 | 7.68M | } |
864 | | |
865 | | // Normalized number |
866 | | |
867 | 74.4M | exponent += (127 - 15); |
868 | 74.4M | mantissa <<= 13; |
869 | | |
870 | | // Assemble sign, exponent and mantissa. |
871 | | |
872 | 74.4M | return (uint32) ((sign << 31) | (exponent << 23) | mantissa); |
873 | | |
874 | 269M | } |
875 | | |
876 | | /*****************************************************************************/ |
877 | | |
878 | | inline uint16 DNG_FloatToHalf (uint32 i) |
879 | 415M | { |
880 | | |
881 | 415M | int32 sign = (i >> 16) & 0x00008000; |
882 | 415M | int32 exponent = ((i >> 23) & 0x000000ff) - (127 - 15); |
883 | 415M | int32 mantissa = i & 0x007fffff; |
884 | | |
885 | 415M | if (exponent <= 0) |
886 | 299M | { |
887 | | |
888 | 299M | if (exponent < -10) |
889 | 298M | { |
890 | | |
891 | | // Zero or underflow to zero. |
892 | | |
893 | 298M | return (uint16)sign; |
894 | | |
895 | 298M | } |
896 | | |
897 | | // E is between -10 and 0. We convert f to a denormalized half. |
898 | | |
899 | 1.26M | mantissa = (mantissa | 0x00800000) >> (1 - exponent); |
900 | | |
901 | | // Round to nearest, round "0.5" up. |
902 | | // |
903 | | // Rounding may cause the significand to overflow and make |
904 | | // our number normalized. Because of the way a half's bits |
905 | | // are laid out, we don't have to treat this case separately; |
906 | | // the code below will handle it correctly. |
907 | | |
908 | 1.26M | if (mantissa & 0x00001000) |
909 | 542k | mantissa += 0x00002000; |
910 | | |
911 | | // Assemble the half from sign, exponent (zero) and mantissa. |
912 | | |
913 | 1.26M | return (uint16)(sign | (mantissa >> 13)); |
914 | | |
915 | 299M | } |
916 | | |
917 | 115M | else if (exponent == 0xff - (127 - 15)) |
918 | 495k | { |
919 | | |
920 | 495k | if (mantissa == 0) |
921 | 92.5k | { |
922 | | |
923 | | // F is an infinity; convert f to a half |
924 | | // infinity with the same sign as f. |
925 | | |
926 | 92.5k | return (uint16)(sign | 0x7c00); |
927 | | |
928 | 92.5k | } |
929 | | |
930 | 402k | else |
931 | 402k | { |
932 | | |
933 | | // F is a NAN; produce a half NAN that preserves |
934 | | // the sign bit and the 10 leftmost bits of the |
935 | | // significand of f. |
936 | | |
937 | 402k | return (uint16)(sign | 0x7c00 | (mantissa >> 13)); |
938 | | |
939 | 402k | } |
940 | | |
941 | 495k | } |
942 | | |
943 | | // E is greater than zero. F is a normalized float. |
944 | | // We try to convert f to a normalized half. |
945 | | |
946 | | // Round to nearest, round "0.5" up |
947 | | |
948 | 115M | if (mantissa & 0x00001000) |
949 | 33.8M | { |
950 | | |
951 | 33.8M | mantissa += 0x00002000; |
952 | | |
953 | 33.8M | if (mantissa & 0x00800000) |
954 | 3.82M | { |
955 | 3.82M | mantissa = 0; // overflow in significand, |
956 | 3.82M | exponent += 1; // adjust exponent |
957 | 3.82M | } |
958 | | |
959 | 33.8M | } |
960 | | |
961 | | // Handle exponent overflow |
962 | | |
963 | 115M | if (exponent > 30) |
964 | 7.18M | { |
965 | 7.18M | return (uint16)(sign | 0x7c00); // infinity with the same sign as f. |
966 | 7.18M | } |
967 | | |
968 | | // Assemble the half from sign, exponent and mantissa. |
969 | | |
970 | 108M | return (uint16)(sign | (exponent << 10) | (mantissa >> 13)); |
971 | | |
972 | 115M | } |
973 | | |
974 | | /*****************************************************************************/ |
975 | | |
976 | | inline uint32 DNG_FP24ToFloat (const uint8 *input) |
977 | 8.89M | { |
978 | | |
979 | 8.89M | int32 sign = (input [0] >> 7) & 0x01; |
980 | 8.89M | int32 exponent = (input [0] ) & 0x7F; |
981 | 8.89M | int32 mantissa = (((int32) input [1]) << 8) | input[2]; |
982 | | |
983 | 8.89M | if (exponent == 0) |
984 | 3.04M | { |
985 | | |
986 | 3.04M | if (mantissa == 0) |
987 | 2.12M | { |
988 | | |
989 | | // Plus or minus zero |
990 | | |
991 | 2.12M | return (uint32) (sign << 31); |
992 | | |
993 | 2.12M | } |
994 | | |
995 | 919k | else |
996 | 919k | { |
997 | | |
998 | | // Denormalized number -- renormalize it |
999 | | |
1000 | 7.96M | while (!(mantissa & 0x00010000)) |
1001 | 7.04M | { |
1002 | 7.04M | mantissa <<= 1; |
1003 | 7.04M | exponent -= 1; |
1004 | 7.04M | } |
1005 | | |
1006 | 919k | exponent += 1; |
1007 | 919k | mantissa &= ~0x00010000; |
1008 | | |
1009 | 919k | } |
1010 | | |
1011 | 3.04M | } |
1012 | | |
1013 | 5.85M | else if (exponent == 127) |
1014 | 459k | { |
1015 | | |
1016 | 459k | if (mantissa == 0) |
1017 | 14.4k | { |
1018 | | |
1019 | | // Positive or negative infinity, convert to maximum (24 bit) values. |
1020 | | |
1021 | 14.4k | return (uint32) ((sign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7)); |
1022 | | |
1023 | 14.4k | } |
1024 | | |
1025 | 444k | else |
1026 | 444k | { |
1027 | | |
1028 | | // Nan -- Just set to zero. |
1029 | | |
1030 | 444k | return 0; |
1031 | | |
1032 | 444k | } |
1033 | | |
1034 | 459k | } |
1035 | | |
1036 | | // Normalized number |
1037 | | |
1038 | 6.31M | exponent += (128 - 64); |
1039 | 6.31M | mantissa <<= 7; |
1040 | | |
1041 | | // Assemble sign, exponent and mantissa. |
1042 | | |
1043 | 6.31M | return (uint32) ((sign << 31) | (exponent << 23) | mantissa); |
1044 | | |
1045 | 8.89M | } |
1046 | | |
1047 | | /*****************************************************************************/ |
1048 | | |
1049 | | inline void DNG_FloatToFP24 (uint32 input, uint8 *output) |
1050 | 4.73M | { |
1051 | | |
1052 | 4.73M | int32 exponent = (int32) ((input >> 23) & 0xFF) - 128; |
1053 | 4.73M | int32 mantissa = input & 0x007FFFFF; |
1054 | | |
1055 | 4.73M | if (exponent == 127) // infinity or NaN |
1056 | 24.7k | { |
1057 | | |
1058 | | // Will the NaN alais to infinity? |
1059 | | |
1060 | 24.7k | if (mantissa != 0x007FFFFF && ((mantissa >> 7) == 0xFFFF)) |
1061 | 286 | { |
1062 | | |
1063 | 286 | mantissa &= 0x003FFFFF; // knock out msb to make it a NaN |
1064 | | |
1065 | 286 | } |
1066 | | |
1067 | 24.7k | } |
1068 | | |
1069 | 4.71M | else if (exponent > 63) // overflow, map to infinity |
1070 | 110k | { |
1071 | | |
1072 | 110k | exponent = 63; |
1073 | 110k | mantissa = 0x007FFFFF; |
1074 | | |
1075 | 110k | } |
1076 | | |
1077 | 4.60M | else if (exponent <= -64) |
1078 | 3.20M | { |
1079 | | |
1080 | 3.20M | if (exponent >= -79) // encode as denorm |
1081 | 49.0k | { |
1082 | 49.0k | mantissa = (mantissa | 0x00800000) >> (-63 - exponent); |
1083 | 49.0k | } |
1084 | | |
1085 | 3.15M | else // underflow to zero |
1086 | 3.15M | { |
1087 | 3.15M | mantissa = 0; |
1088 | 3.15M | } |
1089 | | |
1090 | 3.20M | exponent = -64; |
1091 | | |
1092 | 3.20M | } |
1093 | | |
1094 | 4.73M | output [0] = (uint8)(((input >> 24) & 0x80) | (uint32) (exponent + 64)); |
1095 | | |
1096 | 4.73M | output [1] = (mantissa >> 15) & 0x00FF; |
1097 | 4.73M | output [2] = (mantissa >> 7) & 0x00FF; |
1098 | | |
1099 | 4.73M | } |
1100 | | |
1101 | | /******************************************************************************/ |
1102 | | |
1103 | | // The following code was from PSDivide.h in Photoshop. |
1104 | | |
1105 | | // High order 32-bits of an unsigned 32 by 32 multiply. |
1106 | | |
1107 | | #ifndef MULUH |
1108 | | |
1109 | | #if defined(_X86_) && defined(_MSC_VER) |
1110 | | |
1111 | | inline uint32 Muluh86 (uint32 x, uint32 y) |
1112 | | { |
1113 | | uint32 result; |
1114 | | __asm |
1115 | | { |
1116 | | MOV EAX, x |
1117 | | MUL y |
1118 | | MOV result, EDX |
1119 | | } |
1120 | | return (result); |
1121 | | } |
1122 | | |
1123 | | #define MULUH Muluh86 |
1124 | | |
1125 | | #else |
1126 | | |
1127 | 49.1k | #define MULUH(x,y) ((uint32) (((x) * (uint64) (y)) >> 32)) |
1128 | | |
1129 | | #endif |
1130 | | |
1131 | | #endif |
1132 | | |
1133 | | // High order 32-bits of an signed 32 by 32 multiply. |
1134 | | |
1135 | | #ifndef MULSH |
1136 | | |
1137 | | #if defined(_X86_) && defined(_MSC_VER) |
1138 | | |
1139 | | inline int32 Mulsh86 (int32 x, int32 y) |
1140 | | { |
1141 | | int32 result; |
1142 | | __asm |
1143 | | { |
1144 | | MOV EAX, x |
1145 | | IMUL y |
1146 | | MOV result, EDX |
1147 | | } |
1148 | | return (result); |
1149 | | } |
1150 | | |
1151 | | #define MULSH Mulsh86 |
1152 | | |
1153 | | #else |
1154 | | |
1155 | | #define MULSH(x,y) ((int32) (((x) * (int64) (y)) >> 32)) |
1156 | | |
1157 | | #endif |
1158 | | |
1159 | | #endif |
1160 | | |
1161 | | /******************************************************************************/ |
1162 | | |
1163 | | // Random number generator (identical to Apple's) for portable use. |
1164 | | |
1165 | | // This implements the "minimal standard random number generator" |
1166 | | // as proposed by Park and Miller in CACM October, 1988. |
1167 | | // It has a period of 2147483647 (0x7fffffff) |
1168 | | |
1169 | | // This is the ACM standard 30 bit generator: |
1170 | | // x' = (x * 16807) mod 2^31-1 |
1171 | | // This function intentionally exploits the defined behavior of unsigned integer |
1172 | | // overflow. |
1173 | | #if defined(__clang__) && defined(__has_attribute) |
1174 | | #if __has_attribute(no_sanitize) |
1175 | | __attribute__((no_sanitize("unsigned-integer-overflow"))) |
1176 | | #endif |
1177 | | #endif |
1178 | | inline uint32 DNG_Random (uint32 seed) |
1179 | 49.1k | { |
1180 | | |
1181 | | // high = seed / 127773 |
1182 | | |
1183 | 49.1k | uint32 temp = MULUH (0x069C16BD, seed); |
1184 | 49.1k | uint32 high = (temp + ((seed - temp) >> 1)) >> 16; |
1185 | | |
1186 | | // low = seed % 127773 |
1187 | | |
1188 | 49.1k | uint32 low = seed - high * 127773; |
1189 | | |
1190 | | // seed = (seed * 16807) % 2147483647 |
1191 | | |
1192 | 49.1k | seed = 16807 * low - 2836 * high; |
1193 | | |
1194 | 49.1k | if (seed & 0x80000000) |
1195 | 579 | seed += 2147483647; |
1196 | | |
1197 | 49.1k | return seed; |
1198 | | |
1199 | 49.1k | } |
1200 | | |
1201 | | /*****************************************************************************/ |
1202 | | |
1203 | | class dng_dither |
1204 | | { |
1205 | | |
1206 | | public: |
1207 | | |
1208 | | static const uint32 kRNGBits = 7; |
1209 | | |
1210 | | static const uint32 kRNGSize = 1 << kRNGBits; |
1211 | | |
1212 | | static const uint32 kRNGMask = kRNGSize - 1; |
1213 | | |
1214 | | static const uint32 kRNGSize2D = kRNGSize * kRNGSize; |
1215 | | |
1216 | | private: |
1217 | | |
1218 | | dng_memory_data fNoiseBuffer; |
1219 | | |
1220 | | private: |
1221 | | |
1222 | | dng_dither (); |
1223 | | |
1224 | | // Hidden copy constructor and assignment operator. |
1225 | | |
1226 | | dng_dither (const dng_dither &); |
1227 | | |
1228 | | dng_dither & operator= (const dng_dither &); |
1229 | | |
1230 | | public: |
1231 | | |
1232 | | static const dng_dither & Get (); |
1233 | | |
1234 | | public: |
1235 | | |
1236 | | const uint16 *NoiseBuffer16 () const |
1237 | 32.1k | { |
1238 | 32.1k | return fNoiseBuffer.Buffer_uint16 (); |
1239 | 32.1k | } |
1240 | | |
1241 | | }; |
1242 | | |
1243 | | /*****************************************************************************/ |
1244 | | |
1245 | | void HistogramArea (dng_host &host, |
1246 | | const dng_image &image, |
1247 | | const dng_rect &area, |
1248 | | uint32 *hist, |
1249 | | uint32 histLimit, |
1250 | | uint32 plane = 0); |
1251 | | |
1252 | | /*****************************************************************************/ |
1253 | | |
1254 | | void LimitFloatBitDepth (dng_host &host, |
1255 | | const dng_image &srcImage, |
1256 | | dng_image &dstImage, |
1257 | | uint32 bitDepth, |
1258 | | real32 scale = 1.0f); |
1259 | | |
1260 | | /*****************************************************************************/ |
1261 | | |
1262 | | #if qMacOS |
1263 | | |
1264 | | /*****************************************************************************/ |
1265 | | |
1266 | | template<typename T> |
1267 | | class CFReleaseHelper |
1268 | | { |
1269 | | |
1270 | | private: |
1271 | | |
1272 | | T fRef; |
1273 | | |
1274 | | public: |
1275 | | |
1276 | | CFReleaseHelper (T ref) |
1277 | | : fRef (ref) |
1278 | | { |
1279 | | } |
1280 | | |
1281 | | ~CFReleaseHelper () |
1282 | | { |
1283 | | if (fRef) |
1284 | | { |
1285 | | CFRelease (fRef); |
1286 | | } |
1287 | | } |
1288 | | |
1289 | | T Get () const |
1290 | | { |
1291 | | return fRef; |
1292 | | } |
1293 | | |
1294 | | }; |
1295 | | |
1296 | | /*****************************************************************************/ |
1297 | | |
1298 | | #endif // qMacOS |
1299 | | |
1300 | | /*****************************************************************************/ |
1301 | | |
1302 | | #endif |
1303 | | |
1304 | | /*****************************************************************************/ |