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 | { |
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 | uint32 mask = (uint32) (x >> 31); |
53 | |
54 | return (uint32) (((uint32) x + mask) ^ mask); |
55 | |
56 | #endif |
57 | |
58 | } |
59 | |
60 | inline int32 Min_int32 (int32 x, int32 y) |
61 | { |
62 | |
63 | return (x <= y ? x : y); |
64 | |
65 | } |
66 | |
67 | inline int32 Max_int32 (int32 x, int32 y) |
68 | { |
69 | |
70 | return (x >= y ? x : y); |
71 | |
72 | } |
73 | |
74 | inline int32 Pin_int32 (int32 min, int32 x, int32 max) |
75 | { |
76 | |
77 | return Max_int32 (min, Min_int32 (x, max)); |
78 | |
79 | } |
80 | |
81 | inline int32 Pin_int32_between (int32 a, int32 x, int32 b) |
82 | { |
83 | |
84 | int32 min, max; |
85 | if (a < b) { min = a; max = b; } |
86 | else { min = b; max = a; } |
87 | |
88 | return Pin_int32 (min, x, max); |
89 | |
90 | } |
91 | |
92 | /*****************************************************************************/ |
93 | |
94 | inline uint16 Min_uint16 (uint16 x, uint16 y) |
95 | { |
96 | |
97 | return (x <= y ? x : y); |
98 | |
99 | } |
100 | |
101 | inline uint16 Max_uint16 (uint16 x, uint16 y) |
102 | { |
103 | |
104 | return (x >= y ? x : y); |
105 | |
106 | } |
107 | |
108 | inline int16 Pin_int16 (int32 x) |
109 | { |
110 | |
111 | x = Pin_int32 (-32768, x, 32767); |
112 | |
113 | return (int16) x; |
114 | |
115 | } |
116 | |
117 | /*****************************************************************************/ |
118 | |
119 | inline uint32 Min_uint32 (uint32 x, uint32 y) |
120 | { |
121 | |
122 | return (x <= y ? x : y); |
123 | |
124 | } |
125 | |
126 | inline uint32 Min_uint32 (uint32 x, uint32 y, uint32 z) |
127 | { |
128 | |
129 | return Min_uint32 (x, Min_uint32 (y, z)); |
130 | |
131 | } |
132 | |
133 | inline uint32 Max_uint32 (uint32 x, uint32 y) |
134 | { |
135 | |
136 | return (x >= y ? x : y); |
137 | |
138 | } |
139 | |
140 | inline uint32 Max_uint32 (uint32 x, uint32 y, uint32 z) |
141 | { |
142 | |
143 | return Max_uint32 (x, Max_uint32 (y, z)); |
144 | |
145 | } |
146 | |
147 | inline uint32 Pin_uint32 (uint32 min, uint32 x, uint32 max) |
148 | { |
149 | |
150 | return Max_uint32 (min, Min_uint32 (x, max)); |
151 | |
152 | } |
153 | |
154 | /*****************************************************************************/ |
155 | |
156 | inline uint16 Pin_uint16 (int32 x) |
157 | { |
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 | if (x & ~65535) |
170 | { |
171 | |
172 | x = ~x >> 31; |
173 | |
174 | } |
175 | |
176 | #endif |
177 | |
178 | return (uint16) x; |
179 | |
180 | } |
181 | |
182 | /*****************************************************************************/ |
183 | |
184 | inline uint32 RoundDown2 (uint32 x) |
185 | { |
186 | |
187 | return x & (uint32) ~1; |
188 | |
189 | } |
190 | |
191 | inline uint32 RoundDown4 (uint32 x) |
192 | { |
193 | |
194 | return x & (uint32) ~3; |
195 | |
196 | } |
197 | |
198 | inline uint32 RoundDown8 (uint32 x) |
199 | { |
200 | |
201 | return x & (uint32) ~7; |
202 | |
203 | } |
204 | |
205 | inline uint32 RoundDown16 (uint32 x) |
206 | { |
207 | |
208 | return x & (uint32) ~15; |
209 | |
210 | } |
211 | |
212 | /******************************************************************************/ |
213 | |
214 | inline bool RoundUpForPixelSize (uint32 x, uint32 pixelSize, uint32 *result) |
215 | { |
216 | |
217 | uint32 multiple; |
218 | switch (pixelSize) |
219 | { |
220 | |
221 | case 1: |
222 | case 2: |
223 | case 4: |
224 | case 8: |
225 | multiple = 16 / pixelSize; |
226 | break; |
227 | |
228 | default: |
229 | multiple = 16; |
230 | break; |
231 | |
232 | } |
233 | |
234 | return RoundUpUint32ToMultiple(x, multiple, result); |
235 | |
236 | } |
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 | { |
261 | |
262 | return (uint64) (x < 0 ? -x : x); |
263 | |
264 | } |
265 | |
266 | inline int64 Min_int64 (int64 x, int64 y) |
267 | { |
268 | |
269 | return (x <= y ? x : y); |
270 | |
271 | } |
272 | |
273 | inline int64 Max_int64 (int64 x, int64 y) |
274 | { |
275 | |
276 | return (x >= y ? x : y); |
277 | |
278 | } |
279 | |
280 | inline int64 Pin_int64 (int64 min, int64 x, int64 max) |
281 | { |
282 | |
283 | return Max_int64 (min, Min_int64 (x, max)); |
284 | |
285 | } |
286 | |
287 | /******************************************************************************/ |
288 | |
289 | inline uint64 Min_uint64 (uint64 x, uint64 y) |
290 | { |
291 | |
292 | return (x <= y ? x : y); |
293 | |
294 | } |
295 | |
296 | inline uint64 Max_uint64 (uint64 x, uint64 y) |
297 | { |
298 | |
299 | return (x >= y ? x : y); |
300 | |
301 | } |
302 | |
303 | inline uint64 Pin_uint64 (uint64 min, uint64 x, uint64 max) |
304 | { |
305 | |
306 | return Max_uint64 (min, Min_uint64 (x, max)); |
307 | |
308 | } |
309 | |
310 | /*****************************************************************************/ |
311 | |
312 | inline real32 Abs_real32 (real32 x) |
313 | { |
314 | |
315 | return (x < 0.0f ? -x : x); |
316 | |
317 | } |
318 | |
319 | inline real32 Min_real32 (real32 x, real32 y) |
320 | { |
321 | |
322 | return (x < y ? x : y); |
323 | |
324 | } |
325 | |
326 | inline real32 Max_real32 (real32 x, real32 y) |
327 | { |
328 | |
329 | return (x > y ? x : y); |
330 | |
331 | } |
332 | |
333 | inline real32 Pin_real32 (real32 min, real32 x, real32 max) |
334 | { |
335 | |
336 | return Max_real32 (min, Min_real32 (x, max)); |
337 | |
338 | } |
339 | |
340 | inline real32 Pin_real32 (real32 x) |
341 | { |
342 | |
343 | return Pin_real32 (0.0f, x, 1.0f); |
344 | |
345 | } |
346 | |
347 | inline real32 Pin_real32_Overrange (real32 min, |
348 | real32 x, |
349 | real32 max) |
350 | { |
351 | |
352 | // Normal numbers in (min,max). No change. |
353 | |
354 | if (x > min && x < max) |
355 | { |
356 | return x; |
357 | } |
358 | |
359 | // Map large numbers (including positive infinity) to max. |
360 | |
361 | else if (x > min) |
362 | { |
363 | return max; |
364 | } |
365 | |
366 | // Map everything else (including negative infinity and all NaNs) to min. |
367 | |
368 | return min; |
369 | |
370 | } |
371 | |
372 | inline real32 Pin_Overrange (real32 x) |
373 | { |
374 | |
375 | // Normal in-range numbers, except for plus and minus zero. |
376 | |
377 | if (x > 0.0f && x <= 1.0f) |
378 | { |
379 | return x; |
380 | } |
381 | |
382 | // Large numbers, including positive infinity. |
383 | |
384 | else if (x > 0.5f) |
385 | { |
386 | return 1.0f; |
387 | } |
388 | |
389 | // Plus and minus zero, negative numbers, negative infinity, and all NaNs. |
390 | |
391 | return 0.0f; |
392 | |
393 | } |
394 | |
395 | inline real32 Lerp_real32 (real32 a, real32 b, real32 t) |
396 | { |
397 | |
398 | return a + t * (b - a); |
399 | |
400 | } |
401 | |
402 | /*****************************************************************************/ |
403 | |
404 | inline real64 Abs_real64 (real64 x) |
405 | { |
406 | |
407 | return (x < 0.0 ? -x : x); |
408 | |
409 | } |
410 | |
411 | inline real64 Min_real64 (real64 x, real64 y) |
412 | { |
413 | |
414 | return (x < y ? x : y); |
415 | |
416 | } |
417 | |
418 | inline real64 Max_real64 (real64 x, real64 y) |
419 | { |
420 | |
421 | return (x > y ? x : y); |
422 | |
423 | } |
424 | |
425 | inline real64 Pin_real64 (real64 min, real64 x, real64 max) |
426 | { |
427 | |
428 | return Max_real64 (min, Min_real64 (x, max)); |
429 | |
430 | } |
431 | |
432 | inline real64 Pin_real64 (real64 x) |
433 | { |
434 | |
435 | return Pin_real64 (0.0, x, 1.0); |
436 | |
437 | } |
438 | |
439 | inline real64 Pin_real64_Overrange (real64 min, |
440 | real64 x, |
441 | real64 max) |
442 | { |
443 | |
444 | // Normal numbers in (min,max). No change. |
445 | |
446 | if (x > min && x < max) |
447 | { |
448 | return x; |
449 | } |
450 | |
451 | // Map large numbers (including positive infinity) to max. |
452 | |
453 | else if (x > min) |
454 | { |
455 | return max; |
456 | } |
457 | |
458 | // Map everything else (including negative infinity and all NaNs) to min. |
459 | |
460 | return min; |
461 | |
462 | } |
463 | |
464 | inline real64 Lerp_real64 (real64 a, real64 b, real64 t) |
465 | { |
466 | |
467 | return a + t * (b - a); |
468 | |
469 | } |
470 | |
471 | /*****************************************************************************/ |
472 | |
473 | inline int32 Round_int32 (real32 x) |
474 | { |
475 | |
476 | return (int32) (x > 0.0f ? x + 0.5f : x - 0.5f); |
477 | |
478 | } |
479 | |
480 | inline int32 Round_int32 (real64 x) |
481 | { |
482 | |
483 | 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 | if (temp > real64(std::numeric_limits<int32>::min()) - 1.0 && |
488 | temp < real64(std::numeric_limits<int32>::max()) + 1.0) |
489 | { |
490 | return (int32) temp; |
491 | } |
492 | |
493 | else |
494 | { |
495 | ThrowProgramError("Overflow in Round_int32" ); |
496 | // Dummy return. |
497 | return 0; |
498 | } |
499 | |
500 | } |
501 | |
502 | inline uint32 Floor_uint32 (real32 x) |
503 | { |
504 | |
505 | return (uint32) Max_real32 (0.0f, x); |
506 | |
507 | } |
508 | |
509 | inline uint32 Floor_uint32 (real64 x) |
510 | { |
511 | |
512 | 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 | if (temp < real64(std::numeric_limits<uint32>::max()) + 1.0) |
517 | { |
518 | return (uint32) temp; |
519 | } |
520 | |
521 | else |
522 | { |
523 | ThrowProgramError("Overflow in Floor_uint32" ); |
524 | // Dummy return. |
525 | return 0; |
526 | } |
527 | |
528 | } |
529 | |
530 | inline uint32 Round_uint32 (real32 x) |
531 | { |
532 | |
533 | return Floor_uint32 (x + 0.5f); |
534 | |
535 | } |
536 | |
537 | inline uint32 Round_uint32 (real64 x) |
538 | { |
539 | |
540 | return Floor_uint32 (x + 0.5); |
541 | |
542 | } |
543 | |
544 | /******************************************************************************/ |
545 | |
546 | inline int64 Round_int64 (real64 x) |
547 | { |
548 | |
549 | return (int64) (x >= 0.0 ? x + 0.5 : x - 0.5); |
550 | |
551 | } |
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 | { |
562 | |
563 | return Round_int64 (x * (real64) kFixed64_One); |
564 | |
565 | } |
566 | |
567 | /******************************************************************************/ |
568 | |
569 | inline real64 Fixed64ToReal64 (int64 x) |
570 | { |
571 | |
572 | return x * (1.0 / (real64) kFixed64_One); |
573 | |
574 | } |
575 | |
576 | /*****************************************************************************/ |
577 | |
578 | inline char ForceUppercase (char c) |
579 | { |
580 | |
581 | if (c >= 'a' && c <= 'z') |
582 | { |
583 | |
584 | c -= 'a' - 'A'; |
585 | |
586 | } |
587 | |
588 | return c; |
589 | |
590 | } |
591 | |
592 | /*****************************************************************************/ |
593 | |
594 | inline uint16 SwapBytes16 (uint16 x) |
595 | { |
596 | |
597 | return (uint16) ((x << 8) | |
598 | (x >> 8)); |
599 | |
600 | } |
601 | |
602 | inline uint32 SwapBytes32 (uint32 x) |
603 | { |
604 | |
605 | return (x << 24) + |
606 | ((x << 8) & 0x00FF0000) + |
607 | ((x >> 8) & 0x0000FF00) + |
608 | (x >> 24); |
609 | |
610 | } |
611 | |
612 | /*****************************************************************************/ |
613 | |
614 | inline bool IsAligned16 (const void *p) |
615 | { |
616 | |
617 | return (((uintptr) p) & 1) == 0; |
618 | |
619 | } |
620 | |
621 | inline bool IsAligned32 (const void *p) |
622 | { |
623 | |
624 | return (((uintptr) p) & 3) == 0; |
625 | |
626 | } |
627 | |
628 | inline bool IsAligned64 (const void *p) |
629 | { |
630 | |
631 | return (((uintptr) p) & 7) == 0; |
632 | |
633 | } |
634 | |
635 | inline bool IsAligned128 (const void *p) |
636 | { |
637 | |
638 | return (((uintptr) p) & 15) == 0; |
639 | |
640 | } |
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 | { |
654 | |
655 | v = Max_real32 (r, Max_real32 (g, b)); |
656 | |
657 | real32 gap = v - Min_real32 (r, Min_real32 (g, b)); |
658 | |
659 | if (gap > 0.0f) |
660 | { |
661 | |
662 | if (r == v) |
663 | { |
664 | |
665 | h = (g - b) / gap; |
666 | |
667 | if (h < 0.0f) |
668 | { |
669 | h += 6.0f; |
670 | } |
671 | |
672 | } |
673 | |
674 | else if (g == v) |
675 | { |
676 | h = 2.0f + (b - r) / gap; |
677 | } |
678 | |
679 | else |
680 | { |
681 | h = 4.0f + (r - g) / gap; |
682 | } |
683 | |
684 | s = gap / v; |
685 | |
686 | } |
687 | |
688 | else |
689 | { |
690 | h = 0.0f; |
691 | s = 0.0f; |
692 | } |
693 | |
694 | } |
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 | { |
708 | |
709 | if (s > 0.0f) |
710 | { |
711 | |
712 | if (!std::isfinite(h)) |
713 | ThrowProgramError("Unexpected NaN or Inf" ); |
714 | h = std::fmod(h, 6.0f); |
715 | if (h < 0.0f) |
716 | h += 6.0f; |
717 | |
718 | int32 i = (int32) h; |
719 | real32 f = h - (real32) i; |
720 | |
721 | real32 p = v * (1.0f - s); |
722 | |
723 | #define q (v * (1.0f - s * f)) |
724 | #define t (v * (1.0f - s * (1.0f - f))) |
725 | |
726 | switch (i) |
727 | { |
728 | case 0: r = v; g = t; b = p; break; |
729 | case 1: r = q; g = v; b = p; break; |
730 | case 2: r = p; g = v; b = t; break; |
731 | case 3: r = p; g = q; b = v; break; |
732 | case 4: r = t; g = p; b = v; break; |
733 | case 5: r = v; g = p; b = q; break; |
734 | } |
735 | |
736 | #undef q |
737 | #undef t |
738 | |
739 | } |
740 | |
741 | else |
742 | { |
743 | r = v; |
744 | g = v; |
745 | b = v; |
746 | } |
747 | |
748 | } |
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 | { |
807 | |
808 | int32 sign = (halfValue >> 15) & 0x00000001; |
809 | int32 exponent = (halfValue >> 10) & 0x0000001f; |
810 | int32 mantissa = halfValue & 0x000003ff; |
811 | |
812 | if (exponent == 0) |
813 | { |
814 | |
815 | if (mantissa == 0) |
816 | { |
817 | |
818 | // Plus or minus zero |
819 | |
820 | return (uint32) (sign << 31); |
821 | |
822 | } |
823 | |
824 | else |
825 | { |
826 | |
827 | // Denormalized number -- renormalize it |
828 | |
829 | while (!(mantissa & 0x00000400)) |
830 | { |
831 | mantissa <<= 1; |
832 | exponent -= 1; |
833 | } |
834 | |
835 | exponent += 1; |
836 | mantissa &= ~0x00000400; |
837 | |
838 | } |
839 | |
840 | } |
841 | |
842 | else if (exponent == 31) |
843 | { |
844 | |
845 | if (mantissa == 0) |
846 | { |
847 | |
848 | // Positive or negative infinity, convert to maximum (16 bit) values. |
849 | |
850 | return (uint32) ((sign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13)); |
851 | |
852 | } |
853 | |
854 | else |
855 | { |
856 | |
857 | // Nan -- Just set to zero. |
858 | |
859 | return 0; |
860 | |
861 | } |
862 | |
863 | } |
864 | |
865 | // Normalized number |
866 | |
867 | exponent += (127 - 15); |
868 | mantissa <<= 13; |
869 | |
870 | // Assemble sign, exponent and mantissa. |
871 | |
872 | return (uint32) ((sign << 31) | (exponent << 23) | mantissa); |
873 | |
874 | } |
875 | |
876 | /*****************************************************************************/ |
877 | |
878 | inline uint16 DNG_FloatToHalf (uint32 i) |
879 | { |
880 | |
881 | int32 sign = (i >> 16) & 0x00008000; |
882 | int32 exponent = ((i >> 23) & 0x000000ff) - (127 - 15); |
883 | int32 mantissa = i & 0x007fffff; |
884 | |
885 | if (exponent <= 0) |
886 | { |
887 | |
888 | if (exponent < -10) |
889 | { |
890 | |
891 | // Zero or underflow to zero. |
892 | |
893 | return (uint16)sign; |
894 | |
895 | } |
896 | |
897 | // E is between -10 and 0. We convert f to a denormalized half. |
898 | |
899 | 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 | if (mantissa & 0x00001000) |
909 | mantissa += 0x00002000; |
910 | |
911 | // Assemble the half from sign, exponent (zero) and mantissa. |
912 | |
913 | return (uint16)(sign | (mantissa >> 13)); |
914 | |
915 | } |
916 | |
917 | else if (exponent == 0xff - (127 - 15)) |
918 | { |
919 | |
920 | if (mantissa == 0) |
921 | { |
922 | |
923 | // F is an infinity; convert f to a half |
924 | // infinity with the same sign as f. |
925 | |
926 | return (uint16)(sign | 0x7c00); |
927 | |
928 | } |
929 | |
930 | else |
931 | { |
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 | return (uint16)(sign | 0x7c00 | (mantissa >> 13)); |
938 | |
939 | } |
940 | |
941 | } |
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 | if (mantissa & 0x00001000) |
949 | { |
950 | |
951 | mantissa += 0x00002000; |
952 | |
953 | if (mantissa & 0x00800000) |
954 | { |
955 | mantissa = 0; // overflow in significand, |
956 | exponent += 1; // adjust exponent |
957 | } |
958 | |
959 | } |
960 | |
961 | // Handle exponent overflow |
962 | |
963 | if (exponent > 30) |
964 | { |
965 | return (uint16)(sign | 0x7c00); // infinity with the same sign as f. |
966 | } |
967 | |
968 | // Assemble the half from sign, exponent and mantissa. |
969 | |
970 | return (uint16)(sign | (exponent << 10) | (mantissa >> 13)); |
971 | |
972 | } |
973 | |
974 | /*****************************************************************************/ |
975 | |
976 | inline uint32 DNG_FP24ToFloat (const uint8 *input) |
977 | { |
978 | |
979 | int32 sign = (input [0] >> 7) & 0x01; |
980 | int32 exponent = (input [0] ) & 0x7F; |
981 | int32 mantissa = (((int32) input [1]) << 8) | input[2]; |
982 | |
983 | if (exponent == 0) |
984 | { |
985 | |
986 | if (mantissa == 0) |
987 | { |
988 | |
989 | // Plus or minus zero |
990 | |
991 | return (uint32) (sign << 31); |
992 | |
993 | } |
994 | |
995 | else |
996 | { |
997 | |
998 | // Denormalized number -- renormalize it |
999 | |
1000 | while (!(mantissa & 0x00010000)) |
1001 | { |
1002 | mantissa <<= 1; |
1003 | exponent -= 1; |
1004 | } |
1005 | |
1006 | exponent += 1; |
1007 | mantissa &= ~0x00010000; |
1008 | |
1009 | } |
1010 | |
1011 | } |
1012 | |
1013 | else if (exponent == 127) |
1014 | { |
1015 | |
1016 | if (mantissa == 0) |
1017 | { |
1018 | |
1019 | // Positive or negative infinity, convert to maximum (24 bit) values. |
1020 | |
1021 | return (uint32) ((sign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7)); |
1022 | |
1023 | } |
1024 | |
1025 | else |
1026 | { |
1027 | |
1028 | // Nan -- Just set to zero. |
1029 | |
1030 | return 0; |
1031 | |
1032 | } |
1033 | |
1034 | } |
1035 | |
1036 | // Normalized number |
1037 | |
1038 | exponent += (128 - 64); |
1039 | mantissa <<= 7; |
1040 | |
1041 | // Assemble sign, exponent and mantissa. |
1042 | |
1043 | return (uint32) ((sign << 31) | (exponent << 23) | mantissa); |
1044 | |
1045 | } |
1046 | |
1047 | /*****************************************************************************/ |
1048 | |
1049 | inline void DNG_FloatToFP24 (uint32 input, uint8 *output) |
1050 | { |
1051 | |
1052 | int32 exponent = (int32) ((input >> 23) & 0xFF) - 128; |
1053 | int32 mantissa = input & 0x007FFFFF; |
1054 | |
1055 | if (exponent == 127) // infinity or NaN |
1056 | { |
1057 | |
1058 | // Will the NaN alais to infinity? |
1059 | |
1060 | if (mantissa != 0x007FFFFF && ((mantissa >> 7) == 0xFFFF)) |
1061 | { |
1062 | |
1063 | mantissa &= 0x003FFFFF; // knock out msb to make it a NaN |
1064 | |
1065 | } |
1066 | |
1067 | } |
1068 | |
1069 | else if (exponent > 63) // overflow, map to infinity |
1070 | { |
1071 | |
1072 | exponent = 63; |
1073 | mantissa = 0x007FFFFF; |
1074 | |
1075 | } |
1076 | |
1077 | else if (exponent <= -64) |
1078 | { |
1079 | |
1080 | if (exponent >= -79) // encode as denorm |
1081 | { |
1082 | mantissa = (mantissa | 0x00800000) >> (-63 - exponent); |
1083 | } |
1084 | |
1085 | else // underflow to zero |
1086 | { |
1087 | mantissa = 0; |
1088 | } |
1089 | |
1090 | exponent = -64; |
1091 | |
1092 | } |
1093 | |
1094 | output [0] = (uint8)(((input >> 24) & 0x80) | (uint32) (exponent + 64)); |
1095 | |
1096 | output [1] = (mantissa >> 15) & 0x00FF; |
1097 | output [2] = (mantissa >> 7) & 0x00FF; |
1098 | |
1099 | } |
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 | #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 | { |
1180 | |
1181 | // high = seed / 127773 |
1182 | |
1183 | uint32 temp = MULUH (0x069C16BD, seed); |
1184 | uint32 high = (temp + ((seed - temp) >> 1)) >> 16; |
1185 | |
1186 | // low = seed % 127773 |
1187 | |
1188 | uint32 low = seed - high * 127773; |
1189 | |
1190 | // seed = (seed * 16807) % 2147483647 |
1191 | |
1192 | seed = 16807 * low - 2836 * high; |
1193 | |
1194 | if (seed & 0x80000000) |
1195 | seed += 2147483647; |
1196 | |
1197 | return seed; |
1198 | |
1199 | } |
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 | { |
1238 | return fNoiseBuffer.Buffer_uint16 (); |
1239 | } |
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 | #endif |
1263 | |
1264 | /*****************************************************************************/ |
1265 | |