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