1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
16 // Copyright (C) 2014, Itseez Inc., all rights reserved.
17 // Third party copyrights are property of their respective owners.
18 //
19 // Redistribution and use in source and binary forms, with or without modification,
20 // are permitted provided that the following conditions are met:
21 //
22 //   * Redistribution's of source code must retain the above copyright notice,
23 //     this list of conditions and the following disclaimer.
24 //
25 //   * Redistribution's in binary form must reproduce the above copyright notice,
26 //     this list of conditions and the following disclaimer in the documentation
27 //     and/or other materials provided with the distribution.
28 //
29 //   * The name of the copyright holders may not be used to endorse or promote products
30 //     derived from this software without specific prior written permission.
31 //
32 // This software is provided by the copyright holders and contributors "as is" and
33 // any express or implied warranties, including, but not limited to, the implied
34 // warranties of merchantability and fitness for a particular purpose are disclaimed.
35 // In no event shall the Intel Corporation or contributors be liable for any direct,
36 // indirect, incidental, special, exemplary, or consequential damages
37 // (including, but not limited to, procurement of substitute goods or services;
38 // loss of use, data, or profits; or business interruption) however caused
39 // and on any theory of liability, whether in contract, strict liability,
40 // or tort (including negligence or otherwise) arising in any way out of
41 // the use of this software, even if advised of the possibility of such damage.
42 //
43 //M*/
44 
45 #ifndef OPENCV_CORE_SATURATE_HPP
46 #define OPENCV_CORE_SATURATE_HPP
47 
48 #include "opencv2/core/cvdef.h"
49 #include "opencv2/core/fast_math.hpp"
50 
51 namespace cv
52 {
53 
54 //! @addtogroup core_utils
55 //! @{
56 
57 /////////////// saturate_cast (used in image & signal processing) ///////////////////
58 
59 /** @brief Template function for accurate conversion from one primitive type to another.
60 
61  The function saturate_cast resembles the standard C++ cast operations, such as static_cast\<T\>()
62  and others. It perform an efficient and accurate conversion from one primitive type to another
63  (see the introduction chapter). saturate in the name means that when the input value v is out of the
64  range of the target type, the result is not formed just by taking low bits of the input, but instead
65  the value is clipped. For example:
66  @code
67  uchar a = saturate_cast<uchar>(-100); // a = 0 (UCHAR_MIN)
68  short b = saturate_cast<short>(33333.33333); // b = 32767 (SHRT_MAX)
69  @endcode
70  Such clipping is done when the target type is unsigned char , signed char , unsigned short or
71  signed short . For 32-bit integers, no clipping is done.
72 
73  When the parameter is a floating-point value and the target type is an integer (8-, 16- or 32-bit),
74  the floating-point value is first rounded to the nearest integer and then clipped if needed (when
75  the target type is 8- or 16-bit).
76 
77  @param v Function parameter.
78  @sa add, subtract, multiply, divide, Mat::convertTo
79  */
saturate_cast(uchar v)80 template<typename _Tp> static inline _Tp saturate_cast(uchar v)    { return _Tp(v); }
81 /** @overload */
saturate_cast(schar v)82 template<typename _Tp> static inline _Tp saturate_cast(schar v)    { return _Tp(v); }
83 /** @overload */
saturate_cast(ushort v)84 template<typename _Tp> static inline _Tp saturate_cast(ushort v)   { return _Tp(v); }
85 /** @overload */
saturate_cast(short v)86 template<typename _Tp> static inline _Tp saturate_cast(short v)    { return _Tp(v); }
87 /** @overload */
saturate_cast(unsigned v)88 template<typename _Tp> static inline _Tp saturate_cast(unsigned v) { return _Tp(v); }
89 /** @overload */
saturate_cast(int v)90 template<typename _Tp> static inline _Tp saturate_cast(int v)      { return _Tp(v); }
91 /** @overload */
saturate_cast(float v)92 template<typename _Tp> static inline _Tp saturate_cast(float v)    { return _Tp(v); }
93 /** @overload */
saturate_cast(double v)94 template<typename _Tp> static inline _Tp saturate_cast(double v)   { return _Tp(v); }
95 /** @overload */
saturate_cast(int64 v)96 template<typename _Tp> static inline _Tp saturate_cast(int64 v)    { return _Tp(v); }
97 /** @overload */
saturate_cast(uint64 v)98 template<typename _Tp> static inline _Tp saturate_cast(uint64 v)   { return _Tp(v); }
99 
saturate_cast(schar v)100 template<> inline uchar saturate_cast<uchar>(schar v)        { return (uchar)std::max((int)v, 0); }
saturate_cast(ushort v)101 template<> inline uchar saturate_cast<uchar>(ushort v)       { return (uchar)std::min((unsigned)v, (unsigned)UCHAR_MAX); }
saturate_cast(int v)102 template<> inline uchar saturate_cast<uchar>(int v)          { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }
saturate_cast(short v)103 template<> inline uchar saturate_cast<uchar>(short v)        { return saturate_cast<uchar>((int)v); }
saturate_cast(unsigned v)104 template<> inline uchar saturate_cast<uchar>(unsigned v)     { return (uchar)std::min(v, (unsigned)UCHAR_MAX); }
saturate_cast(float v)105 template<> inline uchar saturate_cast<uchar>(float v)        { int iv = cvRound(v); return saturate_cast<uchar>(iv); }
saturate_cast(double v)106 template<> inline uchar saturate_cast<uchar>(double v)       { int iv = cvRound(v); return saturate_cast<uchar>(iv); }
saturate_cast(int64 v)107 template<> inline uchar saturate_cast<uchar>(int64 v)        { return (uchar)((uint64)v <= (uint64)UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }
saturate_cast(uint64 v)108 template<> inline uchar saturate_cast<uchar>(uint64 v)       { return (uchar)std::min(v, (uint64)UCHAR_MAX); }
109 
saturate_cast(uchar v)110 template<> inline schar saturate_cast<schar>(uchar v)        { return (schar)std::min((int)v, SCHAR_MAX); }
saturate_cast(ushort v)111 template<> inline schar saturate_cast<schar>(ushort v)       { return (schar)std::min((unsigned)v, (unsigned)SCHAR_MAX); }
saturate_cast(int v)112 template<> inline schar saturate_cast<schar>(int v)          { return (schar)((unsigned)(v-SCHAR_MIN) <= (unsigned)UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN); }
saturate_cast(short v)113 template<> inline schar saturate_cast<schar>(short v)        { return saturate_cast<schar>((int)v); }
saturate_cast(unsigned v)114 template<> inline schar saturate_cast<schar>(unsigned v)     { return (schar)std::min(v, (unsigned)SCHAR_MAX); }
saturate_cast(float v)115 template<> inline schar saturate_cast<schar>(float v)        { int iv = cvRound(v); return saturate_cast<schar>(iv); }
saturate_cast(double v)116 template<> inline schar saturate_cast<schar>(double v)       { int iv = cvRound(v); return saturate_cast<schar>(iv); }
saturate_cast(int64 v)117 template<> inline schar saturate_cast<schar>(int64 v)        { return (schar)((uint64)((int64)v-SCHAR_MIN) <= (uint64)UCHAR_MAX ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN); }
saturate_cast(uint64 v)118 template<> inline schar saturate_cast<schar>(uint64 v)       { return (schar)std::min(v, (uint64)SCHAR_MAX); }
119 
saturate_cast(schar v)120 template<> inline ushort saturate_cast<ushort>(schar v)      { return (ushort)std::max((int)v, 0); }
saturate_cast(short v)121 template<> inline ushort saturate_cast<ushort>(short v)      { return (ushort)std::max((int)v, 0); }
saturate_cast(int v)122 template<> inline ushort saturate_cast<ushort>(int v)        { return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); }
saturate_cast(unsigned v)123 template<> inline ushort saturate_cast<ushort>(unsigned v)   { return (ushort)std::min(v, (unsigned)USHRT_MAX); }
saturate_cast(float v)124 template<> inline ushort saturate_cast<ushort>(float v)      { int iv = cvRound(v); return saturate_cast<ushort>(iv); }
saturate_cast(double v)125 template<> inline ushort saturate_cast<ushort>(double v)     { int iv = cvRound(v); return saturate_cast<ushort>(iv); }
saturate_cast(int64 v)126 template<> inline ushort saturate_cast<ushort>(int64 v)      { return (ushort)((uint64)v <= (uint64)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); }
saturate_cast(uint64 v)127 template<> inline ushort saturate_cast<ushort>(uint64 v)     { return (ushort)std::min(v, (uint64)USHRT_MAX); }
128 
saturate_cast(ushort v)129 template<> inline short saturate_cast<short>(ushort v)       { return (short)std::min((int)v, SHRT_MAX); }
saturate_cast(int v)130 template<> inline short saturate_cast<short>(int v)          { return (short)((unsigned)(v - SHRT_MIN) <= (unsigned)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); }
saturate_cast(unsigned v)131 template<> inline short saturate_cast<short>(unsigned v)     { return (short)std::min(v, (unsigned)SHRT_MAX); }
saturate_cast(float v)132 template<> inline short saturate_cast<short>(float v)        { int iv = cvRound(v); return saturate_cast<short>(iv); }
saturate_cast(double v)133 template<> inline short saturate_cast<short>(double v)       { int iv = cvRound(v); return saturate_cast<short>(iv); }
saturate_cast(int64 v)134 template<> inline short saturate_cast<short>(int64 v)        { return (short)((uint64)((int64)v - SHRT_MIN) <= (uint64)USHRT_MAX ? v : v > 0 ? SHRT_MAX : SHRT_MIN); }
saturate_cast(uint64 v)135 template<> inline short saturate_cast<short>(uint64 v)       { return (short)std::min(v, (uint64)SHRT_MAX); }
136 
saturate_cast(unsigned v)137 template<> inline int saturate_cast<int>(unsigned v)         { return (int)std::min(v, (unsigned)INT_MAX); }
saturate_cast(int64 v)138 template<> inline int saturate_cast<int>(int64 v)            { return (int)((uint64)(v - INT_MIN) <= (uint64)UINT_MAX ? v : v > 0 ? INT_MAX : INT_MIN); }
saturate_cast(uint64 v)139 template<> inline int saturate_cast<int>(uint64 v)           { return (int)std::min(v, (uint64)INT_MAX); }
saturate_cast(float v)140 template<> inline int saturate_cast<int>(float v)            { return cvRound(v); }
saturate_cast(double v)141 template<> inline int saturate_cast<int>(double v)           { return cvRound(v); }
142 
saturate_cast(schar v)143 template<> inline unsigned saturate_cast<unsigned>(schar v)  { return (unsigned)std::max(v, (schar)0); }
saturate_cast(short v)144 template<> inline unsigned saturate_cast<unsigned>(short v)  { return (unsigned)std::max(v, (short)0); }
saturate_cast(int v)145 template<> inline unsigned saturate_cast<unsigned>(int v)    { return (unsigned)std::max(v, (int)0); }
saturate_cast(int64 v)146 template<> inline unsigned saturate_cast<unsigned>(int64 v)  { return (unsigned)((uint64)v <= (uint64)UINT_MAX ? v : v > 0 ? UINT_MAX : 0); }
saturate_cast(uint64 v)147 template<> inline unsigned saturate_cast<unsigned>(uint64 v) { return (unsigned)std::min(v, (uint64)UINT_MAX); }
148 // we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc.
saturate_cast(float v)149 template<> inline unsigned saturate_cast<unsigned>(float v)  { return static_cast<unsigned>(cvRound(v)); }
saturate_cast(double v)150 template<> inline unsigned saturate_cast<unsigned>(double v) { return static_cast<unsigned>(cvRound(v)); }
151 
saturate_cast(schar v)152 template<> inline uint64 saturate_cast<uint64>(schar v)      { return (uint64)std::max(v, (schar)0); }
saturate_cast(short v)153 template<> inline uint64 saturate_cast<uint64>(short v)      { return (uint64)std::max(v, (short)0); }
saturate_cast(int v)154 template<> inline uint64 saturate_cast<uint64>(int v)        { return (uint64)std::max(v, (int)0); }
saturate_cast(int64 v)155 template<> inline uint64 saturate_cast<uint64>(int64 v)      { return (uint64)std::max(v, (int64)0); }
156 
saturate_cast(uint64 v)157 template<> inline int64 saturate_cast<int64>(uint64 v)       { return (int64)std::min(v, (uint64)LLONG_MAX); }
158 
159 /** @overload */
saturate_cast(float16_t v)160 template<typename _Tp> static inline _Tp saturate_cast(float16_t v) { return saturate_cast<_Tp>((float)v); }
161 
162 // in theory, we could use a LUT for 8u/8s->16f conversion,
163 // but with hardware support for FP32->FP16 conversion the current approach is preferable
saturate_cast(uchar v)164 template<> inline float16_t saturate_cast<float16_t>(uchar v)   { return float16_t((float)v); }
saturate_cast(schar v)165 template<> inline float16_t saturate_cast<float16_t>(schar v)   { return float16_t((float)v); }
saturate_cast(ushort v)166 template<> inline float16_t saturate_cast<float16_t>(ushort v)  { return float16_t((float)v); }
saturate_cast(short v)167 template<> inline float16_t saturate_cast<float16_t>(short v)   { return float16_t((float)v); }
saturate_cast(unsigned v)168 template<> inline float16_t saturate_cast<float16_t>(unsigned v){ return float16_t((float)v); }
saturate_cast(int v)169 template<> inline float16_t saturate_cast<float16_t>(int v)     { return float16_t((float)v); }
saturate_cast(uint64 v)170 template<> inline float16_t saturate_cast<float16_t>(uint64 v)  { return float16_t((float)v); }
saturate_cast(int64 v)171 template<> inline float16_t saturate_cast<float16_t>(int64 v)   { return float16_t((float)v); }
saturate_cast(float v)172 template<> inline float16_t saturate_cast<float16_t>(float v)   { return float16_t(v); }
saturate_cast(double v)173 template<> inline float16_t saturate_cast<float16_t>(double v)  { return float16_t((float)v); }
174 
175 //! @}
176 
177 } // cv
178 
179 #endif // OPENCV_CORE_SATURATE_HPP
180