File indexing completed on 2024-05-12 15:59:36
0001 /* 0002 * SPDX-FileCopyrightText: 2005 Adrian Page <adrian@pagenet.plus.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef KO_INTEGER_MATHS_H 0008 #define KO_INTEGER_MATHS_H 0009 0010 #include <cstdint> 0011 0012 #ifndef UINT8_MAX 0013 #define UINT8_MAX 255u 0014 #endif 0015 0016 #ifndef UINT8_MIN 0017 #define UINT8_MIN 0u 0018 #endif 0019 0020 #ifndef UINT16_MAX 0021 #define UINT16_MAX 65535u 0022 #endif 0023 0024 #ifndef UINT16_MIN 0025 #define UINT16_MIN 0u 0026 #endif 0027 0028 #ifndef UINT32_MAX 0029 #define UINT32_MAX (4294967295u) 0030 #endif 0031 0032 #ifndef UINT32_MIN 0033 #define UINT32_MIN 0u 0034 #endif 0035 0036 #ifndef INT16_MAX 0037 #define INT16_MAX 32767 0038 #endif 0039 0040 #ifndef INT16_MIN 0041 #define INT16_MIN -32768 0042 #endif 0043 0044 typedef unsigned int uint; 0045 0046 template<typename _T_, typename _T2_, typename _T3_> 0047 inline _T_ CLAMP(_T_ x, _T2_ l, _T3_ u) 0048 { 0049 if (x < l) 0050 return _T_(l); 0051 else if (x > u) 0052 return _T_(u); 0053 return x; 0054 } 0055 0056 /// take a and scale it up by 256*b/255 0057 inline uint UINT8_SCALEBY(uint a, uint b) 0058 { 0059 uint c = a * b + 0x80u; 0060 return (c >> 8) + c; 0061 } 0062 0063 /// multiplication of two scale values 0064 /// A scale value is interpreted as 255 equaling 1.0 (such as seen in rgb8 triplets) 0065 /// thus "255*255=255" because 1.0*1.0=1.0 0066 inline uint UINT8_MULT(uint a, uint b) 0067 { 0068 uint c = a * b + 0x80u; 0069 return ((c >> 8) + c) >> 8; 0070 } 0071 0072 inline uint UINT8_DIVIDE(uint a, uint b) 0073 { 0074 uint c = (a * UINT8_MAX + (b / 2u)) / b; 0075 return c; 0076 } 0077 0078 /// Approximation of (a * b * c + 32512) / 65025.0 0079 inline uint UINT8_MULT3(uint a, uint b, uint c) 0080 { 0081 uint t = a * b * c + 0x7F5B; 0082 return ((t >> 7) + t) >> 16; 0083 } 0084 0085 /// Blending of two scale values as described by the alpha scale value 0086 /// A scale value is interpreted as 255 equaling 1.0 (such as seen in rgb8 triplets) 0087 /// Basically we do: a*alpha + b*(1-alpha) 0088 inline uint UINT8_BLEND(uint a, uint b, uint alpha) 0089 { 0090 // However the formula is refactored to (a-b)*alpha + b since that saves a multiplication 0091 // Signed arithmetic is needed since a-b might be negative 0092 int c = (int(a) - int(b)) * alpha + 0x80u; 0093 c = ((c >> 8) + c) >> 8; 0094 return c + b; 0095 } 0096 0097 inline uint UINT16_MULT(uint a, uint b) 0098 { 0099 uint c = a * b + 0x8000u; 0100 return ((c >> 16) + c) >> 16; 0101 } 0102 0103 inline int INT16_MULT(int a, int b) 0104 { 0105 return (a*b) / INT16_MAX; 0106 } 0107 0108 inline uint UINT16_DIVIDE(uint a, uint b) 0109 { 0110 uint c = (a * UINT16_MAX + (b / 2u)) / b; 0111 return c; 0112 } 0113 0114 inline uint UINT16_BLEND(uint a, uint b, uint alpha) 0115 { 0116 // Basically we do a*alpha + b*(1-alpha) 0117 // However refactored to (a-b)*alpha + b since that saves a multiplication 0118 // Signed arithmetic is needed since a-b might be negative 0119 int c = ((int(a) - int(b)) * int(alpha)) >> 16; 0120 return uint(c + b); 0121 } 0122 0123 inline uint UINT8_TO_UINT16(uint c) 0124 { 0125 return c | (c << 8); 0126 } 0127 0128 inline uint UINT16_TO_UINT8(uint c) 0129 { 0130 //return round(c / 257.0); 0131 //For all UINT16 this calculation is the same and a lot faster (off by c/65656 which for every c is 0) 0132 c = c - (c >> 8) + 128; 0133 return c >> 8; 0134 } 0135 0136 inline int INT16_BLEND(int a, int b, uint alpha) 0137 { 0138 // Basically we do a*alpha + b*(1-alpha) 0139 // However refactored to (a-b)*alpha + b since that saves a multiplication 0140 int c = ((int(a) - int(b)) * int(alpha)) >> 16; 0141 return c + b; 0142 } 0143 0144 #endif 0145