File indexing completed on 2025-01-19 03:55:18

0001 /*****************************************************************************/
0002 // Copyright 2006-2019 Adobe Systems Incorporated
0003 // All Rights Reserved.
0004 //
0005 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
0006 // accordance with the terms of the Adobe license agreement accompanying it.
0007 /*****************************************************************************/
0008 
0009 #ifndef __dng_utils__
0010 #define __dng_utils__
0011 
0012 /*****************************************************************************/
0013 
0014 #include "dng_classes.h"
0015 #include "dng_flags.h"
0016 #include "dng_memory.h"
0017 #include "dng_safe_arithmetic.h"
0018 #include "dng_types.h"
0019 #include "dng_uncopyable.h"
0020 
0021 /*****************************************************************************/
0022 
0023 // The unsigned integer overflow is intended here since a wrap around is used to
0024 // calculate the abs() in the branchless version.
0025 
0026 DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow")
0027 inline uint32 Abs_int32 (int32 x)
0028     {
0029 
0030     #if 0
0031 
0032     // Reference version.
0033 
0034     return (uint32) (x < 0 ? -x : x);
0035 
0036     #else
0037 
0038     // Branchless version.
0039 
0040     uint32 mask = (uint32) (x >> 31);
0041 
0042     return (uint32) (((uint32) x + mask) ^ mask);
0043 
0044     #endif
0045 
0046     }
0047 
0048 inline int32 Min_int32 (int32 x, int32 y)
0049     {
0050 
0051     return (x <= y ? x : y);
0052 
0053     }
0054 
0055 inline int32 Max_int32 (int32 x, int32 y)
0056     {
0057 
0058     return (x >= y ? x : y);
0059 
0060     }
0061 
0062 inline int32 Pin_int32 (int32 min, int32 x, int32 max)
0063     {
0064 
0065     return Max_int32 (min, Min_int32 (x, max));
0066 
0067     }
0068 
0069 inline int32 Pin_int32_between (int32 a, int32 x, int32 b)
0070     {
0071 
0072     int32 min, max;
0073     if (a < b) { min = a; max = b; }
0074     else { min = b; max = a; }
0075 
0076     return Pin_int32 (min, x, max);
0077 
0078     }
0079 
0080 /*****************************************************************************/
0081 
0082 inline uint16 Min_uint16 (uint16 x, uint16 y)
0083     {
0084 
0085     return (x <= y ? x : y);
0086 
0087     }
0088 
0089 inline uint16 Max_uint16 (uint16 x, uint16 y)
0090     {
0091 
0092     return (x >= y ? x : y);
0093 
0094     }
0095 
0096 inline int16 Pin_int16 (int32 x)
0097     {
0098 
0099     x = Pin_int32 (-32768, x, 32767);
0100 
0101     return (int16) x;
0102 
0103     }
0104 
0105 /*****************************************************************************/
0106 
0107 inline uint32 Min_uint32 (uint32 x, uint32 y)
0108     {
0109 
0110     return (x <= y ? x : y);
0111 
0112     }
0113 
0114 inline uint32 Min_uint32 (uint32 x, uint32 y, uint32 z)
0115     {
0116 
0117     return Min_uint32 (x, Min_uint32 (y, z));
0118 
0119     }
0120 
0121 inline uint32 Max_uint32 (uint32 x, uint32 y)
0122     {
0123 
0124     return (x >= y ? x : y);
0125 
0126     }
0127 
0128 inline uint32 Max_uint32 (uint32 x, uint32 y, uint32 z)
0129     {
0130 
0131     return Max_uint32 (x, Max_uint32 (y, z));
0132 
0133     }
0134 
0135 inline uint32 Pin_uint32 (uint32 min, uint32 x, uint32 max)
0136     {
0137 
0138     return Max_uint32 (min, Min_uint32 (x, max));
0139 
0140     }
0141 
0142 /*****************************************************************************/
0143 
0144 inline uint16 Pin_uint16 (int32 x)
0145     {
0146 
0147     #if 0
0148 
0149     // Reference version.
0150 
0151     x = Pin_int32 (0, x, 0x0FFFF);
0152 
0153     #else
0154 
0155     // Single branch version.
0156 
0157     if (x & ~65535)
0158         {
0159 
0160         x = ~x >> 31;
0161 
0162         }
0163 
0164     #endif
0165 
0166     return (uint16) x;
0167 
0168     }
0169 
0170 /*****************************************************************************/
0171 
0172 inline uint32 RoundUp2 (uint32 x)
0173     {
0174 
0175     return (x + 1) & (uint32) ~1;
0176 
0177     }
0178 
0179 inline uint32 RoundUp4 (uint32 x)
0180     {
0181 
0182     return (x + 3) & (uint32) ~3;
0183 
0184     }
0185 
0186 inline uint32 RoundUp8 (uint32 x)
0187     {
0188 
0189     return (x + 7) & (uint32) ~7;
0190 
0191     }
0192 
0193 inline uint32 RoundUp16 (uint32 x)
0194     {
0195 
0196     return (x + 15) & (uint32) ~15;
0197 
0198     }
0199 
0200 inline uint32 RoundUp32 (uint32 x)
0201     {
0202 
0203     return (x + 31) & (uint32) ~31;
0204 
0205     }
0206 
0207 inline uint32 RoundUpSIMD (uint32 x)
0208     {
0209 
0210     #if qDNGAVXSupport
0211     return RoundUp32 (x);
0212     #else
0213     return RoundUp16 (x);
0214     #endif
0215 
0216     }
0217 
0218 inline uint32 RoundUp4096 (uint32 x)
0219     {
0220 
0221     return (x + 4095) & (uint32) ~4095;
0222 
0223     }
0224 
0225 /******************************************************************************/
0226 
0227 inline uint32 RoundDown2 (uint32 x)
0228     {
0229 
0230     return x & (uint32) ~1;
0231 
0232     }
0233 
0234 inline uint32 RoundDown4 (uint32 x)
0235     {
0236 
0237     return x & (uint32) ~3;
0238 
0239     }
0240 
0241 inline uint32 RoundDown8 (uint32 x)
0242     {
0243 
0244     return x & (uint32) ~7;
0245 
0246     }
0247 
0248 inline uint32 RoundDown16 (uint32 x)
0249     {
0250 
0251     return x & (uint32) ~15;
0252 
0253     }
0254 
0255 inline uint32 RoundDown32 (uint32 x)
0256     {
0257 
0258     return x & (uint32) ~31;
0259 
0260     }
0261 
0262 inline uint32 RoundDownSIMD (uint32 x)
0263     {
0264 
0265     #if qDNGAVXSupport
0266     return RoundDown32 (x);
0267     #else
0268     return RoundDown16 (x);
0269     #endif
0270 
0271     }
0272 
0273 /******************************************************************************/
0274 
0275 inline bool RoundUpForPixelSize (uint32 x,
0276                                  uint32 pixelSize,
0277                                  uint32 *result)
0278     {
0279 
0280     #if qDNGAVXSupport
0281     static const uint32 kTargetMultiple = 32;
0282     #else
0283     static const uint32 kTargetMultiple = 16;
0284     #endif
0285 
0286     uint32 multiple;
0287 
0288     switch (pixelSize)
0289         {
0290 
0291         case 1:
0292         case 2:
0293         case 4:
0294         case 8:
0295             {
0296             multiple = kTargetMultiple / pixelSize;
0297             break;
0298             }
0299 
0300         default:
0301             {
0302             multiple = kTargetMultiple;
0303             break;
0304             }
0305 
0306         }
0307 
0308     return RoundUpUint32ToMultiple (x, multiple, result);
0309 
0310     }
0311 
0312 /******************************************************************************/
0313 
0314 inline uint32 RoundUpForPixelSize (uint32 x,
0315                                    uint32 pixelSize)
0316     {
0317 
0318     uint32 result = 0;
0319 
0320     if (!RoundUpForPixelSize (x, pixelSize, &result))
0321         {
0322         ThrowOverflow ("RoundUpForPixelSize");
0323         }
0324 
0325     return result;
0326 
0327     }
0328 
0329 /******************************************************************************/
0330 
0331 inline int32 RoundUpForPixelSizeAsInt32 (uint32 x,
0332                                          uint32 pixelSize)
0333     {
0334 
0335     uint32 result = 0;
0336 
0337     if (!RoundUpForPixelSize (x, pixelSize, &result))
0338         {
0339         ThrowOverflow ("RoundUpForPixelSize");
0340         }
0341 
0342     dng_safe_uint32 safeResult (result);
0343 
0344     return dng_safe_int32 (safeResult).Get ();
0345 
0346     }
0347 
0348 /******************************************************************************/
0349 
0350 // Type of padding to be performed by ComputeBufferSize.
0351 
0352 enum PaddingType
0353     {
0354 
0355     // Don't perform any padding.
0356 
0357     padNone,
0358 
0359     // Pad each scanline to an integer multiple of SIMD vector width (16 or
0360     // 32) bytes (in the same way that RoundUpForPixelSize() does).
0361 
0362     padSIMDBytes
0363 
0364     };
0365 
0366 // Returns the number of bytes required for an image tile with the given pixel
0367 // type, tile size, number of image planes, and desired padding. Throws a
0368 // dng_exception with dng_error_memory error code if one of the components of
0369 // tileSize is negative or if arithmetic overflow occurs during the
0370 // computation.
0371 
0372 uint32 ComputeBufferSize (uint32 pixelType,
0373                           const dng_point &tileSize,
0374                           uint32 numPlanes,
0375                           PaddingType paddingType);
0376 
0377 /******************************************************************************/
0378 
0379 inline uint64 Abs_int64 (int64 x)
0380     {
0381 
0382     return (uint64) (x < 0 ? -x : x);
0383 
0384     }
0385 
0386 inline int64 Min_int64 (int64 x, int64 y)
0387     {
0388 
0389     return (x <= y ? x : y);
0390 
0391     }
0392 
0393 inline int64 Max_int64 (int64 x, int64 y)
0394     {
0395 
0396     return (x >= y ? x : y);
0397 
0398     }
0399 
0400 inline int64 Pin_int64 (int64 min, int64 x, int64 max)
0401     {
0402 
0403     return Max_int64 (min, Min_int64 (x, max));
0404 
0405     }
0406 
0407 /******************************************************************************/
0408 
0409 inline uint64 Min_uint64 (uint64 x, uint64 y)
0410     {
0411 
0412     return (x <= y ? x : y);
0413 
0414     }
0415 
0416 inline uint64 Max_uint64 (uint64 x, uint64 y)
0417     {
0418 
0419     return (x >= y ? x : y);
0420 
0421     }
0422 
0423 inline uint64 Pin_uint64 (uint64 min, uint64 x, uint64 max)
0424     {
0425 
0426     return Max_uint64 (min, Min_uint64 (x, max));
0427 
0428     }
0429 
0430 /*****************************************************************************/
0431 
0432 inline real32 Abs_real32 (real32 x)
0433     {
0434 
0435     return (x < 0.0f ? -x : x);
0436 
0437     }
0438 
0439 inline real32 Min_real32 (real32 x, real32 y)
0440     {
0441 
0442     return (x < y ? x : y);
0443 
0444     }
0445 
0446 inline real32 Max_real32 (real32 x, real32 y)
0447     {
0448 
0449     return (x > y ? x : y);
0450 
0451     }
0452 
0453 inline real32 Pin_real32 (real32 min, real32 x, real32 max)
0454     {
0455 
0456     return Max_real32 (min, Min_real32 (x, max));
0457 
0458     }
0459 
0460 inline real32 Pin_real32 (real32 x)
0461     {
0462 
0463     return Pin_real32 (0.0f, x, 1.0f);
0464 
0465     }
0466 
0467 inline real32 Pin_real32_Overrange (real32 min,
0468                                     real32 x,
0469                                     real32 max)
0470     {
0471 
0472     // Normal numbers in (min,max). No change.
0473 
0474     if (x > min && x < max)
0475         {
0476         return x;
0477         }
0478 
0479     // Map large numbers (including positive infinity) to max.
0480 
0481     else if (x > min)
0482         {
0483         return max;
0484         }
0485 
0486     // Map everything else (including negative infinity and all NaNs) to min.
0487 
0488     return min;
0489 
0490     }
0491 
0492 inline real32 Pin_Overrange (real32 x)
0493     {
0494 
0495     // Normal in-range numbers, except for plus and minus zero.
0496 
0497     if (x > 0.0f && x <= 1.0f)
0498         {
0499         return x;
0500         }
0501 
0502     // Large numbers, including positive infinity.
0503 
0504     else if (x > 0.5f)
0505         {
0506         return 1.0f;
0507         }
0508 
0509     // Plus and minus zero, negative numbers, negative infinity, and all NaNs.
0510 
0511     return 0.0f;
0512 
0513     }
0514 
0515 inline real32 Lerp_real32 (real32 a, real32 b, real32 t)
0516     {
0517 
0518     return a + t * (b - a);
0519 
0520     }
0521 
0522 /*****************************************************************************/
0523 
0524 inline real64 Abs_real64 (real64 x)
0525     {
0526 
0527     return (x < 0.0 ? -x : x);
0528 
0529     }
0530 
0531 inline real64 Min_real64 (real64 x, real64 y)
0532     {
0533 
0534     return (x < y ? x : y);
0535 
0536     }
0537 
0538 inline real64 Max_real64 (real64 x, real64 y)
0539     {
0540 
0541     return (x > y ? x : y);
0542 
0543     }
0544 
0545 inline real64 Pin_real64 (real64 min, real64 x, real64 max)
0546     {
0547 
0548     return Max_real64 (min, Min_real64 (x, max));
0549 
0550     }
0551 
0552 inline real64 Pin_real64 (real64 x)
0553     {
0554 
0555     return Pin_real64 (0.0, x, 1.0);
0556 
0557     }
0558 
0559 inline real64 Pin_real64_Overrange (real64 min,
0560                                     real64 x,
0561                                     real64 max)
0562     {
0563 
0564     // Normal numbers in (min,max). No change.
0565 
0566     if (x > min && x < max)
0567         {
0568         return x;
0569         }
0570 
0571     // Map large numbers (including positive infinity) to max.
0572 
0573     else if (x > min)
0574         {
0575         return max;
0576         }
0577 
0578     // Map everything else (including negative infinity and all NaNs) to min.
0579 
0580     return min;
0581 
0582     }
0583 
0584 inline real64 Lerp_real64 (real64 a, real64 b, real64 t)
0585     {
0586 
0587     return a + t * (b - a);
0588 
0589     }
0590 
0591 /*****************************************************************************/
0592 
0593 inline int32 Round_int32 (real32 x)
0594     {
0595 
0596     return (int32) (x > 0.0f ? x + 0.5f : x - 0.5f);
0597 
0598     }
0599 
0600 inline int32 Round_int32 (real64 x)
0601     {
0602 
0603     return (int32) (x > 0.0 ? x + 0.5 : x - 0.5);
0604 
0605     }
0606 
0607 inline uint32 Floor_uint32 (real32 x)
0608     {
0609 
0610     return (uint32) Max_real32 (0.0f, x);
0611 
0612     }
0613 
0614 DNG_ATTRIB_NO_SANITIZE("float-cast-overflow")
0615 inline uint32 Floor_uint32 (real64 x)
0616     {
0617 
0618     return (uint32) Max_real64 (0.0, x);
0619 
0620     }
0621 
0622 inline uint32 Round_uint32 (real32 x)
0623     {
0624 
0625     return Floor_uint32 (x + 0.5f);
0626 
0627     }
0628 
0629 inline uint32 Round_uint32 (real64 x)
0630     {
0631 
0632     return Floor_uint32 (x + 0.5);
0633 
0634     }
0635 
0636 /******************************************************************************/
0637 
0638 inline int64 Round_int64 (real64 x)
0639     {
0640 
0641     return (int64) (x >= 0.0 ? x + 0.5 : x - 0.5);
0642 
0643     }
0644 
0645 /*****************************************************************************/
0646 
0647 const int64 kFixed64_One  = (((int64) 1) << 32);
0648 const int64 kFixed64_Half = (((int64) 1) << 31);
0649 
0650 /******************************************************************************/
0651 
0652 inline int64 Real64ToFixed64 (real64 x)
0653     {
0654 
0655     return Round_int64 (x * (real64) kFixed64_One);
0656 
0657     }
0658 
0659 /******************************************************************************/
0660 
0661 inline real64 Fixed64ToReal64 (int64 x)
0662     {
0663 
0664     return x * (1.0 / (real64) kFixed64_One);
0665 
0666     }
0667 
0668 /*****************************************************************************/
0669 
0670 inline char ForceUppercase (char c)
0671     {
0672 
0673     if (c >= 'a' && c <= 'z')
0674         {
0675 
0676         c -= 'a' - 'A';
0677 
0678         }
0679 
0680     return c;
0681 
0682     }
0683 
0684 /*****************************************************************************/
0685 
0686 inline uint16 SwapBytes16 (uint16 x)
0687     {
0688 
0689     return (uint16) ((x << 8) |
0690                      (x >> 8));
0691 
0692     }
0693 
0694 inline uint32 SwapBytes32 (uint32 x)
0695     {
0696 
0697     return (x << 24) +
0698            ((x << 8) & 0x00FF0000) +
0699            ((x >> 8) & 0x0000FF00) +
0700            (x >> 24);
0701 
0702     }
0703 
0704 /*****************************************************************************/
0705 
0706 inline bool IsAligned16 (const void *p)
0707     {
0708 
0709     return (((uintptr) p) & 1) == 0;
0710 
0711     }
0712 
0713 inline bool IsAligned32 (const void *p)
0714     {
0715 
0716     return (((uintptr) p) & 3) == 0;
0717 
0718     }
0719 
0720 inline bool IsAligned64 (const void *p)
0721     {
0722 
0723     return (((uintptr) p) & 7) == 0;
0724 
0725     }
0726 
0727 inline bool IsAligned128 (const void *p)
0728     {
0729 
0730     return (((uintptr) p) & 15) == 0;
0731 
0732     }
0733 
0734 /******************************************************************************/
0735 
0736 // Converts from RGB values (range 0.0 to 1.0) to HSV values (range 0.0 to
0737 // 6.0 for hue, and 0.0 to 1.0 for saturation and value).
0738 
0739 inline void DNG_RGBtoHSV (real32 r,
0740                           real32 g,
0741                           real32 b,
0742                           real32 &h,
0743                           real32 &s,
0744                           real32 &v)
0745     {
0746 
0747     v = Max_real32 (r, Max_real32 (g, b));
0748 
0749     real32 gap = v - Min_real32 (r, Min_real32 (g, b));
0750 
0751     if (gap > 0.0f)
0752         {
0753 
0754         if (r == v)
0755             {
0756 
0757             h = (g - b) / gap;
0758 
0759             if (h < 0.0f)
0760                 {
0761                 h += 6.0f;
0762                 }
0763 
0764             }
0765 
0766         else if (g == v)
0767             {
0768             h = 2.0f + (b - r) / gap;
0769             }
0770 
0771         else
0772             {
0773             h = 4.0f + (r - g) / gap;
0774             }
0775 
0776         s = gap / v;
0777 
0778         }
0779 
0780     else
0781         {
0782         h = 0.0f;
0783         s = 0.0f;
0784         }
0785 
0786     }
0787 
0788 /*****************************************************************************/
0789 
0790 // Converts from HSV values (range 0.0 to 6.0 for hue, and 0.0 to 1.0 for
0791 // saturation and value) to RGB values (range 0.0 to 1.0).
0792 
0793 inline void DNG_HSVtoRGB (real32 h,
0794                           real32 s,
0795                           real32 v,
0796                           real32 &r,
0797                           real32 &g,
0798                           real32 &b)
0799     {
0800 
0801     if (s > 0.0f)
0802         {
0803 
0804         if (h < 0.0f)
0805             h += 6.0f;
0806 
0807         if (h >= 6.0f)
0808             h -= 6.0f;
0809 
0810         int32  i = (int32) h;
0811         real32 f = h - (real32) i;
0812 
0813         real32 p = v * (1.0f - s);
0814 
0815         #define q   (v * (1.0f - s * f))
0816         #define t   (v * (1.0f - s * (1.0f - f)))
0817 
0818         switch (i)
0819             {
0820             case 0: r = v; g = t; b = p; break;
0821             case 1: r = q; g = v; b = p; break;
0822             case 2: r = p; g = v; b = t; break;
0823             case 3: r = p; g = q; b = v; break;
0824             case 4: r = t; g = p; b = v; break;
0825             case 5: r = v; g = p; b = q; break;
0826             }
0827 
0828         #undef q
0829         #undef t
0830 
0831         }
0832 
0833     else
0834         {
0835         r = v;
0836         g = v;
0837         b = v;
0838         }
0839 
0840     }
0841 
0842 /******************************************************************************/
0843 
0844 // High resolution timer, for code profiling.
0845 
0846 real64 TickTimeInSeconds ();
0847 
0848 // Lower resolution timer, but more stable.
0849 
0850 real64 TickCountInSeconds ();
0851 
0852 /******************************************************************************/
0853 
0854 void DNGIncrementTimerLevel ();
0855 
0856 int32 DNGDecrementTimerLevel ();
0857 
0858 /******************************************************************************/
0859 
0860 class dng_timer: private dng_uncopyable
0861     {
0862 
0863     public:
0864 
0865         dng_timer (const char *message);
0866 
0867         ~dng_timer ();
0868 
0869     private:
0870 
0871         const char *fMessage;
0872 
0873         real64 fStartTime;
0874 
0875     };
0876 
0877 /*****************************************************************************/
0878 
0879 // Returns the maximum squared Euclidean distance from the specified point to the
0880 // specified rectangle rect.
0881 
0882 real64 MaxSquaredDistancePointToRect (const dng_point_real64 &point,
0883                                       const dng_rect_real64 &rect);
0884 
0885 /*****************************************************************************/
0886 
0887 // Returns the maximum Euclidean distance from the specified point to the specified
0888 // rectangle rect.
0889 
0890 real64 MaxDistancePointToRect (const dng_point_real64 &point,
0891                                const dng_rect_real64 &rect);
0892 
0893 /*****************************************************************************/
0894 
0895 inline uint32 DNG_HalfToFloat (uint16 halfValue)
0896     {
0897 
0898     int32 sign     = (halfValue >> 15) & 0x00000001;
0899     int32 exponent = (halfValue >> 10) & 0x0000001f;
0900     int32 mantissa =  halfValue        & 0x000003ff;
0901 
0902     if (exponent == 0)
0903         {
0904 
0905         if (mantissa == 0)
0906             {
0907 
0908             // Plus or minus zero
0909 
0910             return (uint32) (sign << 31);
0911 
0912             }
0913 
0914         else
0915             {
0916 
0917             // Denormalized number -- renormalize it
0918 
0919             while (!(mantissa & 0x00000400))
0920                 {
0921                 mantissa <<= 1;
0922                 exponent -=  1;
0923                 }
0924 
0925             exponent += 1;
0926             mantissa &= ~0x00000400;
0927 
0928             }
0929 
0930         }
0931 
0932     else if (exponent == 31)
0933         {
0934 
0935         if (mantissa == 0)
0936             {
0937 
0938             // Positive or negative infinity, convert to maximum (16 bit) values.
0939 
0940             return (uint32) ((sign << 31) | ((0x1eL + 127 - 15) << 23) |  (0x3ffL << 13));
0941 
0942             }
0943 
0944         else
0945             {
0946 
0947             // Nan -- Just set to zero.
0948 
0949             return 0;
0950 
0951             }
0952 
0953         }
0954 
0955     // Normalized number
0956 
0957     exponent += (127 - 15);
0958     mantissa <<= 13;
0959 
0960     // Assemble sign, exponent and mantissa.
0961 
0962     return (uint32) ((sign << 31) | (exponent << 23) | mantissa);
0963 
0964     }
0965 
0966 /*****************************************************************************/
0967 
0968 inline uint16 DNG_FloatToHalf (uint32 i)
0969     {
0970 
0971     int32 sign     =  (i >> 16) & 0x00008000;
0972     int32 exponent = ((i >> 23) & 0x000000ff) - (127 - 15);
0973     int32 mantissa =   i        & 0x007fffff;
0974 
0975     if (exponent <= 0)
0976         {
0977 
0978         if (exponent < -10)
0979             {
0980 
0981             // Zero or underflow to zero.
0982 
0983             return (uint16)sign;
0984 
0985             }
0986 
0987         // E is between -10 and 0.  We convert f to a denormalized half.
0988 
0989         mantissa = (mantissa | 0x00800000) >> (1 - exponent);
0990 
0991         // Round to nearest, round "0.5" up.
0992         //
0993         // Rounding may cause the significand to overflow and make
0994         // our number normalized.  Because of the way a half's bits
0995         // are laid out, we don't have to treat this case separately;
0996         // the code below will handle it correctly.
0997 
0998         if (mantissa &  0x00001000)
0999             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 
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 
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 
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 
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")
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 
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 
1355         CFReleaseHelper (T ref)
1356             :   fRef (ref)
1357             {
1358             }
1359 
1360         ~CFReleaseHelper ()
1361             {
1362             if (fRef)
1363                 {
1364                 CFRelease (fRef);
1365                 }
1366             }
1367 
1368         T Get () const
1369             {
1370             return fRef;
1371             }
1372 
1373     };
1374 
1375 /*****************************************************************************/
1376 
1377 #endif  // qMacOS
1378 
1379 /*****************************************************************************/
1380 
1381 #endif
1382 
1383 /*****************************************************************************/