[cimg] 01/01: New upstream version 1.7.9+dfsg
Andreas Tille
tille at debian.org
Mon Dec 5 20:30:27 UTC 2016
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to annotated tag upstream/1.7.9+dfsg
in repository cimg.
commit 7968fe362f4e7d72d6bb3c3534db274bd4981189
Author: Andreas Tille <tille at debian.org>
Date: Mon Dec 5 19:40:19 2016 +0100
New upstream version 1.7.9+dfsg
---
CImg.h | 1121 ++++++++++++++++++++++++++++--------------
examples/CImg_demo.cpp | 2 +-
examples/edge_explorer2d.cpp | 8 +-
html/header.html | 4 +-
html/header_reference.html | 4 +-
html/img/CImgLogo2.jpg | Bin 70868 -> 73652 bytes
html/img/postcard65.jpg | Bin 0 -> 18325 bytes
html/index.shtml | 5 +-
8 files changed, 763 insertions(+), 381 deletions(-)
diff --git a/CImg.h b/CImg.h
index 8f91cb9..aabbb23 100644
--- a/CImg.h
+++ b/CImg.h
@@ -54,7 +54,7 @@
// Set version number of the library.
#ifndef cimg_version
-#define cimg_version 178
+#define cimg_version 179
/*-----------------------------------------------------------
#
@@ -197,7 +197,7 @@
#endif
// Convenient macro to define pragma
-#ifdef _MSC_VER_
+#ifdef _MSC_VER
#define cimg_pragma(x) __pragma(x)
#else
#define cimg_pragma(x) _Pragma(#x)
@@ -211,16 +211,21 @@
#define cimg_ulong UINT_PTR
#define cimg_long INT_PTR
#else
-#if UINTPTR_MAX==0xffffffff
+#if UINTPTR_MAX==0xffffffff || defined(__arm__) || defined(_M_ARM)
#define cimg_uint64 unsigned long long
#define cimg_int64 long long
#else
#define cimg_uint64 unsigned long
#define cimg_int64 long
#endif
+#if defined(__arm__) || defined(_M_ARM)
+#define cimg_ulong unsigned long long
+#define cimg_long long long
+#else
#define cimg_ulong unsigned long
#define cimg_long long
#endif
+#endif
// Configure filename separator.
//
@@ -2549,6 +2554,7 @@ namespace cimg_library_suffixed {
static T inf() { return max(); }
static T cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(T)val; }
static const char* format() { return "%s"; }
+ static const char* format_s() { return "%s"; }
static const char* format(const T& val) { static const char *const s = "unknown"; cimg::unused(val); return s; }
};
@@ -2563,6 +2569,7 @@ namespace cimg_library_suffixed {
static bool is_inf() { return false; }
static bool cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(bool)val; }
static const char* format() { return "%s"; }
+ static const char* format_s() { return "%s"; }
static const char* format(const bool val) { static const char* s[] = { "false", "true" }; return s[val?1:0]; }
};
@@ -2577,6 +2584,7 @@ namespace cimg_library_suffixed {
static unsigned char cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; }
static const char* format() { return "%u"; }
+ static const char* format_s() { return "%u"; }
static unsigned int format(const unsigned char val) { return (unsigned int)val; }
};
@@ -2592,6 +2600,7 @@ namespace cimg_library_suffixed {
static char cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned char)val; }
static const char* format() { return "%u"; }
+ static const char* format_s() { return "%u"; }
static unsigned int format(const char val) { return (unsigned int)val; }
};
#else
@@ -2605,6 +2614,7 @@ namespace cimg_library_suffixed {
static char inf() { return max(); }
static char cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(char)val; }
static const char* format() { return "%d"; }
+ static const char* format_s() { return "%d"; }
static int format(const char val) { return (int)val; }
};
#endif
@@ -2620,6 +2630,7 @@ namespace cimg_library_suffixed {
static signed char cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(signed char)val; }
static const char* format() { return "%d"; }
+ static const char* format_s() { return "%d"; }
static int format(const signed char val) { return (int)val; }
};
@@ -2634,6 +2645,7 @@ namespace cimg_library_suffixed {
static unsigned short cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned short)val; }
static const char* format() { return "%u"; }
+ static const char* format_s() { return "%u"; }
static unsigned int format(const unsigned short val) { return (unsigned int)val; }
};
@@ -2647,6 +2659,7 @@ namespace cimg_library_suffixed {
static short inf() { return max(); }
static short cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(short)val; }
static const char* format() { return "%d"; }
+ static const char* format_s() { return "%d"; }
static int format(const short val) { return (int)val; }
};
@@ -2661,6 +2674,7 @@ namespace cimg_library_suffixed {
static unsigned int cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(unsigned int)val; }
static const char* format() { return "%u"; }
+ static const char* format_s() { return "%u"; }
static unsigned int format(const unsigned int val) { return val; }
};
@@ -2674,6 +2688,7 @@ namespace cimg_library_suffixed {
static int inf() { return max(); }
static int cut(const double val) { return val<(double)min()?min():val>(double)max()?max():(int)val; }
static const char* format() { return "%d"; }
+ static const char* format_s() { return "%d"; }
static int format(const int val) { return val; }
};
@@ -2688,6 +2703,7 @@ namespace cimg_library_suffixed {
static cimg_uint64 cut(const double val) {
return val<(double)min()?min():val>(double)max()?max():(cimg_uint64)val; }
static const char* format() { return "%lu"; }
+ static const char* format_s() { return "%lu"; }
static unsigned long format(const cimg_uint64 val) { return (unsigned long)val; }
};
@@ -2703,6 +2719,7 @@ namespace cimg_library_suffixed {
return val<(double)min()?min():val>(double)max()?max():(cimg_int64)val;
}
static const char* format() { return "%ld"; }
+ static const char* format_s() { return "%ld"; }
static long format(const long val) { return (long)val; }
};
@@ -2740,7 +2757,8 @@ namespace cimg_library_suffixed {
#endif
}
static double cut(const double val) { return val; }
- static const char* format() { return "%.16g"; }
+ static const char* format() { return "%.17g"; }
+ static const char* format_s() { return "%g"; }
static double format(const double val) { return val; }
};
@@ -2767,7 +2785,8 @@ namespace cimg_library_suffixed {
static float nan() { return (float)cimg::type<double>::nan(); }
static float cut(const double val) { return (float)val; }
static float cut(const float val) { return (float)val; }
- static const char* format() { return "%.16g"; }
+ static const char* format() { return "%.9g"; }
+ static const char* format_s() { return "%g"; }
static double format(const float val) { return (double)val; }
};
@@ -2793,7 +2812,8 @@ namespace cimg_library_suffixed {
static long double inf() { return max()*max(); }
static long double nan() { const long double val_nan = -std::sqrt(-1.0L); return val_nan; }
static long double cut(const long double val) { return val; }
- static const char* format() { return "%.16g"; }
+ static const char* format() { return "%.17g"; }
+ static const char* format_s() { return "%g"; }
static double format(const long double val) { return (double)val; }
};
@@ -2820,7 +2840,8 @@ namespace cimg_library_suffixed {
static half inf() { return max()*max(); }
static half nan() { const half val_nan = (half)-std::sqrt(-1.0); return val_nan; }
static half cut(const double val) { return (half)val; }
- static const char* format() { return "%.16g"; }
+ static const char* format() { return "%.9g"; }
+ static const char* format_s() { return "%g"; }
static double format(const half val) { return (double)val; }
};
#endif
@@ -4543,7 +4564,7 @@ namespace cimg_library_suffixed {
// Use the system RNG.
inline void srand() {
const unsigned int t = (unsigned int)cimg::time();
-#if cimg_OS==1
+#if cimg_OS==1 || defined(__BORLANDC__)
std::srand(t + (unsigned int)getpid());
#elif cimg_OS==2
std::srand(t + (unsigned int)_getpid());
@@ -5249,8 +5270,8 @@ namespace cimg_library_suffixed {
inline double _fibonacci(int exp) {
double
- base = 1.6180339887498948482045868343656, // (1 + sqrt(5))/2;
- result = 0.44721359549995793928183473374626; // 1 / sqrt(5)
+ base = (1 + std::sqrt(5.0))/2,
+ result = 1/std::sqrt(5.0);
while (exp) {
if (exp&1) result*=base;
exp>>=1;
@@ -5508,7 +5529,8 @@ namespace cimg_library_suffixed {
for (unsigned int k = 0; k<8; ++k) {
const int v = (int)cimg::rand(65535)%3;
randomid[k] = (char)(v==0?('0' + ((int)cimg::rand(65535)%10)):
- (v==1?('a' + ((int)cimg::rand(65535)%26)):('A' + ((int)cimg::rand(65535)%26))));
+ (v==1?('a' + ((int)cimg::rand(65535)%26)):
+ ('A' + ((int)cimg::rand(65535)%26))));
}
cimg::mutex(6,0);
return randomid;
@@ -5547,7 +5569,11 @@ namespace cimg_library_suffixed {
res = (*mode=='r')?cimg::_stdin():cimg::_stdout();
#if cimg_OS==2
if (*mode && mode[1]=='b') { // Force stdin/stdout to be in binary mode.
+#ifdef __BORLANDC__
+ if (setmode(_fileno(res),0x8000)==-1) res = 0;
+#else
if (_setmode(_fileno(res),0x8000)==-1) res = 0;
+#endif
}
#endif
} else res = std_fopen(path,mode);
@@ -6565,6 +6591,15 @@ namespace cimg_library_suffixed {
assign(disp);
}
+ //! Take a screenshot.
+ /**
+ \param[out] img Output screenshot. Can be empty on input
+ **/
+ template<typename T>
+ static void screenshot(CImg<T>& img) {
+ return screenshot(0,0,cimg::type<int>::max(),cimg::type<int>::max(),img);
+ }
+
#if cimg_display==0
static void _no_display_exception() {
@@ -7801,6 +7836,21 @@ namespace cimg_library_suffixed {
return assign();
}
+
+ //! Take a snapshot of the current screen content.
+ /**
+ \param x0 X-coordinate of the upper left corner.
+ \param y0 Y-coordinate of the upper left corner.
+ \param x1 X-coordinate of the lower right corner.
+ \param y1 Y-coordinate of the lower right corner.
+ \param[out] img Output screenshot. Can be empty on input
+ **/
+ template<typename T>
+ static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg<T>& img) {
+ cimg::unused(x0,y0,x1,y1,&img);
+ _no_display_exception();
+ }
+
//! Take a snapshot of the associated window content.
/**
\param[out] img Output snapshot. Can be empty on input.
@@ -9016,6 +9066,56 @@ namespace cimg_library_suffixed {
}
template<typename T>
+ static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg<T>& img) {
+ img.assign();
+ Display *dpy = cimg::X11_attr().display;
+ cimg_lock_display();
+ if (!dpy) {
+ dpy = XOpenDisplay(0);
+ if (!dpy)
+ throw CImgDisplayException("CImgDisplay::screenshot(): Failed to open X11 display.");
+ }
+ Window root = DefaultRootWindow(dpy);
+ XWindowAttributes gwa;
+ XGetWindowAttributes(dpy,root,&gwa);
+ const int width = gwa.width, height = gwa.height;
+ int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1;
+ if (_x0>_x1) cimg::swap(_x0,_x1);
+ if (_y0>_y1) cimg::swap(_y0,_y1);
+
+ XImage *image = 0;
+ if (_x1>=0 && _x0<width && _y1>=0 && _y0<height) {
+ _x0 = cimg::max(_x0,0);
+ _y0 = cimg::max(_y0,0);
+ _x1 = cimg::min(_x1,width - 1);
+ _y1 = cimg::min(_y1,height - 1);
+ image = XGetImage(dpy,root,_x0,_y0,_x1 - _x0 + 1,_y1 - _y0 + 1,AllPlanes,ZPixmap);
+
+ if (image) {
+ const unsigned long
+ red_mask = image->red_mask,
+ green_mask = image->green_mask,
+ blue_mask = image->blue_mask;
+ img.assign(image->width,image->height,1,3);
+ T *pR = img.data(0,0,0,0), *pG = img.data(0,0,0,1), *pB = img.data(0,0,0,2);
+ cimg_forXY(img,x,y) {
+ const unsigned long pixel = XGetPixel(image,x,y);
+ *(pR++) = (T)((pixel & red_mask)>>16);
+ *(pG++) = (T)((pixel & green_mask)>>8);
+ *(pB++) = (T)(pixel & blue_mask);
+ }
+ XDestroyImage(image);
+ }
+ }
+ if (!cimg::X11_attr().display) XCloseDisplay(dpy);
+ cimg_unlock_display();
+ if (img.is_empty())
+ throw CImgDisplayException("CImgDisplay::screenshot(): Failed to take screenshot "
+ "with coordinates (%d,%d)-(%d,%d).",
+ x0,y0,x1,y1);
+ }
+
+ template<typename T>
const CImgDisplay& snapshot(CImg<T>& img) const {
if (is_empty()) { img.assign(); return *this; }
const unsigned char *ptrs = (unsigned char*)_data;
@@ -9189,7 +9289,7 @@ namespace cimg_library_suffixed {
disp->_mouse_x = disp->_mouse_y = -1;
disp->_is_mouse_tracked = false;
cimg::mutex(15);
- while (ShowCursor(TRUE)<0);
+ while (ShowCursor(TRUE)<0) {}
cimg::mutex(15,0);
} break;
case WM_LBUTTONDOWN :
@@ -9672,6 +9772,65 @@ namespace cimg_library_suffixed {
}
template<typename T>
+ static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg<T>& img) {
+ img.assign();
+ HDC hScreen = GetDC(GetDesktopWindow());
+ if (hScreen) {
+ const int
+ width = GetDeviceCaps(hScreen,HORZRES),
+ height = GetDeviceCaps(hScreen,VERTRES);
+ int _x0 = x0, _y0 = y0, _x1 = x1, _y1 = y1;
+ if (_x0>_x1) cimg::swap(_x0,_x1);
+ if (_y0>_y1) cimg::swap(_y0,_y1);
+ if (_x1>=0 && _x0<width && _y1>=0 && _y0<height) {
+ _x0 = cimg::max(_x0,0);
+ _y0 = cimg::max(_y0,0);
+ _x1 = cimg::min(_x1,width - 1);
+ _y1 = cimg::min(_y1,height - 1);
+ const int bw = _x1 - _x0 + 1, bh = _y1 - _y0 + 1;
+ HDC hdcMem = CreateCompatibleDC(hScreen);
+ if (hdcMem) {
+ HBITMAP hBitmap = CreateCompatibleBitmap(hScreen,bw,bh);
+ if (hBitmap) {
+ HGDIOBJ hOld = SelectObject(hdcMem,hBitmap);
+ if (hOld && BitBlt(hdcMem,0,0,bw,bh,hScreen,_x0,_y0,SRCCOPY) && SelectObject(hdcMem,hOld)) {
+ BITMAPINFOHEADER bmi = {0};
+ bmi.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.biPlanes = 1;
+ bmi.biBitCount = 32;
+ bmi.biWidth = bw;
+ bmi.biHeight = -bh;
+ bmi.biCompression = BI_RGB;
+ bmi.biSizeImage = 0;
+
+ unsigned char *buf = new unsigned char[4*bw*bh];
+ if (GetDIBits(hdcMem,hBitmap,0,bh,buf,(BITMAPINFO*)&bmi,DIB_RGB_COLORS)) {
+ img.assign(bw,bh,1,3);
+ const unsigned char *ptrs = buf;
+ T *pR = img.data(0,0,0,0), *pG = img.data(0,0,0,1), *pB = img.data(0,0,0,2);
+ cimg_forXY(img,x,y) {
+ *(pR++) = (T)ptrs[2];
+ *(pG++) = (T)ptrs[1];
+ *(pB++) = (T)ptrs[0];
+ ptrs+=4;
+ }
+ }
+ delete[] buf;
+ }
+ DeleteObject(hBitmap);
+ }
+ DeleteDC(hdcMem);
+ }
+ }
+ ReleaseDC(GetDesktopWindow(),hScreen);
+ }
+ if (img.is_empty())
+ throw CImgDisplayException("CImgDisplay::screenshot(): Failed to take screenshot "
+ "with coordinates (%d,%d)-(%d,%d).",
+ x0,y0,x1,y1);
+ }
+
+ template<typename T>
const CImgDisplay& snapshot(CImg<T>& img) const {
if (is_empty()) { img.assign(); return *this; }
const unsigned int *ptrs = _data;
@@ -13517,7 +13676,6 @@ namespace cimg_library_suffixed {
const T *ptrs = _data;
unsigned int string_size = 0;
const char *const _format = format?format:cimg::type<T>::format();
-
for (ulongT off = 0, siz = size(); off<siz && string_size<=max_size; ++off) {
const unsigned int printed_size = 1U + cimg_snprintf(s_item,s_item._width,_format,
cimg::type<T>::format(*(ptrs++)));
@@ -14382,16 +14540,16 @@ namespace cimg_library_suffixed {
CImg<T> &imgout;
CImgList<T>& listout;
- CImg<doubleT> _img_stats, &img_stats;
+ CImg<doubleT> _img_stats, &img_stats, constcache_vals;
CImgList<doubleT> _list_stats, &list_stats, _list_median, &list_median;
- CImg<uintT> mem_img_stats;
+ CImg<uintT> mem_img_stats, constcache_inds;
CImg<uintT> level, variable_pos, reserved_label;
CImgList<charT> variable_def, macro_def, macro_body;
CImgList<boolT> macro_body_is_string;
char *user_macro;
- unsigned int mempos, mem_img_median, debug_indent, init_size, result_dim, break_type;
+ unsigned int mempos, mem_img_median, debug_indent, init_size, result_dim, break_type, constcache_size;
bool is_parallelizable, need_input_copy;
double *result;
const char *const calling_function, *s_op, *ss_op;
@@ -14435,7 +14593,7 @@ namespace cimg_library_suffixed {
imgin(img_input),listin(list_input?*list_input:CImgList<T>::const_empty()),
imgout(img_output?*img_output:CImg<T>::empty()),listout(list_output?*list_output:CImgList<T>::empty()),
img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),user_macro(0),
- mem_img_median(~0U),debug_indent(0),init_size(0),result_dim(0),break_type(0),
+ mem_img_median(~0U),debug_indent(0),init_size(0),result_dim(0),break_type(0),constcache_size(0),
is_parallelizable(true),need_input_copy(false),calling_function(funcname?funcname:"cimg_math_parser") {
if (!expression || !*expression)
throw CImgArgumentException("[_cimg_math_parser] "
@@ -14511,11 +14669,13 @@ namespace cimg_library_suffixed {
else mem[ind_result] = cimg::type<double>::nan();
}
- // Free resources used for parsing and prepare for evaluation.
- if (_cimg_mp_is_vector(ind_result)) result_dim = _cimg_mp_vector_size(ind_result);
+ // Free resources used for compiling expression and prepare evaluation.
+ result_dim = _cimg_mp_vector_size(ind_result);
mem.resize(mempos,1,1,1,-1);
result = mem._data + ind_result;
memtype.assign();
+ constcache_vals.assign();
+ constcache_inds.assign();
level.assign();
variable_pos.assign();
reserved_label.assign();
@@ -14524,7 +14684,7 @@ namespace cimg_library_suffixed {
opcode.assign();
opcode._is_shared = true;
- // Execute init() function if any specified.
+ // Execute init() bloc if any specified.
p_code_begin = code._data + init_size;
if (init_size) {
mem[_cimg_mp_slot_x] = mem[_cimg_mp_slot_y] = mem[_cimg_mp_slot_z] = mem[_cimg_mp_slot_c] = 0;
@@ -14542,7 +14702,8 @@ namespace cimg_library_suffixed {
imgin(CImg<T>::const_empty()),listin(CImgList<T>::const_empty()),
imgout(CImg<T>::empty()),listout(CImgList<T>::empty()),
img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),debug_indent(0),
- result_dim(0),break_type(0),is_parallelizable(true),need_input_copy(false),calling_function(0) {
+ result_dim(0),break_type(0),constcache_size(0),is_parallelizable(true),need_input_copy(false),
+ calling_function(0) {
mem.assign(1 + _cimg_mp_slot_c,1,1,1,0); // Allow to skip 'is_empty?' test in operator()()
result = mem._data;
}
@@ -14551,7 +14712,7 @@ namespace cimg_library_suffixed {
mem(mp.mem),code(mp.code),p_code_begin(mp.p_code_begin),p_code_end(mp.p_code_end),p_break(mp.p_break),
imgin(mp.imgin),listin(mp.listin),imgout(mp.imgout),listout(mp.listout),img_stats(mp.img_stats),
list_stats(mp.list_stats),list_median(mp.list_median),debug_indent(0),result_dim(mp.result_dim),
- break_type(0),is_parallelizable(mp.is_parallelizable),need_input_copy(mp.need_input_copy),
+ break_type(0),constcache_size(0),is_parallelizable(mp.is_parallelizable),need_input_copy(mp.need_input_copy),
result(mem._data + (mp.result - mp.mem._data)),calling_function(0) {
#ifdef cimg_use_openmp
mem[17] = omp_get_thread_num();
@@ -14566,18 +14727,18 @@ namespace cimg_library_suffixed {
unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string
CImg<uintT> res(expr._width - 1);
unsigned int *pd = res._data;
- int lv = 0;
- for (const char *ps = expr._data; *ps && lv>=0; ++ps) {
+ int level = 0;
+ for (const char *ps = expr._data; *ps && level>=0; ++ps) {
if (!next_is_escaped && *ps=='\\') next_is_escaped = true;
if (!is_escaped && *ps=='\'') { // Non-escaped character
if (!mode && ps>expr._data && *(ps - 1)=='[') next_mode = mode = 2; // Start vector-string
else if (mode==2 && *(ps + 1)==']') next_mode = !mode; // End vector-string
else if (mode<2) next_mode = mode?(mode = 0):1; // Start/end char-string
}
- *(pd++) = (unsigned int)(mode>=1 || is_escaped?lv + (mode==1):
- *ps=='(' || *ps=='['?lv++:
- *ps==')' || *ps==']'?--lv:
- lv);
+ *(pd++) = (unsigned int)(mode>=1 || is_escaped?level + (mode==1):
+ *ps=='(' || *ps=='['?level++:
+ *ps==')' || *ps==']'?--level:
+ level);
mode = next_mode;
is_escaped = next_is_escaped;
next_is_escaped = false;
@@ -14589,7 +14750,7 @@ namespace cimg_library_suffixed {
pixel_type(),_cimg_mp_calling_function,
expr._data);
}
- if (lv!=0) {
+ if (level) {
cimg::strellipsize(expr,64);
throw CImgArgumentException("[_cimg_math_parser] "
"CImg<%s>::%s: Unbalanced parentheses/brackets, in expression '%s'.",
@@ -15201,7 +15362,7 @@ namespace cimg_library_suffixed {
if (arg1==~0U) { // Create new variable
if (_cimg_mp_is_vector(arg2)) { // Vector variable
- arg1 = vector_copy(arg2);
+ arg1 = is_comp_vector(arg2)?arg2:vector_copy(arg2);
set_variable_vector(arg1);
} else { // Scalar variable
if (is_const) arg1 = arg2;
@@ -15396,7 +15557,7 @@ namespace cimg_library_suffixed {
s0!=expr._data?"...":"",s0,se<&expr.back()?"...":"");
}
- // Apply unary/binary/ternary operators. The operator precedences should be roughly the same as in C++.
+ // Apply unary/binary/ternary operators. The operator precedences should be the same as in C++.
for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1
if (*s=='=' && (*ps=='*' || *ps=='/' || *ps=='^') && *ns==*ps &&
level[s - expr._data]==clevel) { // Self-operators for complex numbers only (**=,//=,^^=)
@@ -15930,7 +16091,7 @@ namespace cimg_library_suffixed {
pos = vector(2);
CImg<ulongT>::vector((ulongT)mp_complex_mul,pos,arg1,arg2).move_to(code);
_cimg_mp_return(pos);
- } else { // Matrix multiplication
+ } else { // Particular case of matrix multiplication
p1 = _cimg_mp_vector_size(arg1);
p2 = _cimg_mp_vector_size(arg2);
arg4 = p1/p2;
@@ -15985,6 +16146,12 @@ namespace cimg_library_suffixed {
_cimg_mp_op("Operator '*'");
arg1 = compile(ss,s,depth1,0);
arg2 = compile(s + 1,se,depth1,0);
+ p2 = _cimg_mp_vector_size(arg2);
+ if (p2>0 && _cimg_mp_vector_size(arg1)==p2*p2) { // Particular case of matrix multiplication
+ pos = vector(p2);
+ CImg<ulongT>::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,p2,p2,1).move_to(code);
+ _cimg_mp_return(pos);
+ }
_cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
if (arg2==1) _cimg_mp_return(arg1);
if (arg1==1) _cimg_mp_return(arg2);
@@ -16263,6 +16430,8 @@ namespace cimg_library_suffixed {
if (*se1==']' && *ss!='[') {
_cimg_mp_op("Value accessor '[]'");
is_relative = *ss=='j' || *ss=='J';
+ s0 = std::strchr(ss,'[');
+ if (s0>ss && *(s0 - 1)==' ') cimg::swap(*s0,*(s0 - 1)); // Allow one space before opening bracket
if ((*ss=='I' || *ss=='J') && *ss1=='[' &&
(reserved_label[*ss]==~0U || !_cimg_mp_is_vector(reserved_label[*ss]))) { // Image value as a vector
@@ -16400,8 +16569,10 @@ namespace cimg_library_suffixed {
// Look for a function call, an access to image value, or a parenthesis.
if (*se1==')') {
if (*ss=='(') _cimg_mp_return(compile(ss1,se1,depth1,p_ref)); // Simple parentheses
- is_relative = *ss=='j' || *ss=='J';
_cimg_mp_op("Value accessor '()'");
+ is_relative = *ss=='j' || *ss=='J';
+ s0 = std::strchr(ss,'(');
+ if (s0>ss && *(s0 - 1)==' ') cimg::swap(*s0,*(s0 - 1)); // Allow one space before opening brace
// I/J(_#ind,_x,_y,_z,_interpolation,_boundary)
if ((*ss=='I' || *ss=='J') && *ss1=='(') { // Image value as scalar
@@ -16651,6 +16822,14 @@ namespace cimg_library_suffixed {
_cimg_mp_return(_cimg_mp_slot_nan);
}
}
+
+ if (!std::strncmp(ss,"breakpoint(",11)) { // Break point (for abort test)
+ _cimg_mp_op("Function 'breakpoint()'");
+ if (pexpr[se2 - expr._data]=='(') { // no arguments?
+ CImg<ulongT>::vector((ulongT)mp_breakpoint,_cimg_mp_slot_nan).move_to(code);
+ _cimg_mp_return(_cimg_mp_slot_nan);
+ }
+ }
break;
case 'c' :
@@ -17031,7 +17210,6 @@ namespace cimg_library_suffixed {
if (!std::strncmp(ss,"dowhile",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // Do..while
_cimg_mp_op("Function 'dowhile()'");
- if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace
s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
arg1 = code._width;
arg6 = mempos;
@@ -17157,7 +17335,7 @@ namespace cimg_library_suffixed {
_cimg_mp_check_matrix_square(arg1,1);
p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
pos = vector((p1 + 1)*p1);
- CImg<ulongT>::vector((ulongT)mp_eig,pos,arg1,p1).move_to(code);
+ CImg<ulongT>::vector((ulongT)mp_matrix_eig,pos,arg1,p1).move_to(code);
_cimg_mp_return(pos);
}
@@ -17239,7 +17417,6 @@ namespace cimg_library_suffixed {
if (*ss1=='o' && *ss2=='r' && (*ss3=='(' || (*ss3 && *ss3<=' ' && *ss4=='('))) { // For loop
_cimg_mp_op("Function 'for()'");
- if (*ss3<=' ') cimg::swap(*ss3,*ss4); // Allow space before opening brace
s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
s3 = s2 + 1; while (s3<se1 && (*s3!=',' || level[s3 - expr._data]!=clevel1)) ++s3;
@@ -17287,7 +17464,6 @@ namespace cimg_library_suffixed {
case 'i' :
if (*ss1=='f' && (*ss2=='(' || (*ss2 && *ss2<=' ' && *ss3=='('))) { // If..then[..else.]
_cimg_mp_op("Function 'if()'");
- if (*ss2<=' ') cimg::swap(*ss2,*ss3); // Allow space before opening brace
s1 = ss3; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
s2 = s1 + 1; while (s2<se1 && (*s2!=',' || level[s2 - expr._data]!=clevel1)) ++s2;
arg1 = compile(ss3,s1,depth1,0);
@@ -17336,11 +17512,15 @@ namespace cimg_library_suffixed {
if (!std::strncmp(ss,"inv(",4)) { // Matrix/scalar inversion
_cimg_mp_op("Function 'inv()'");
arg1 = compile(ss4,se1,depth1,0);
- _cimg_mp_check_matrix_square(arg1,1);
- p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
- pos = vector(p1*p1);
- CImg<ulongT>::vector((ulongT)mp_inv,pos,arg1,p1).move_to(code);
- _cimg_mp_return(pos);
+ if (_cimg_mp_is_vector(arg1)) {
+ _cimg_mp_check_matrix_square(arg1,1);
+ p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1));
+ pos = vector(p1*p1);
+ CImg<ulongT>::vector((ulongT)mp_matrix_inv,pos,arg1,p1).move_to(code);
+ _cimg_mp_return(pos);
+ }
+ if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(1/mem[arg1]);
+ _cimg_mp_scalar2(mp_div,1,arg1);
}
if (*ss1=='s') { // Family of 'is_?()' functions
@@ -17485,7 +17665,7 @@ namespace cimg_library_suffixed {
cimg::strellipsize(s0,64);
throw CImgArgumentException("[_cimg_math_parser] "
"CImg<%s>::%s: %s: Types of first and second arguments ('%s' and '%s') "
- "do not match for third argument 'nb_colsB=%u', "
+ "do not match with third argument 'nb_colsB=%u', "
"in expression '%s%s%s'.",
pixel_type(),_cimg_mp_calling_function,s_op,
s_type(arg1)._data,s_type(arg2)._data,p3,
@@ -17511,8 +17691,16 @@ namespace cimg_library_suffixed {
}
if ((cimg_sscanf(ss,"norm%u%c",&(arg1=~0U),&sep)==2 && sep=='(') ||
- !std::strncmp(ss,"norminf(",8)) { // Lp norm
+ !std::strncmp(ss,"norminf(",8) || !std::strncmp(ss,"norm(",5) ||
+ (!std::strncmp(ss,"norm",4) && ss5<se1 && (s=std::strchr(ss5,'('))!=0)) { // Lp norm
_cimg_mp_op("Function 'normP()'");
+ if (*ss4=='(') { arg1 = 2; s = ss5; }
+ else if (*ss4=='i' && *ss5=='n' && *ss6=='f' && *ss7=='(') { arg1 = ~0U; s = ss8; }
+ else if (arg1==~0U) {
+ arg1 = compile(ss4,s++,depth1,0);
+ _cimg_mp_check_constant(arg1,0,2);
+ arg1 = (unsigned int)mem[arg1];
+ } else s = std::strchr(ss4,'(') + 1;
pos = scalar();
switch (arg1) {
case 0 :
@@ -17527,7 +17715,7 @@ namespace cimg_library_suffixed {
CImg<ulongT>::vector((ulongT)mp_normp,pos,0,(ulongT)(arg1==~0U?-1:(int)arg1)).
move_to(_opcode);
}
- for (s = std::strchr(ss5,'(') + 1; s<se; ++s) {
+ for ( ; s<se; ++s) {
ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
(*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
arg2 = compile(s,ns,depth1,0);
@@ -17564,6 +17752,33 @@ namespace cimg_library_suffixed {
_cimg_mp_scalar3(mp_permutations,arg1,arg2,arg3);
}
+ if (!std::strncmp(ss,"pseudoinv(",10)) { // Matrix/scalar pseudo-inversion
+ _cimg_mp_op("Function 'pseudoinv()'");
+ s1 = ss + 10; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+ arg1 = compile(ss + 10,s1,depth1,0);
+ arg2 = s1<se1?compile(++s1,se1,depth1,0):1;
+ _cimg_mp_check_type(arg1,1,2,0);
+ _cimg_mp_check_constant(arg2,2,3);
+ p1 = _cimg_mp_vector_size(arg1);
+ p2 = (unsigned int)mem[arg2];
+ p3 = p1/p2;
+ if (p3*p2!=p1) {
+ *se = saved_char;
+ s0 = ss - 4>expr._data?ss - 4:expr._data;
+ cimg::strellipsize(s0,64);
+ throw CImgArgumentException("[_cimg_math_parser] "
+ "CImg<%s>::%s: %s: Type of first argument ('%s') "
+ "does not match with second argument 'nb_colsA=%u', "
+ "in expression '%s%s%s'.",
+ pixel_type(),_cimg_mp_calling_function,s_op,
+ s_type(arg1)._data,p2,
+ s0!=expr._data?"...":"",s0,se<&expr.back()?"...":"");
+ }
+ pos = vector(p1);
+ CImg<ulongT>::vector((ulongT)mp_matrix_pseudoinv,pos,arg1,p2,p3).move_to(code);
+ _cimg_mp_return(pos);
+ }
+
if (!std::strncmp(ss,"print(",6)) { // Print expressions
_cimg_mp_op("Function 'print()'");
for (s = ss6; s<se; ++s) {
@@ -17778,7 +17993,7 @@ namespace cimg_library_suffixed {
cimg::strellipsize(s0,64);
throw CImgArgumentException("[_cimg_math_parser] "
"CImg<%s>::%s: %s: Types of first and second arguments ('%s' and '%s') "
- "do not match for third argument 'nb_colsB=%u', "
+ "do not match with third argument 'nb_colsB=%u', "
"in expression '%s%s%s'.",
pixel_type(),_cimg_mp_calling_function,s_op,
s_type(arg1)._data,s_type(arg2)._data,p3,
@@ -17845,6 +18060,33 @@ namespace cimg_library_suffixed {
p1 = _cimg_mp_vector_size(arg1);
_cimg_mp_scalar3(mp_stod,arg1,p1,arg2);
}
+
+ if (!std::strncmp(ss,"svd(",4)) { // Matrix SVD
+ _cimg_mp_op("Function 'svd()'");
+ s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+ arg1 = compile(ss4,s1,depth1,0);
+ arg2 = s1<se1?compile(++s1,se1,depth1,0):1;
+ _cimg_mp_check_type(arg1,1,2,0);
+ _cimg_mp_check_constant(arg2,2,3);
+ p1 = _cimg_mp_vector_size(arg1);
+ p2 = (unsigned int)mem[arg2];
+ p3 = p1/p2;
+ if (p3*p2!=p1) {
+ *se = saved_char;
+ s0 = ss - 4>expr._data?ss - 4:expr._data;
+ cimg::strellipsize(s0,64);
+ throw CImgArgumentException("[_cimg_math_parser] "
+ "CImg<%s>::%s: %s: Type of first argument ('%s') "
+ "does not match with second argument 'nb_colsA=%u', "
+ "in expression '%s%s%s'.",
+ pixel_type(),_cimg_mp_calling_function,s_op,
+ s_type(arg1)._data,p2,
+ s0!=expr._data?"...":"",s0,se<&expr.back()?"...":"");
+ }
+ pos = vector(p1 + p2 + p2*p2);
+ CImg<ulongT>::vector((ulongT)mp_matrix_svd,pos,arg1,p2,p3).move_to(code);
+ _cimg_mp_return(pos);
+ }
break;
case 't' :
@@ -17980,10 +18222,16 @@ namespace cimg_library_suffixed {
case 'v' :
if ((cimg_sscanf(ss,"vector%u%c",&(arg1=~0U),&sep)==2 && sep=='(' && arg1>0) ||
- !std::strncmp(ss,"vector(",7)) { // Vector
+ !std::strncmp(ss,"vector(",7) ||
+ (!std::strncmp(ss,"vector",6) && ss7<se1 && (s=std::strchr(ss7,'('))!=0)) { // Vector
_cimg_mp_op("Function 'vector()'");
arg2 = 0; // Number of specified values.
- s = std::strchr(ss6,'(') + 1;
+ if (arg1==~0U && *ss6!='(') {
+ arg1 = compile(ss6,s++,depth1,0);
+ _cimg_mp_check_constant(arg1,0,3);
+ arg1 = (unsigned int)mem[arg1];
+ } else s = std::strchr(ss6,'(') + 1;
+
if (s<se1 || arg1==~0U) for ( ; s<se; ++s) {
ns = s; while (ns<se && (*ns!=',' || level[ns - expr._data]!=clevel1) &&
(*ns!=')' || level[ns - expr._data]!=clevel)) ++ns;
@@ -18009,7 +18257,6 @@ namespace cimg_library_suffixed {
case 'w' :
if (!std::strncmp(ss,"whiledo",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // While...do
_cimg_mp_op("Function 'whiledo()'");
- if (*ss7<=' ') cimg::swap(*ss7,*ss8); // Allow space before opening brace
s1 = ss8; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
p1 = code._width;
arg1 = compile(ss8,s1,depth1,0);
@@ -18024,6 +18271,23 @@ namespace cimg_library_suffixed {
_cimg_mp_return(pos);
}
break;
+
+ case 'x' :
+ if (!std::strncmp(ss,"xor(",4)) { // Xor
+ _cimg_mp_op("Function 'xor()'");
+ s1 = ss4; while (s1<se1 && (*s1!=',' || level[s1 - expr._data]!=clevel1)) ++s1;
+ arg1 = compile(ss4,s1,depth1,0);
+ arg2 = compile(++s1,se1,depth1,0);
+ _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1));
+ if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_bitwise_xor,arg1,arg2);
+ if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_xor,arg1,arg2);
+ if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_xor,arg1,arg2);
+ if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2))
+ _cimg_mp_constant((ulongT)mem[arg1] ^ (ulongT)mem[arg2]);
+ _cimg_mp_scalar2(mp_bitwise_xor,arg1,arg2);
+ }
+ break;
+
}
if (!std::strncmp(ss,"min(",4) || !std::strncmp(ss,"max(",4) ||
@@ -18447,16 +18711,64 @@ namespace cimg_library_suffixed {
// Insert constant value in memory.
unsigned int constant(const double val) {
+
+ // Search for built-in constant.
if (val==(double)(int)val) {
if (val>=0 && val<=10) return (unsigned int)val;
if (val<0 && val>=-5) return (unsigned int)(10 - val);
}
if (val==0.5) return 16;
if (cimg::type<double>::is_nan(val)) return _cimg_mp_slot_nan;
+
+ // Search for constant already requested before (in const cache).
+ unsigned int ind = ~0U;
+ if (constcache_size<1024) {
+ if (!constcache_size) {
+ constcache_vals.assign(16,1,1,1,0);
+ constcache_inds.assign(16,1,1,1,0);
+ *constcache_vals = val;
+ constcache_size = 1;
+ ind = 0;
+ } else { // Dichotomic search
+ const double val_beg = *constcache_vals, val_end = constcache_vals[constcache_size - 1];
+ if (val_beg>=val) ind = 0;
+ else if (val_end==val) ind = constcache_size - 1;
+ else if (val_end<val) ind = constcache_size;
+ else {
+ unsigned int i0 = 1, i1 = constcache_size - 2;
+ while (i0<=i1) {
+ const unsigned int mid = (i0 + i1)/2;
+ if (constcache_vals[mid]==val) { i0 = mid; break; }
+ else if (constcache_vals[mid]<val) i0 = mid + 1;
+ else i1 = mid - 1;
+ }
+ ind = i0;
+ }
+
+ if (ind>=constcache_size || constcache_vals[ind]!=val) {
+ ++constcache_size;
+ if (constcache_size>constcache_vals._width) {
+ constcache_vals.resize(-200,1,1,1,0);
+ constcache_inds.resize(-200,1,1,1,0);
+ }
+ const int l = constcache_size - (int)ind - 1;
+ if (l>0) {
+ std::memmove(&constcache_vals[ind + 1],&constcache_vals[ind],l*sizeof(double));
+ std::memmove(&constcache_inds[ind + 1],&constcache_inds[ind],l*sizeof(unsigned int));
+ }
+ constcache_vals[ind] = val;
+ constcache_inds[ind] = 0;
+ }
+ }
+ if (constcache_inds[ind]) return constcache_inds[ind];
+ }
+
+ // Insert new constant in memory if necessary.
if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(-200,1,1,1,0); }
const unsigned int pos = mempos++;
mem[pos] = val;
memtype[pos] = 1; // Set constant property
+ if (ind!=~0U) constcache_inds[ind] = pos;
return pos;
}
@@ -18574,7 +18886,7 @@ namespace cimg_library_suffixed {
}
// Insert code instructions for processing vectors.
- bool is_tmp_vector(const unsigned int arg) const {
+ bool is_comp_vector(const unsigned int arg) const {
unsigned int siz = _cimg_mp_vector_size(arg);
if (siz>8) return false;
const int *ptr = memtype.data(arg + 1);
@@ -18639,7 +18951,7 @@ namespace cimg_library_suffixed {
unsigned int vector1_v(const mp_func op, const unsigned int arg1) {
const unsigned int
siz = _cimg_mp_vector_size(arg1),
- pos = is_tmp_vector(arg1)?arg1:vector(siz);
+ pos = is_comp_vector(arg1)?arg1:vector(siz);
if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code);
else {
code.insert(siz);
@@ -18652,7 +18964,7 @@ namespace cimg_library_suffixed {
unsigned int vector2_vv(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
const unsigned int
siz = _cimg_mp_vector_size(arg1),
- pos = is_tmp_vector(arg1)?arg1:is_tmp_vector(arg2)?arg2:vector(siz);
+ pos = is_comp_vector(arg1)?arg1:is_comp_vector(arg2)?arg2:vector(siz);
if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_vv,pos,siz,(ulongT)op,arg1,arg2).move_to(code);
else {
code.insert(siz);
@@ -18665,7 +18977,7 @@ namespace cimg_library_suffixed {
unsigned int vector2_vs(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
const unsigned int
siz = _cimg_mp_vector_size(arg1),
- pos = is_tmp_vector(arg1)?arg1:vector(siz);
+ pos = is_comp_vector(arg1)?arg1:vector(siz);
if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_vs,pos,siz,(ulongT)op,arg1,arg2).move_to(code);
else {
code.insert(siz);
@@ -18678,7 +18990,7 @@ namespace cimg_library_suffixed {
unsigned int vector2_sv(const mp_func op, const unsigned int arg1, const unsigned int arg2) {
const unsigned int
siz = _cimg_mp_vector_size(arg2),
- pos = is_tmp_vector(arg2)?arg2:vector(siz);
+ pos = is_comp_vector(arg2)?arg2:vector(siz);
if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_sv,pos,siz,(ulongT)op,arg1,arg2).move_to(code);
else {
code.insert(siz);
@@ -18692,7 +19004,7 @@ namespace cimg_library_suffixed {
const unsigned int arg3) {
const unsigned int
siz = _cimg_mp_vector_size(arg1),
- pos = is_tmp_vector(arg1)?arg1:vector(siz);
+ pos = is_comp_vector(arg1)?arg1:vector(siz);
if (siz>24) CImg<ulongT>::vector((ulongT)mp_vector_map_vss,pos,siz,(ulongT)op,arg1,arg2,arg3).move_to(code);
else {
code.insert(siz);
@@ -18924,12 +19236,22 @@ namespace cimg_library_suffixed {
return (double)((longT)_mp_arg(2)>>(unsigned int)_mp_arg(3));
}
+ static double mp_bitwise_xor(_cimg_math_parser& mp) {
+ return (double)((ulongT)_mp_arg(2) ^ (ulongT)_mp_arg(3));
+ }
+
static double mp_break(_cimg_math_parser& mp) {
mp.break_type = 1;
mp.p_code = mp.p_break - 1;
return cimg::type<double>::nan();
}
+ static double mp_breakpoint(_cimg_math_parser& mp) {
+ cimg_abort_test();
+ cimg::unused(mp);
+ return cimg::type<double>::nan();
+ }
+
static double mp_cbrt(_cimg_math_parser& mp) {
return cimg::cbrt(_mp_arg(2));
}
@@ -19303,17 +19625,6 @@ namespace cimg_library_suffixed {
return cimg::type<double>::nan();
}
- static double mp_eig(_cimg_math_parser& mp) {
- double *ptrd = &_mp_arg(1) + 1;
- const double *ptr1 = &_mp_arg(2) + 1;
- const unsigned int k = (unsigned int)mp.opcode[3];
- CImg<double> val, vec;
- CImg<double>(ptr1,k,k,1,1,true).symmetric_eigen(val,vec);
- CImg<double>(ptrd,k,1,1,1,true) = val.unroll('x');
- CImg<double>(ptrd + k,k,k,1,1,true) = vec.get_transpose();
- return cimg::type<double>::nan();
- }
-
static double mp_eq(_cimg_math_parser& mp) {
return (double)(_mp_arg(2)==_mp_arg(3));
}
@@ -19515,14 +19826,6 @@ namespace cimg_library_suffixed {
return (double)(longT)_mp_arg(2);
}
- static double mp_inv(_cimg_math_parser& mp) {
- double *ptrd = &_mp_arg(1) + 1;
- const double *ptr1 = &_mp_arg(2) + 1;
- const unsigned int k = (unsigned int)mp.opcode[3];
- CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptr1,k,k,1,1,true).get_invert();
- return cimg::type<double>::nan();
- }
-
static double mp_ioff(_cimg_math_parser& mp) {
const unsigned int
boundary_conditions = (unsigned int)_mp_arg(3);
@@ -20291,6 +20594,25 @@ namespace cimg_library_suffixed {
return (double)(_mp_arg(2)<=_mp_arg(3));
}
+ static double mp_matrix_eig(_cimg_math_parser& mp) {
+ double *ptrd = &_mp_arg(1) + 1;
+ const double *ptr1 = &_mp_arg(2) + 1;
+ const unsigned int k = (unsigned int)mp.opcode[3];
+ CImg<double> val, vec;
+ CImg<double>(ptr1,k,k,1,1,true).symmetric_eigen(val,vec);
+ CImg<double>(ptrd,1,k,1,1,true) = val;
+ CImg<double>(ptrd + k,k,k,1,1,true) = vec.get_transpose();
+ return cimg::type<double>::nan();
+ }
+
+ static double mp_matrix_inv(_cimg_math_parser& mp) {
+ double *ptrd = &_mp_arg(1) + 1;
+ const double *ptr1 = &_mp_arg(2) + 1;
+ const unsigned int k = (unsigned int)mp.opcode[3];
+ CImg<double>(ptrd,k,k,1,1,true) = CImg<double>(ptr1,k,k,1,1,true).get_invert();
+ return cimg::type<double>::nan();
+ }
+
static double mp_matrix_mul(_cimg_math_parser& mp) {
double *ptrd = &_mp_arg(1) + 1;
const double
@@ -20304,6 +20626,30 @@ namespace cimg_library_suffixed {
return cimg::type<double>::nan();
}
+ static double mp_matrix_pseudoinv(_cimg_math_parser& mp) {
+ double *ptrd = &_mp_arg(1) + 1;
+ const double *ptr1 = &_mp_arg(2) + 1;
+ const unsigned int
+ k = (unsigned int)mp.opcode[3],
+ l = (unsigned int)mp.opcode[4];
+ CImg<double>(ptrd,l,k,1,1,true) = CImg<double>(ptr1,k,l,1,1,true).get_pseudoinvert();
+ return cimg::type<double>::nan();
+ }
+
+ static double mp_matrix_svd(_cimg_math_parser& mp) {
+ double *ptrd = &_mp_arg(1) + 1;
+ const double *ptr1 = &_mp_arg(2) + 1;
+ const unsigned int
+ k = (unsigned int)mp.opcode[3],
+ l = (unsigned int)mp.opcode[4];
+ CImg<double> U, S, V;
+ CImg<double>(ptr1,k,l,1,1,true).SVD(U,S,V);
+ CImg<double>(ptrd,k,l,1,1,true) = U;
+ CImg<double>(ptrd + k*l,1,k,1,1,true) = S;
+ CImg<double>(ptrd + k*l + k,k,k,1,1,true) = V;
+ return cimg::type<double>::nan();
+ }
+
static double mp_max(_cimg_math_parser& mp) {
const unsigned int i_end = (unsigned int)mp.opcode[2];
double val = _mp_arg(3);
@@ -20985,7 +21331,7 @@ namespace cimg_library_suffixed {
static double mp_sum(_cimg_math_parser& mp) {
const unsigned int i_end = (unsigned int)mp.opcode[2];
double val = _mp_arg(3);
- for (unsigned int i = 3; i<i_end; ++i) val+=_mp_arg(i);
+ for (unsigned int i = 4; i<i_end; ++i) val+=_mp_arg(i);
return val;
}
@@ -21225,7 +21571,15 @@ namespace cimg_library_suffixed {
siz = siz0;
cimg::mutex(6);
std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = [ ",expr._data);
- while (siz-->0) std::fprintf(cimg::output(),"%g%s",mp.mem[ptr++],siz?",":"");
+ unsigned int count = 0;
+ while (siz-->0) {
+ if (count>=64 && siz>=64) {
+ std::fprintf(cimg::output(),"...,");
+ ptr = (unsigned int)mp.opcode[1] + 1 + siz0 - 64;
+ siz = 64;
+ } else std::fprintf(cimg::output(),"%g%s",mp.mem[ptr++],siz?",":"");
+ ++count;
+ }
std::fprintf(cimg::output()," ] (size: %u)",siz0);
std::fflush(cimg::output());
cimg::mutex(6,0);
@@ -25026,6 +25380,7 @@ namespace cimg_library_suffixed {
if (repeat_values && nb && nb<siz)
for (T *ptrs = _data, *const ptre = _data + siz; ptrd<ptre; ++ptrs) *(ptrd++) = *ptrs;
}
+
cimg::exception_mode(omode);
cimg_abort_test();
return *this;
@@ -26220,7 +26575,7 @@ namespace cimg_library_suffixed {
dx[nb] = 1; dy[nb] = 1; dz[nb++] = 1;
}
}
- return _get_label(nb,dx,dy,dz,tolerance);
+ return _label(nb,dx,dy,dz,tolerance);
}
//! Label connected components \overloading.
@@ -26245,12 +26600,12 @@ namespace cimg_library_suffixed {
connectivity_mask(x,y,z)) {
dx[nb] = x; dy[nb] = y; dz[nb++] = z;
}
- return _get_label(nb,dx,dy,dz,tolerance);
+ return _label(nb,dx,dy,dz,tolerance);
}
- CImg<ulongT> _get_label(const unsigned int nb, const int
- *const dx, const int *const dy, const int *const dz,
- const Tfloat tolerance) const {
+ CImg<ulongT> _label(const unsigned int nb, const int
+ *const dx, const int *const dy, const int *const dz,
+ const Tfloat tolerance) const {
CImg<ulongT> res(_width,_height,_depth,_spectrum);
cimg_forC(*this,c) {
CImg<ulongT> _res = res.get_shared_channel(c);
@@ -27018,9 +27373,9 @@ namespace cimg_library_suffixed {
//! Convert pixel values from RGB to XYZ color spaces.
/**
- \note Use formula from the Wikipedia page : https://en.wikipedia.org/wiki/CIE_1931_color_space
+ \param use_D65 Tell to use the D65 illuminant (D50 otherwise).
**/
- CImg<T>& RGBtoXYZ() {
+ CImg<T>& RGBtoXYZ(const bool use_D65=true) {
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"RGBtoXYZ(): Instance is not a RGB image.",
@@ -27034,20 +27389,29 @@ namespace cimg_library_suffixed {
R = (Tfloat)p1[N]/255,
G = (Tfloat)p2[N]/255,
B = (Tfloat)p3[N]/255;
- p1[N] = (T)(0.43603516*R + 0.38511658*G + 0.14305115*B);
- p2[N] = (T)(0.22248840*R + 0.71690369*G + 0.06060791*B);
- p3[N] = (T)(0.01391602*R + 0.09706116*G + 0.71392822*B);
+ if (use_D65) { // D65
+ p1[N] = (T)(0.4124564*R + 0.3575761*G + 0.1804375*B);
+ p2[N] = (T)(0.2126729*R + 0.7151522*G + 0.0721750*B);
+ p3[N] = (T)(0.0193339*R + 0.1191920*G + 0.9503041*B);
+ } else { // D50
+ p1[N] = (T)(0.43603516*R + 0.38511658*G + 0.14305115*B);
+ p2[N] = (T)(0.22248840*R + 0.71690369*G + 0.06060791*B);
+ p3[N] = (T)(0.01391602*R + 0.09706116*G + 0.71392822*B);
+ }
}
return *this;
}
//! Convert pixel values from RGB to XYZ color spaces \newinstance.
- CImg<Tfloat> get_RGBtoXYZ() const {
- return CImg<Tfloat>(*this,false).RGBtoXYZ();
+ CImg<Tfloat> get_RGBtoXYZ(const bool use_D65=true) const {
+ return CImg<Tfloat>(*this,false).RGBtoXYZ(use_D65);
}
//! Convert pixel values from XYZ to RGB color spaces.
- CImg<T>& XYZtoRGB() {
+ /**
+ \param use_D65 Tell to use the D65 illuminant (D50 otherwise).
+ **/
+ CImg<T>& XYZtoRGB(const bool use_D65=true) {
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"XYZtoRGB(): Instance is not a XYZ image.",
@@ -27061,27 +27425,33 @@ namespace cimg_library_suffixed {
X = (Tfloat)p1[N]*255,
Y = (Tfloat)p2[N]*255,
Z = (Tfloat)p3[N]*255;
- p1[N] = (T)cimg::cut(3.134274799724*X - 1.617275708956*Y - 0.490724283042*Z,0,255);
- p2[N] = (T)cimg::cut(-0.978795575994*X + 1.916161689117*Y + 0.033453331711*Z,0,255);
- p3[N] = (T)cimg::cut(0.071976988401*X - 0.228984974402*Y + 1.405718224383*Z,0,255);
+ if (use_D65) {
+ p1[N] = (T)cimg::cut(3.2404542*X - 1.5371385*Y - 0.4985314*Z,0,255);
+ p2[N] = (T)cimg::cut(-0.9692660*X + 1.8760108*Y + 0.0415560*Z,0,255);
+ p3[N] = (T)cimg::cut(0.0556434*X - 0.2040259*Y + 1.0572252*Z,0,255);
+ } else {
+ p1[N] = (T)cimg::cut(3.134274799724*X - 1.617275708956*Y - 0.490724283042*Z,0,255);
+ p2[N] = (T)cimg::cut(-0.978795575994*X + 1.916161689117*Y + 0.033453331711*Z,0,255);
+ p3[N] = (T)cimg::cut(0.071976988401*X - 0.228984974402*Y + 1.405718224383*Z,0,255);
+ }
}
return *this;
}
//! Convert pixel values from XYZ to RGB color spaces \newinstance.
- CImg<Tuchar> get_XYZtoRGB() const {
- return CImg<Tuchar>(*this,false).XYZtoRGB();
+ CImg<Tuchar> get_XYZtoRGB(const bool use_D65=true) const {
+ return CImg<Tuchar>(*this,false).XYZtoRGB(use_D65);
}
//! Convert pixel values from XYZ to Lab color spaces.
- CImg<T>& XYZtoLab() {
+ CImg<T>& XYZtoLab(const bool use_D65=true) {
#define _cimg_Labf(x) (24389*(x)>216?cimg::cbrt(x):(24389*(x)/27 + 16)/116)
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"XYZtoLab(): Instance is not a XYZ image.",
cimg_instance);
- const CImg<Tfloat> white = CImg<Tfloat>(1,1,1,3,255).RGBtoXYZ();
+ const CImg<Tfloat> white = CImg<Tfloat>(1,1,1,3,255).RGBtoXYZ(use_D65);
T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
const ulongT whd = (ulongT)_width*_height*_depth;
cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=128))
@@ -27101,17 +27471,17 @@ namespace cimg_library_suffixed {
}
//! Convert pixel values from XYZ to Lab color spaces \newinstance.
- CImg<Tfloat> get_XYZtoLab() const {
- return CImg<Tfloat>(*this,false).XYZtoLab();
+ CImg<Tfloat> get_XYZtoLab(const bool use_D65=true) const {
+ return CImg<Tfloat>(*this,false).XYZtoLab(use_D65);
}
//! Convert pixel values from Lab to XYZ color spaces.
- CImg<T>& LabtoXYZ() {
+ CImg<T>& LabtoXYZ(const bool use_D65=true) {
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"LabtoXYZ(): Instance is not a Lab image.",
cimg_instance);
- const CImg<Tfloat> white = CImg<Tfloat>(1,1,1,3,255).RGBtoXYZ();
+ const CImg<Tfloat> white = CImg<Tfloat>(1,1,1,3,255).RGBtoXYZ(use_D65);
T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
const ulongT whd = (ulongT)_width*_height*_depth;
cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=128))
@@ -27134,8 +27504,8 @@ namespace cimg_library_suffixed {
}
//! Convert pixel values from Lab to XYZ color spaces \newinstance.
- CImg<Tfloat> get_LabtoXYZ() const {
- return CImg<Tfloat>(*this,false).LabtoXYZ();
+ CImg<Tfloat> get_LabtoXYZ(const bool use_D65=true) const {
+ return CImg<Tfloat>(*this,false).LabtoXYZ(use_D65);
}
//! Convert pixel values from XYZ to xyY color spaces.
@@ -27196,43 +27566,43 @@ namespace cimg_library_suffixed {
}
//! Convert pixel values from RGB to Lab color spaces.
- CImg<T>& RGBtoLab() {
- return RGBtoXYZ().XYZtoLab();
+ CImg<T>& RGBtoLab(const bool use_D65=true) {
+ return RGBtoXYZ(use_D65).XYZtoLab(use_D65);
}
//! Convert pixel values from RGB to Lab color spaces \newinstance.
- CImg<Tfloat> get_RGBtoLab() const {
- return CImg<Tfloat>(*this,false).RGBtoLab();
+ CImg<Tfloat> get_RGBtoLab(const bool use_D65=true) const {
+ return CImg<Tfloat>(*this,false).RGBtoLab(use_D65);
}
//! Convert pixel values from Lab to RGB color spaces.
- CImg<T>& LabtoRGB() {
- return LabtoXYZ().XYZtoRGB();
+ CImg<T>& LabtoRGB(const bool use_D65=true) {
+ return LabtoXYZ().XYZtoRGB(use_D65);
}
//! Convert pixel values from Lab to RGB color spaces \newinstance.
- CImg<Tuchar> get_LabtoRGB() const {
- return CImg<Tuchar>(*this,false).LabtoRGB();
+ CImg<Tuchar> get_LabtoRGB(const bool use_D65=true) const {
+ return CImg<Tuchar>(*this,false).LabtoRGB(use_D65);
}
//! Convert pixel values from RGB to xyY color spaces.
- CImg<T>& RGBtoxyY() {
- return RGBtoXYZ().XYZtoxyY();
+ CImg<T>& RGBtoxyY(const bool use_D65=true) {
+ return RGBtoXYZ(use_D65).XYZtoxyY();
}
//! Convert pixel values from RGB to xyY color spaces \newinstance.
- CImg<Tfloat> get_RGBtoxyY() const {
- return CImg<Tfloat>(*this,false).RGBtoxyY();
+ CImg<Tfloat> get_RGBtoxyY(const bool use_D65=true) const {
+ return CImg<Tfloat>(*this,false).RGBtoxyY(use_D65);
}
//! Convert pixel values from xyY to RGB color spaces.
- CImg<T>& xyYtoRGB() {
- return xyYtoXYZ().XYZtoRGB();
+ CImg<T>& xyYtoRGB(const bool use_D65=true) {
+ return xyYtoXYZ().XYZtoRGB(use_D65);
}
//! Convert pixel values from xyY to RGB color spaces \newinstance.
- CImg<Tuchar> get_xyYtoRGB() const {
- return CImg<Tuchar>(*this,false).xyYtoRGB();
+ CImg<Tuchar> get_xyYtoRGB(const bool use_D65=true) const {
+ return CImg<Tuchar>(*this,false).xyYtoRGB(use_D65);
}
//! Convert pixel values from RGB to CMYK color spaces.
@@ -27574,37 +27944,37 @@ namespace cimg_library_suffixed {
//
case 3 : {
CImg<uintT> off(cimg::max(sx,sy,sz,sc));
- CImg<floatT> foff(off._width);
+ CImg<doubleT> foff(off._width);
CImg<T> resx, resy, resz, resc;
+ double curr, old;
if (sx!=_width) {
if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
+ else if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
else {
- if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
- else {
- const float fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.0f)/(sx - 1):0):(float)_width/sx;
- resx.assign(sx,_height,_depth,_spectrum);
- float curr = 0, old = 0;
- unsigned int *poff = off._data;
- float *pfoff = foff._data;
- cimg_forX(resx,x) {
- *(pfoff++) = curr - (unsigned int)curr;
- old = curr;
- curr+=fx;
- *(poff++) = (unsigned int)curr - (unsigned int)old;
- }
- cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resx.size()>=65536))
+ const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.0)/(sx - 1):0):
+ (double)_width/sx;
+ resx.assign(sx,_height,_depth,_spectrum);
+ curr = old = 0;
+ unsigned int *poff = off._data;
+ double *pfoff = foff._data;
+ cimg_forX(resx,x) {
+ *(pfoff++) = curr - (unsigned int)curr;
+ old = curr;
+ curr = std::min(width() - 1.0,curr + fx);
+ *(poff++) = (unsigned int)curr - (unsigned int)old;
+ }
+ cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resx.size()>=65536))
cimg_forYZC(resx,y,z,c) {
- const T *ptrs = data(0,y,z,c), *const ptrsmax = ptrs + _width - 1;
- T *ptrd = resx.data(0,y,z,c);
- const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
- cimg_forX(resx,x) {
- const float alpha = *(pfoff++);
- const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs + 1):val1;
- *(ptrd++) = (T)((1 - alpha)*val1 + alpha*val2);
- ptrs+=*(poff++);
- }
+ const T *ptrs = data(0,y,z,c), *const ptrsmax = ptrs + _width - 1;
+ T *ptrd = resx.data(0,y,z,c);
+ const unsigned int *poff = off._data;
+ const double *pfoff = foff._data;
+ cimg_forX(resx,x) {
+ const double alpha = *(pfoff++);
+ const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs + 1):val1;
+ *(ptrd++) = (T)((1 - alpha)*val1 + alpha*val2);
+ ptrs+=*(poff++);
}
}
}
@@ -27615,16 +27985,16 @@ namespace cimg_library_suffixed {
else {
if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy);
else {
- const float fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0f)/(sy - 1):0):
- (float)_height/sy;
+ const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0)/(sy - 1):0):
+ (double)_height/sy;
resy.assign(sx,sy,_depth,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forY(resy,y) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fy;
+ curr = std::min(height() - 1.0,curr + fy);
*(poff++) = sx*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resy.size()>=65536))
@@ -27632,9 +28002,9 @@ namespace cimg_library_suffixed {
const T *ptrs = resx.data(x,0,z,c), *const ptrsmax = ptrs + (_height - 1)*sx;
T *ptrd = resy.data(x,0,z,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forY(resy,y) {
- const float alpha = *(pfoff++);
+ const double alpha = *(pfoff++);
const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs + sx):val1;
*ptrd = (T)((1 - alpha)*val1 + alpha*val2);
ptrd+=sx;
@@ -27651,16 +28021,17 @@ namespace cimg_library_suffixed {
else {
if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz);
else {
- const float fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.0f)/(sz - 1):0):(float)_depth/sz;
+ const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.0)/(sz - 1):0):
+ (double)_depth/sz;
const unsigned int sxy = sx*sy;
resz.assign(sx,sy,sz,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forZ(resz,z) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fz;
+ curr = std::min(depth() - 1.0,curr + fz);
*(poff++) = sxy*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resz.size()>=65536))
@@ -27668,9 +28039,9 @@ namespace cimg_library_suffixed {
const T *ptrs = resy.data(x,y,0,c), *const ptrsmax = ptrs + (_depth - 1)*sxy;
T *ptrd = resz.data(x,y,0,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forZ(resz,z) {
- const float alpha = *(pfoff++);
+ const double alpha = *(pfoff++);
const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs + sxy):val1;
*ptrd = (T)((1 - alpha)*val1 + alpha*val2);
ptrd+=sxy;
@@ -27687,17 +28058,17 @@ namespace cimg_library_suffixed {
else {
if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc);
else {
- const float fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.0f)/(sc - 1):0):
- (float)_spectrum/sc;
+ const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.0)/(sc - 1):0):
+ (double)_spectrum/sc;
const unsigned int sxyz = sx*sy*sz;
resc.assign(sx,sy,sz,sc);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forC(resc,c) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fc;
+ curr = std::min(spectrum() - 1.0,curr + fc);
*(poff++) = sxyz*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resc.size()>=65536))
@@ -27705,9 +28076,9 @@ namespace cimg_library_suffixed {
const T *ptrs = resz.data(x,y,z,0), *const ptrsmax = ptrs + (_spectrum - 1)*sxyz;
T *ptrd = resc.data(x,y,z,0);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forC(resc,c) {
- const float alpha = *(pfoff++);
+ const double alpha = *(pfoff++);
const T val1 = *ptrs, val2 = ptrs<ptrsmax?*(ptrs + sxyz):val1;
*ptrd = (T)((1 - alpha)*val1 + alpha*val2);
ptrd+=sxyz;
@@ -27792,23 +28163,25 @@ namespace cimg_library_suffixed {
case 5 : {
const Tfloat vmin = (Tfloat)cimg::type<T>::min(), vmax = (Tfloat)cimg::type<T>::max();
CImg<uintT> off(cimg::max(sx,sy,sz,sc));
- CImg<floatT> foff(off._width);
+ CImg<doubleT> foff(off._width);
CImg<T> resx, resy, resz, resc;
+ double curr, old;
if (sx!=_width) {
if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
else {
if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
else {
- const float fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.0f)/(sx - 1):0):(float)_width/sx;
+ const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.0)/(sx - 1):0):
+ (double)_width/sx;
resx.assign(sx,_height,_depth,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forX(resx,x) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fx;
+ curr = std::min(width() - 1.0,curr + fx);
*(poff++) = (unsigned int)curr - (unsigned int)old;
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resx.size()>=65536))
@@ -27816,14 +28189,14 @@ namespace cimg_library_suffixed {
const T *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_width - 2);
T *ptrd = resx.data(0,y,z,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forX(resx,x) {
- const float t = *(pfoff++);
- const Tfloat
- val1 = (Tfloat)*ptrs,
- val0 = ptrs>ptrs0?(Tfloat)*(ptrs - 1):val1,
- val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs + 1):val1,
- val3 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2):val2,
+ const double
+ t = *(pfoff++),
+ val1 = (double)*ptrs,
+ val0 = ptrs>ptrs0?(double)*(ptrs - 1):val1,
+ val2 = ptrs<=ptrsmax?(double)*(ptrs + 1):val1,
+ val3 = ptrs<ptrsmax?(double)*(ptrs + 2):val2,
val = val1 + 0.5f*(t*(-val0 + val2) + t*t*(2*val0 - 5*val1 + 4*val2 - val3) +
t*t*t*(-val0 + 3*val1 - 3*val2 + val3));
*(ptrd++) = (T)(val<vmin?vmin:val>vmax?vmax:val);
@@ -27839,16 +28212,16 @@ namespace cimg_library_suffixed {
else {
if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy);
else {
- const float fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0f)/(sy - 1):0):
- (float)_height/sy;
+ const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0)/(sy - 1):0):
+ (double)_height/sy;
resy.assign(sx,sy,_depth,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forY(resy,y) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fy;
+ curr = std::min(height() - 1.0,curr + fy);
*(poff++) = sx*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resy.size()>=65536))
@@ -27856,14 +28229,14 @@ namespace cimg_library_suffixed {
const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_height - 2)*sx;
T *ptrd = resy.data(x,0,z,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forY(resy,y) {
- const float t = *(pfoff++);
- const Tfloat
- val1 = (Tfloat)*ptrs,
- val0 = ptrs>ptrs0?(Tfloat)*(ptrs - sx):val1,
- val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs + sx):val1,
- val3 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2*sx):val2,
+ const double
+ t = *(pfoff++),
+ val1 = (double)*ptrs,
+ val0 = ptrs>ptrs0?(double)*(ptrs - sx):val1,
+ val2 = ptrs<=ptrsmax?(double)*(ptrs + sx):val1,
+ val3 = ptrs<ptrsmax?(double)*(ptrs + 2*sx):val2,
val = val1 + 0.5f*(t*(-val0 + val2) + t*t*(2*val0 - 5*val1 + 4*val2 - val3) +
t*t*t*(-val0 + 3*val1 - 3*val2 + val3));
*ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
@@ -27881,16 +28254,17 @@ namespace cimg_library_suffixed {
else {
if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz);
else {
- const float fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.0f)/(sz - 1):0):(float)_depth/sz;
+ const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.0)/(sz - 1):0):
+ (double)_depth/sz;
const unsigned int sxy = sx*sy;
resz.assign(sx,sy,sz,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forZ(resz,z) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fz;
+ curr = std::min(depth() - 1.0,curr + fz);
*(poff++) = sxy*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resz.size()>=65536))
@@ -27898,14 +28272,14 @@ namespace cimg_library_suffixed {
const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmax = ptrs + (_depth - 2)*sxy;
T *ptrd = resz.data(x,y,0,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forZ(resz,z) {
- const float t = *(pfoff++);
- const Tfloat
- val1 = (Tfloat)*ptrs,
- val0 = ptrs>ptrs0?(Tfloat)*(ptrs - sxy):val1,
- val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs + sxy):val1,
- val3 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2*sxy):val2,
+ const double
+ t = *(pfoff++),
+ val1 = (double)*ptrs,
+ val0 = ptrs>ptrs0?(double)*(ptrs - sxy):val1,
+ val2 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val1,
+ val3 = ptrs<ptrsmax?(double)*(ptrs + 2*sxy):val2,
val = val1 + 0.5f*(t*(-val0 + val2) + t*t*(2*val0 - 5*val1 + 4*val2 - val3) +
t*t*t*(-val0 + 3*val1 - 3*val2 + val3));
*ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
@@ -27923,17 +28297,17 @@ namespace cimg_library_suffixed {
else {
if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc);
else {
- const float fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.0f)/(sc - 1):0):
- (float)_spectrum/sc;
+ const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.0)/(sc - 1):0):
+ (double)_spectrum/sc;
const unsigned int sxyz = sx*sy*sz;
resc.assign(sx,sy,sz,sc);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forC(resc,c) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fc;
+ curr = std::min(spectrum() - 1.0,curr + fc);
*(poff++) = sxyz*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resc.size()>=65536))
@@ -27941,14 +28315,14 @@ namespace cimg_library_suffixed {
const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmax = ptrs + (_spectrum - 2)*sxyz;
T *ptrd = resc.data(x,y,z,0);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forC(resc,c) {
- const float t = *(pfoff++);
- const Tfloat
- val1 = (Tfloat)*ptrs,
- val0 = ptrs>ptrs0?(Tfloat)*(ptrs - sxyz):val1,
- val2 = ptrs<=ptrsmax?(Tfloat)*(ptrs + sxyz):val1,
- val3 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2*sxyz):val2,
+ const double
+ t = *(pfoff++),
+ val1 = (double)*ptrs,
+ val0 = ptrs>ptrs0?(double)*(ptrs - sxyz):val1,
+ val2 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val1,
+ val3 = ptrs<ptrsmax?(double)*(ptrs + 2*sxyz):val2,
val = val1 + 0.5f*(t*(-val0 + val2) + t*t*(2*val0 - 5*val1 + 4*val2 - val3) +
t*t*t*(-val0 + 3*val1 - 3*val2 + val3));
*ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
@@ -27967,25 +28341,27 @@ namespace cimg_library_suffixed {
// Lanczos interpolation.
//
case 6 : {
- const Tfloat vmin = (Tfloat)cimg::type<T>::min(), vmax = (Tfloat)cimg::type<T>::max();
+ const double vmin = (double)cimg::type<T>::min(), vmax = (double)cimg::type<T>::max();
CImg<uintT> off(cimg::max(sx,sy,sz,sc));
- CImg<floatT> foff(off._width);
+ CImg<doubleT> foff(off._width);
CImg<T> resx, resy, resz, resc;
+ double curr, old;
if (sx!=_width) {
if (_width==1) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx);
else {
if (_width>sx) get_resize(sx,_height,_depth,_spectrum,2).move_to(resx);
else {
- const float fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.0f)/(sx - 1):0):(float)_width/sx;
+ const double fx = (!boundary_conditions && sx>_width)?(sx>1?(_width - 1.0)/(sx - 1):0):
+ (double)_width/sx;
resx.assign(sx,_height,_depth,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forX(resx,x) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fx;
+ curr = std::min(width() - 1.0,curr + fx);
*(poff++) = (unsigned int)curr - (unsigned int)old;
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resx.size()>=65536))
@@ -27994,21 +28370,20 @@ namespace cimg_library_suffixed {
*const ptrsmax = ptrs0 + (_width - 2);
T *ptrd = resx.data(0,y,z,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forX(resx,x) {
- const float
+ const double
t = *(pfoff++),
w0 = _cimg_lanczos(t + 2),
w1 = _cimg_lanczos(t + 1),
w2 = _cimg_lanczos(t),
w3 = _cimg_lanczos(t - 1),
- w4 = _cimg_lanczos(t - 2);
- const Tfloat
- val2 = (Tfloat)*ptrs,
- val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs - 1):val2,
- val0 = ptrs>ptrsmin?(Tfloat)*(ptrs - 2):val1,
- val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs + 1):val2,
- val4 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2):val3,
+ w4 = _cimg_lanczos(t - 2),
+ val2 = (double)*ptrs,
+ val1 = ptrs>=ptrsmin?(double)*(ptrs - 1):val2,
+ val0 = ptrs>ptrsmin?(double)*(ptrs - 2):val1,
+ val3 = ptrs<=ptrsmax?(double)*(ptrs + 1):val2,
+ val4 = ptrs<ptrsmax?(double)*(ptrs + 2):val3,
val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
*(ptrd++) = (T)(val<vmin?vmin:val>vmax?vmax:val);
ptrs+=*(poff++);
@@ -28023,16 +28398,16 @@ namespace cimg_library_suffixed {
else {
if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy);
else {
- const float fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0f)/(sy - 1):0):
- (float)_height/sy;
+ const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0)/(sy - 1):0):
+ (double)_height/sy;
resy.assign(sx,sy,_depth,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forY(resy,y) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fy;
+ curr = std::min(height() - 1.0,curr + fy);
*(poff++) = sx*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resy.size()>=65536))
@@ -28041,21 +28416,20 @@ namespace cimg_library_suffixed {
*const ptrsmax = ptrs0 + (_height - 2)*sx;
T *ptrd = resy.data(x,0,z,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forY(resy,y) {
- const float
+ const double
t = *(pfoff++),
w0 = _cimg_lanczos(t + 2),
w1 = _cimg_lanczos(t + 1),
w2 = _cimg_lanczos(t),
w3 = _cimg_lanczos(t - 1),
- w4 = _cimg_lanczos(t - 2);
- const Tfloat
- val2 = (Tfloat)*ptrs,
- val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs - sx):val2,
- val0 = ptrs>ptrsmin?(Tfloat)*(ptrs - 2*sx):val1,
- val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs + sx):val2,
- val4 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2*sx):val3,
+ w4 = _cimg_lanczos(t - 2),
+ val2 = (double)*ptrs,
+ val1 = ptrs>=ptrsmin?(double)*(ptrs - sx):val2,
+ val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sx):val1,
+ val3 = ptrs<=ptrsmax?(double)*(ptrs + sx):val2,
+ val4 = ptrs<ptrsmax?(double)*(ptrs + 2*sx):val3,
val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
*ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
ptrd+=sx;
@@ -28072,16 +28446,17 @@ namespace cimg_library_suffixed {
else {
if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz);
else {
- const float fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.0f)/(sz - 1):0):(float)_depth/sz;
+ const double fz = (!boundary_conditions && sz>_depth)?(sz>1?(_depth - 1.0)/(sz - 1):0):
+ (double)_depth/sz;
const unsigned int sxy = sx*sy;
resz.assign(sx,sy,sz,_spectrum);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forZ(resz,z) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fz;
+ curr = std::min(depth() - 1.0,curr + fz);
*(poff++) = sxy*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resz.size()>=65536))
@@ -28090,21 +28465,20 @@ namespace cimg_library_suffixed {
*const ptrsmax = ptrs0 + (_depth - 2)*sxy;
T *ptrd = resz.data(x,y,0,c);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forZ(resz,z) {
- const float
+ const double
t = *(pfoff++),
w0 = _cimg_lanczos(t + 2),
w1 = _cimg_lanczos(t + 1),
w2 = _cimg_lanczos(t),
w3 = _cimg_lanczos(t - 1),
- w4 = _cimg_lanczos(t - 2);
- const Tfloat
- val2 = (Tfloat)*ptrs,
- val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs - sxy):val2,
- val0 = ptrs>ptrsmin?(Tfloat)*(ptrs - 2*sxy):val1,
- val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs + sxy):val2,
- val4 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2*sxy):val3,
+ w4 = _cimg_lanczos(t - 2),
+ val2 = (double)*ptrs,
+ val1 = ptrs>=ptrsmin?(double)*(ptrs - sxy):val2,
+ val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxy):val1,
+ val3 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val2,
+ val4 = ptrs<ptrsmax?(double)*(ptrs + 2*sxy):val3,
val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
*ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
ptrd+=sxy;
@@ -28121,17 +28495,17 @@ namespace cimg_library_suffixed {
else {
if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc);
else {
- const float fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.0f)/(sc - 1):0):
- (float)_spectrum/sc;
+ const double fc = (!boundary_conditions && sc>_spectrum)?(sc>1?(_spectrum - 1.0)/(sc - 1):0):
+ (double)_spectrum/sc;
const unsigned int sxyz = sx*sy*sz;
resc.assign(sx,sy,sz,sc);
- float curr = 0, old = 0;
+ curr = old = 0;
unsigned int *poff = off._data;
- float *pfoff = foff._data;
+ double *pfoff = foff._data;
cimg_forC(resc,c) {
*(pfoff++) = curr - (unsigned int)curr;
old = curr;
- curr+=fc;
+ curr = std::min(spectrum() - 1.0,curr + fc);
*(poff++) = sxyz*((unsigned int)curr - (unsigned int)old);
}
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(resc.size()>=65536))
@@ -28140,21 +28514,20 @@ namespace cimg_library_suffixed {
*const ptrsmax = ptrs + (_spectrum - 2)*sxyz;
T *ptrd = resc.data(x,y,z,0);
const unsigned int *poff = off._data;
- const float *pfoff = foff._data;
+ const double *pfoff = foff._data;
cimg_forC(resc,c) {
- const float
+ const double
t = *(pfoff++),
w0 = _cimg_lanczos(t + 2),
w1 = _cimg_lanczos(t + 1),
w2 = _cimg_lanczos(t),
w3 = _cimg_lanczos(t - 1),
- w4 = _cimg_lanczos(t - 2);
- const Tfloat
- val2 = (Tfloat)*ptrs,
- val1 = ptrs>=ptrsmin?(Tfloat)*(ptrs - sxyz):val2,
- val0 = ptrs>ptrsmin?(Tfloat)*(ptrs - 2*sxyz):val1,
- val3 = ptrs<=ptrsmax?(Tfloat)*(ptrs + sxyz):val2,
- val4 = ptrs<ptrsmax?(Tfloat)*(ptrs + 2*sxyz):val3,
+ w4 = _cimg_lanczos(t - 2),
+ val2 = (double)*ptrs,
+ val1 = ptrs>=ptrsmin?(double)*(ptrs - sxyz):val2,
+ val0 = ptrs>ptrsmin?(double)*(ptrs - 2*sxyz):val1,
+ val3 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val2,
+ val4 = ptrs<ptrsmax?(double)*(ptrs + 2*sxyz):val3,
val = (val0*w0 + val1*w1 + val2*w2 + val3*w3 + val4*w4)/(w1 + w2 + w3 + w4);
*ptrd = (T)(val<vmin?vmin:val>vmax?vmax:val);
ptrd+=sxyz;
@@ -28702,11 +29075,11 @@ namespace cimg_library_suffixed {
//! Permute axes order \newinstance.
CImg<T> get_permute_axes(const char *const order) const {
const T foo = (T)0;
- return _get_permute_axes(order,foo);
+ return _permute_axes(order,foo);
}
template<typename t>
- CImg<t> _get_permute_axes(const char *const permut, const t&) const {
+ CImg<t> _permute_axes(const char *const permut, const t&) const {
if (is_empty() || !permut) return CImg<t>(*this,false);
CImg<t> res;
const T* ptrs = _data;
@@ -31035,26 +31408,41 @@ namespace cimg_library_suffixed {
return get_correlate(kernel,boundary_conditions,is_normalized).move_to(*this);
}
- //! Correlate image by a kernel \newinstance.
template<typename t>
CImg<_cimg_Ttfloat> get_correlate(const CImg<t>& kernel, const unsigned int boundary_conditions=1,
const bool is_normalized=false) const {
+ return _correlate(kernel,boundary_conditions,is_normalized,false);
+ }
+
+ //! Correlate image by a kernel \newinstance.
+ template<typename t>
+ CImg<_cimg_Ttfloat> _correlate(const CImg<t>& kernel, const unsigned int boundary_conditions,
+ const bool is_normalized, const bool is_convolution) const {
if (is_empty() || !kernel) return *this;
typedef _cimg_Ttfloat Ttfloat;
CImg<Ttfloat> res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum));
cimg_abort_init;
if (boundary_conditions && kernel._width==kernel._height &&
((kernel._depth==1 && kernel._width<=5) || (kernel._depth==kernel._width && kernel._width<=3))) {
- // A special optimization is done for 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 kernel (with boundary_conditions=1)
+ // A special optimization is done for 2x2, 3x3, 4x4, 5x5, 2x2x2 and 3x3x3 kernel (with boundary_conditions=1).
+ CImg<t> _kernel;
+ if (is_convolution) { // Add empty column/row/slice to shift kernel center in case of convolution
+ const int dw = !(kernel.width()%2), dh = !(kernel.height()%2), dd = !(kernel.depth()%2);
+ if (dw || dh || dd)
+ kernel.get_resize(kernel.width() + dw,kernel.height() + dh,kernel.depth() + dd,-100,0,0).
+ move_to(_kernel);
+ }
+ if (!_kernel) _kernel = kernel.get_shared();
+
Ttfloat *ptrd = res._data;
CImg<T> I;
- switch (kernel._depth) {
+ switch (_kernel._depth) {
case 3 : {
I.assign(27);
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> _K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> _K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)_K.magnitude(2), M = _M*_M;
cimg_for3x3x3(_img,x,y,z,0,I,T) {
@@ -31094,7 +31482,7 @@ namespace cimg_library_suffixed {
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M;
cimg_for2x2x2(_img,x,y,z,0,I,T) {
@@ -31116,13 +31504,13 @@ namespace cimg_library_suffixed {
} break;
default :
case 1 :
- switch (kernel._width) {
+ switch (_kernel._width) {
case 6 : {
I.assign(36);
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M;
cimg_forZ(_img,z) cimg_for6x6(_img,x,y,z,0,I,T) {
@@ -31162,7 +31550,7 @@ namespace cimg_library_suffixed {
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M;
cimg_forZ(_img,z) cimg_for5x5(_img,x,y,z,0,I,T) {
@@ -31194,7 +31582,7 @@ namespace cimg_library_suffixed {
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M;
cimg_forZ(_img,z) cimg_for4x4(_img,x,y,z,0,I,T) {
@@ -31220,7 +31608,7 @@ namespace cimg_library_suffixed {
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M;
cimg_forZ(_img,z) cimg_for3x3(_img,x,y,z,0,I,T) {
@@ -31242,7 +31630,7 @@ namespace cimg_library_suffixed {
cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
if (is_normalized) {
const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M;
cimg_forZ(_img,z) cimg_for2x2(_img,x,y,z,0,I,T) {
@@ -31261,20 +31649,19 @@ namespace cimg_library_suffixed {
else cimg_forC(res,c) {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
- const CImg<t> K = kernel.get_shared_channel(c%kernel._spectrum);
+ const CImg<t> K = _kernel.get_shared_channel(c%_kernel._spectrum);
res.get_shared_channel(c).assign(_img)*=K[0];
}
break;
}
}
} else { // Generic version for other kernels and boundary conditions.
- const int
+ int
mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = kernel.depth()/2,
- mx1 = mx2 - 1 + (kernel.width()%2), my1 = my2 - 1 + (kernel.height()%2), mz1 = mz2 - 1 + (kernel.depth()%2),
+ mx1 = kernel.width() - mx2 - 1, my1 = kernel.height() - my2 - 1, mz1 = kernel.depth() - mz2 - 1;
+ if (is_convolution) cimg::swap(mx1,mx2,my1,my2,mz1,mz2); // Shift kernel center in case of convolution
+ const int
mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2;
-#if cimg_OS!=2
- cimg_pragma_openmp(parallel for cimg_openmp_if(res._spectrum>=2)) // (Isn't stable on Windows)
-#endif
cimg_forC(res,c) cimg_abort_try {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -31335,7 +31722,7 @@ namespace cimg_library_suffixed {
} cimg_abort_catch2()
} else { // Classical correlation.
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width*_height*_depth>=32768))
- for (int z = mz1; z<mze; ++z)
+ for (int z = mz1; z<mze; ++z)
for (int y = my1; y<mye; ++y)
for (int x = mx1; x<mxe; ++x) cimg_abort_try2 {
cimg_abort_test2();
@@ -31396,6 +31783,14 @@ namespace cimg_library_suffixed {
return get_convolve(kernel,boundary_conditions,is_normalized).move_to(*this);
}
+ //! Convolve image by a kernel \newinstance.
+ template<typename t>
+ CImg<_cimg_Ttfloat> get_convolve(const CImg<t>& kernel, const unsigned int boundary_conditions=1,
+ const bool is_normalized=false) const {
+ return _correlate(CImg<t>(kernel._data,kernel.size(),1,1,1,true).get_mirror('x').
+ resize(kernel,-1),boundary_conditions,is_normalized,true);
+ }
+
//! Cumulate image values, optionally along specified axis.
/**
\param axis Cumulation axis. Set it to 0 to cumulate all values globally without taking axes into account.
@@ -31465,20 +31860,11 @@ namespace cimg_library_suffixed {
return CImg<Tlong>(*this,false).cumulate(axes);
}
- //! Convolve image by a kernel \newinstance.
- template<typename t>
- CImg<_cimg_Ttfloat> get_convolve(const CImg<t>& kernel, const unsigned int boundary_conditions=1,
- const bool is_normalized=false) const {
- if (is_empty() || !kernel) return *this;
- return get_correlate(CImg<t>(kernel._data,kernel.size(),1,1,1,true).get_mirror('x').
- resize(kernel,-1),boundary_conditions,is_normalized);
- }
-
//! Erode image by a structuring element.
/**
\param kernel Structuring element.
\param boundary_conditions Boundary conditions.
- \param is_real Do the erosion in real mode (\c true) rather than binary mode (\c false).
+ \param is_real Do the erosion in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false).
**/
template<typename t>
CImg<T>& erode(const CImg<t>& kernel, const unsigned int boundary_conditions=1,
@@ -31497,12 +31883,9 @@ namespace cimg_library_suffixed {
CImg<Tt> res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum));
const int
mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = kernel.depth()/2,
- mx1 = mx2 - 1 + (kernel.width()%2), my1 = my2 - 1 + (kernel.height()%2), mz1 = mz2 - 1 + (kernel.depth()%2),
+ mx1 = kernel.width() - mx2 - 1, my1 = kernel.height() - my2 - 1, mz1 = kernel.depth() - mz2 - 1,
mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2;
cimg_abort_init;
-#if cimg_OS!=2
- cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) // (Isn't stable on Windows)
-#endif
cimg_forC(*this,c) cimg_abort_try {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -31517,7 +31900,7 @@ namespace cimg_library_suffixed {
for (int zm = -mz1; zm<=mz2; ++zm)
for (int ym = -my1; ym<=my2; ++ym)
for (int xm = -mx1; xm<=mx2; ++xm) {
- const t mval = K(mx2 - xm,my2 - ym,mz2 - zm);
+ const t mval = K(mx1 + xm,my1 + ym,mz1 + zm);
const Tt cval = (Tt)(_img(x + xm,y + ym,z + zm) - mval);
if (cval<min_val) min_val = cval;
}
@@ -31532,7 +31915,7 @@ namespace cimg_library_suffixed {
for (int zm = -mz1; zm<=mz2; ++zm)
for (int ym = -my1; ym<=my2; ++ym)
for (int xm = -mx1; xm<=mx2; ++xm) {
- const t mval = K(mx2 - xm,my2 - ym,mz2 - zm);
+ const t mval = K(mx1 + xm,my1 + ym,mz1 + zm);
const Tt cval = (Tt)(_img._atXYZ(x + xm,y + ym,z + zm) - mval);
if (cval<min_val) min_val = cval;
}
@@ -31548,7 +31931,7 @@ namespace cimg_library_suffixed {
for (int zm = -mz1; zm<=mz2; ++zm)
for (int ym = -my1; ym<=my2; ++ym)
for (int xm = -mx1; xm<=mx2; ++xm) {
- const t mval = K(mx2 - xm,my2 - ym,mz2 - zm);
+ const t mval = K(mx1 + xm,my1 + ym,mz1 + zm);
const Tt cval = (Tt)(_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) - mval);
if (cval<min_val) min_val = cval;
}
@@ -31566,7 +31949,7 @@ namespace cimg_library_suffixed {
for (int zm = -mz1; zm<=mz2; ++zm)
for (int ym = -my1; ym<=my2; ++ym)
for (int xm = -mx1; xm<=mx2; ++xm)
- if (K(mx2 - xm,my2 - ym,mz2 - zm)) {
+ if (K(mx1 + xm,my1 + ym,mz1 + zm)) {
const Tt cval = (Tt)_img(x + xm,y + ym,z + zm);
if (cval<min_val) min_val = cval;
}
@@ -31581,7 +31964,7 @@ namespace cimg_library_suffixed {
for (int zm = -mz1; zm<=mz2; ++zm)
for (int ym = -my1; ym<=my2; ++ym)
for (int xm = -mx1; xm<=mx2; ++xm)
- if (K(mx2 - xm,my2 - ym,mz2 - zm)) {
+ if (K(mx1 + xm,my1 + ym,mz1 + zm)) {
const T cval = (Tt)_img._atXYZ(x + xm,y + ym,z + zm);
if (cval<min_val) min_val = cval;
}
@@ -31597,7 +31980,7 @@ namespace cimg_library_suffixed {
for (int zm = -mz1; zm<=mz2; ++zm)
for (int ym = -my1; ym<=my2; ++ym)
for (int xm = -mx1; xm<=mx2; ++xm)
- if (K(mx2 - xm,my2 - ym,mz2 - zm)) {
+ if (K(mx1 + xm,my1 + ym,mz1 + zm)) {
const T cval = (Tt)_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0);
if (cval<min_val) min_val = cval;
}
@@ -31619,7 +32002,7 @@ namespace cimg_library_suffixed {
CImg<T>& erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) {
if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this;
if (sx>1 && _width>1) { // Along X-axis.
- const int L = width(), off = 1, s = (int)sx, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2;
+ const int L = width(), off = 1, s = (int)sx, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2;
CImg<T> buf(L);
cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288))
cimg_forYZC(*this,y,z,c) {
@@ -31659,7 +32042,7 @@ namespace cimg_library_suffixed {
}
if (sy>1 && _height>1) { // Along Y-axis.
- const int L = height(), off = width(), s = (int)sy, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1,
+ const int L = height(), off = width(), s = (int)sy, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1,
s2 = _s2>L?L:_s2;
CImg<T> buf(L);
cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288))
@@ -31701,7 +32084,7 @@ namespace cimg_library_suffixed {
}
if (sz>1 && _depth>1) { // Along Z-axis.
- const int L = depth(), off = width()*height(), s = (int)sz, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1,
+ const int L = depth(), off = width()*height(), s = (int)sz, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1,
s2 = _s2>L?L:_s2;
CImg<T> buf(L);
cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288))
@@ -31766,7 +32149,7 @@ namespace cimg_library_suffixed {
/**
\param kernel Structuring element.
\param boundary_conditions Boundary conditions.
- \param is_real Do the dilation in real mode (\c true) rather than binary mode (\c false).
+ \param is_real Do the dilation in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false).
**/
template<typename t>
CImg<T>& dilate(const CImg<t>& kernel, const unsigned int boundary_conditions=1,
@@ -31783,13 +32166,10 @@ namespace cimg_library_suffixed {
typedef _cimg_Tt Tt;
CImg<Tt> res(_width,_height,_depth,_spectrum);
const int
- mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = kernel.depth()/2,
- mx1 = mx2 - 1 + (kernel.width()%2), my1 = my2 - 1 + (kernel.height()%2), mz1 = mz2 - 1 + (kernel.depth()%2),
+ mx1 = kernel.width()/2, my1 = kernel.height()/2, mz1 = kernel.depth()/2,
+ mx2 = kernel.width() - mx1 - 1, my2 = kernel.height() - my1 - 1, mz2 = kernel.depth() - mz1 - 1,
mxe = width() - mx2, mye = height() - my2, mze = depth() - mz2;
cimg_abort_init;
-#if cimg_OS!=2
- cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) // (Isn't stable on Windows)
-#endif
cimg_forC(*this,c) cimg_abort_try {
cimg_abort_test();
const CImg<T> _img = get_shared_channel(c%_spectrum);
@@ -31905,7 +32285,7 @@ namespace cimg_library_suffixed {
CImg<T>& dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) {
if (is_empty() || (sx==1 && sy==1 && sz==1)) return *this;
if (sx>1 && _width>1) { // Along X-axis.
- const int L = width(), off = 1, s = (int)sx, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2;
+ const int L = width(), off = 1, s = (int)sx, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2;
CImg<T> buf(L);
cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288))
cimg_forYZC(*this,y,z,c) {
@@ -31946,7 +32326,7 @@ namespace cimg_library_suffixed {
}
if (sy>1 && _height>1) { // Along Y-axis.
- const int L = height(), off = width(), s = (int)sy, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1,
+ const int L = height(), off = width(), s = (int)sy, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1,
s2 = _s2>L?L:_s2;
CImg<T> buf(L);
cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288))
@@ -31988,7 +32368,7 @@ namespace cimg_library_suffixed {
}
if (sz>1 && _depth>1) { // Along Z-axis.
- const int L = depth(), off = width()*height(), s = (int)sz, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1,
+ const int L = depth(), off = width()*height(), s = (int)sz, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1,
s2 = _s2>L?L:_s2;
CImg<T> buf(L);
cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288))
@@ -33570,7 +33950,7 @@ namespace cimg_library_suffixed {
CImg<T> res(_width,_height,_depth,_spectrum);
T *ptrd = res._data;
cimg::unused(ptrd);
- const int hl = (int)n/2, hr = hl - 1 + (int)n%2;
+ const int hr = (int)n/2, hl = n - hr - 1;
if (res._depth!=1) { // 3d
if (threshold>0)
cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=16 && _height*_depth*_spectrum>=4))
@@ -34668,9 +35048,9 @@ namespace cimg_library_suffixed {
const unsigned int nb_randoms,
const CImg<t1> &guide,
CImg<t2> &matching_score) const {
- return _get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
- nb_iterations,nb_randoms,
- guide,true,matching_score);
+ return _patchmatch(patch_image,patch_width,patch_height,patch_depth,
+ nb_iterations,nb_randoms,
+ guide,true,matching_score);
}
//! Compute correspondence map between two images, using the patch-match algorithm \overloading.
@@ -34695,9 +35075,9 @@ namespace cimg_library_suffixed {
const unsigned int nb_iterations,
const unsigned int nb_randoms,
const CImg<t> &guide) const {
- return _get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
- nb_iterations,nb_randoms,
- guide,false,CImg<T>::empty());
+ return _patchmatch(patch_image,patch_width,patch_height,patch_depth,
+ nb_iterations,nb_randoms,
+ guide,false,CImg<T>::empty());
}
//! Compute correspondence map between two images, using the patch-match algorithm \overloading.
@@ -34718,22 +35098,22 @@ namespace cimg_library_suffixed {
const unsigned int patch_depth=1,
const unsigned int nb_iterations=5,
const unsigned int nb_randoms=5) const {
- return _get_patchmatch(patch_image,patch_width,patch_height,patch_depth,
- nb_iterations,nb_randoms,
- CImg<T>::const_empty(),
- false,CImg<T>::empty());
+ return _patchmatch(patch_image,patch_width,patch_height,patch_depth,
+ nb_iterations,nb_randoms,
+ CImg<T>::const_empty(),
+ false,CImg<T>::empty());
}
template<typename t1, typename t2>
- CImg<intT> _get_patchmatch(const CImg<T>& patch_image,
- const unsigned int patch_width,
- const unsigned int patch_height,
- const unsigned int patch_depth,
- const unsigned int nb_iterations,
- const unsigned int nb_randoms,
- const CImg<t1> &guide,
- const bool is_matching_score,
- CImg<t2> &matching_score) const {
+ CImg<intT> _patchmatch(const CImg<T>& patch_image,
+ const unsigned int patch_width,
+ const unsigned int patch_height,
+ const unsigned int patch_depth,
+ const unsigned int nb_iterations,
+ const unsigned int nb_randoms,
+ const CImg<t1> &guide,
+ const bool is_matching_score,
+ CImg<t2> &matching_score) const {
if (is_empty()) return CImg<intT>::const_empty();
if (patch_image._spectrum!=_spectrum)
throw CImgArgumentException(_cimg_instance
@@ -41389,12 +41769,11 @@ namespace cimg_library_suffixed {
const int x1, const int y1, const int z1, const int c1,
const T val, const float opacity=1) {
if (is_empty()) return *this;
- const bool bx = (x0<x1), by = (y0<y1), bz = (z0<z1), bc = (c0<c1);
const int
- nx0 = bx?x0:x1, nx1 = bx?x1:x0,
- ny0 = by?y0:y1, ny1 = by?y1:y0,
- nz0 = bz?z0:z1, nz1 = bz?z1:z0,
- nc0 = bc?c0:c1, nc1 = bc?c1:c0;
+ nx0 = x0<x1?x0:x1, nx1 = x0^x1^nx0,
+ ny0 = y0<y1?y0:y1, ny1 = y0^y1^ny0,
+ nz0 = z0<z1?z0:z1, nz1 = z0^z1^nz0,
+ nc0 = c0<c1?c0:c1, nc1 = c0^c1^nc0;
const int
lX = (1 + nx1 - nx0) + (nx1>=width()?width() - 1 - nx1:0) + (nx0<0?nx0:0),
lY = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0),
@@ -41491,10 +41870,9 @@ namespace cimg_library_suffixed {
if (is_empty()) return *this;
if (y0==y1) return draw_line(x0,y0,x1,y0,color,opacity,pattern,true);
if (x0==x1) return draw_line(x0,y0,x0,y1,color,opacity,pattern,true);
- const bool bx = (x0<x1), by = (y0<y1);
const int
- nx0 = bx?x0:x1, nx1 = bx?x1:x0,
- ny0 = by?y0:y1, ny1 = by?y1:y0;
+ nx0 = x0<x1?x0:x1, nx1 = x0^x1^nx0,
+ ny0 = y0<y1?y0:y1, ny1 = y0^y1^ny0;
if (ny1==ny0 + 1) return draw_line(nx0,ny0,nx1,ny0,color,opacity,pattern,true).
draw_line(nx1,ny1,nx0,ny1,color,opacity,pattern,false);
return draw_line(nx0,ny0,nx1,ny0,color,opacity,pattern,true).
@@ -44642,7 +45020,7 @@ namespace cimg_library_suffixed {
CImg<intT> get_select(CImgDisplay &disp,
const unsigned int feature_type=2, unsigned int *const XYZ=0,
const bool exit_on_anykey=false) const {
- return _get_select(disp,0,feature_type,XYZ,0,0,0,exit_on_anykey,true,false);
+ return _select(disp,0,feature_type,XYZ,0,0,0,exit_on_anykey,true,false);
}
//! Simple interface to select a shape from an image \newinstance.
@@ -44650,15 +45028,15 @@ namespace cimg_library_suffixed {
const unsigned int feature_type=2, unsigned int *const XYZ=0,
const bool exit_on_anykey=false) const {
CImgDisplay disp;
- return _get_select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false);
+ return _select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false);
}
- CImg<intT> _get_select(CImgDisplay &disp, const char *const title,
- const unsigned int feature_type, unsigned int *const XYZ,
- const int origX, const int origY, const int origZ,
- const bool exit_on_anykey,
- const bool reset_view3d,
- const bool force_display_z_coord) const {
+ CImg<intT> _select(CImgDisplay &disp, const char *const title,
+ const unsigned int feature_type, unsigned int *const XYZ,
+ const int origX, const int origY, const int origZ,
+ const bool exit_on_anykey,
+ const bool reset_view3d,
+ const bool force_display_z_coord) const {
if (is_empty()) return CImg<intT>(1,feature_type==0?3:6,1,1,-1);
if (!disp) {
disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1);
@@ -45142,7 +45520,7 @@ namespace cimg_library_suffixed {
else cimg_snprintf(text,text._width," Point (%d,%d) = [ ",origX + (int)X,origY + (int)Y);
char *ctext = text._data + std::strlen(text), *const ltext = text._data + 512;
for (unsigned int c = 0; c<_spectrum && ctext<ltext; ++c) {
- cimg_snprintf(ctext,text._width/2,cimg::type<T>::format(),
+ cimg_snprintf(ctext,text._width/2,cimg::type<T>::format_s(),
cimg::type<T>::format((*this)((int)X,(int)Y,(int)Z,c)));
ctext = text._data + std::strlen(text);
*(ctext++) = ' '; *ctext = 0;
@@ -45891,7 +46269,7 @@ namespace cimg_library_suffixed {
if (header_size>40) cimg::fseek(nfile,header_size - 40,SEEK_CUR);
const int
- dx_bytes = (bpp==1)?(dx/8 + (dx%8?1:0)):((bpp==4)?(dx/2 + (dx%2?1:0)):(dx*bpp/8)),
+ dx_bytes = (bpp==1)?(dx/8 + (dx%8?1:0)):((bpp==4)?(dx/2 + (dx%2)):(dx*bpp/8)),
align_bytes = (4 - dx_bytes%4)%4;
const longT
cimg_iobuffer = (longT)24*1024*1024,
@@ -48702,6 +49080,7 @@ namespace cimg_library_suffixed {
\param display_stats Tells to compute and display image statistics.
**/
const CImg<T>& print(const char *const title=0, const bool display_stats=true) const {
+
int xm = 0, ym = 0, zm = 0, vm = 0, xM = 0, yM = 0, zM = 0, vM = 0;
CImg<doubleT> st;
if (!is_empty() && display_stats) {
@@ -48709,6 +49088,7 @@ namespace cimg_library_suffixed {
xm = (int)st[4]; ym = (int)st[5], zm = (int)st[6], vm = (int)st[7];
xM = (int)st[8]; yM = (int)st[9], zM = (int)st[10], vM = (int)st[11];
}
+
const ulongT siz = size(), msiz = siz*sizeof(T), siz1 = siz - 1,
mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U, width1 = _width - 1;
@@ -48719,7 +49099,7 @@ namespace cimg_library_suffixed {
cimg::t_magenta,cimg::t_bold,title?title:_title._data,cimg::t_normal,
cimg::t_bold,cimg::t_normal,(void*)this,
cimg::t_bold,cimg::t_normal,_width,_height,_depth,_spectrum,
- mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20)),
+ (unsigned long)(mdisp==0?msiz:(mdisp==1?(msiz>>10):(msiz>>20))),
mdisp==0?"b":(mdisp==1?"Kio":"Mio"),
cimg::t_bold,cimg::t_normal,pixel_type(),(void*)begin());
if (_data)
@@ -48727,7 +49107,7 @@ namespace cimg_library_suffixed {
else std::fprintf(cimg::output()," (%s) = [ ",_is_shared?"shared":"non-shared");
if (!is_empty()) cimg_foroff(*this,off) {
- std::fprintf(cimg::output(),cimg::type<T>::format(),cimg::type<T>::format(_data[off]));
+ std::fprintf(cimg::output(),"%g",(double)_data[off]);
if (off!=siz1) std::fprintf(cimg::output(),"%s",off%_width==width1?" ; ":" ");
if (off==7 && siz>16) { off = siz1 - 8; std::fprintf(cimg::output(),"... "); }
}
@@ -48811,7 +49191,6 @@ namespace cimg_library_suffixed {
} else zoom = get_crop(x0,y0,z0,x1,y1,z1);
const CImg<T>& visu = zoom?zoom:*this;
-
const unsigned int
dx = 1U + x1 - x0, dy = 1U + y1 - y0, dz = 1U + z1 - z0,
tw = dx + (dz>1?dz:0U), th = dy + (dz>1?dz:0U);
@@ -48842,7 +49221,7 @@ namespace cimg_library_suffixed {
}
disp._mouse_x = old_mouse_x; disp._mouse_y = old_mouse_y;
- const CImg<intT> selection = visu._get_select(disp,0,2,_XYZ,x0,y0,z0,true,is_first_select,_depth>1);
+ const CImg<intT> selection = visu._select(disp,0,2,_XYZ,x0,y0,z0,true,is_first_select,_depth>1);
old_mouse_x = disp._mouse_x; old_mouse_y = disp._mouse_y;
is_first_select = false;
@@ -49920,7 +50299,7 @@ namespace cimg_library_suffixed {
std::fprintf(nfile,"%u %u %u %u\n",_width,_height,_depth,_spectrum);
const T* ptrs = _data;
cimg_forYZC(*this,y,z,c) {
- cimg_forX(*this,x) std::fprintf(nfile,"%.16g ",(double)*(ptrs++));
+ cimg_forX(*this,x) std::fprintf(nfile,"%.17g ",(double)*(ptrs++));
std::fputc('\n',nfile);
}
if (!file) cimg::fclose(nfile);
@@ -49997,7 +50376,7 @@ namespace cimg_library_suffixed {
std::FILE *const nfile = file?file:cimg::fopen(filename,"w");
const T* ptrs = _data;
cimg_forYZC(*this,y,z,c) {
- cimg_forX(*this,x) std::fprintf(nfile,"%.16g%s",(double)*(ptrs++),(x==width() - 1)?"":",");
+ cimg_forX(*this,x) std::fprintf(nfile,"%.17g%s",(double)*(ptrs++),(x==width() - 1)?"":",");
std::fputc('\n',nfile);
}
if (!file) cimg::fclose(nfile);
@@ -54370,7 +54749,7 @@ namespace cimg_library_suffixed {
CImg<intT> get_select(CImgDisplay &disp, const bool feature_type=true,
const char axis='x', const float align=0,
const bool exit_on_anykey=false) const {
- return _get_select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false);
+ return _select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false);
}
//! Display a simple interactive interface to select images or sublists.
@@ -54385,13 +54764,13 @@ namespace cimg_library_suffixed {
const char axis='x', const float align=0,
const bool exit_on_anykey=false) const {
CImgDisplay disp;
- return _get_select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false);
+ return _select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false);
}
- CImg<intT> _get_select(CImgDisplay &disp, const char *const title, const bool feature_type,
- const char axis, const float align, const bool exit_on_anykey,
- const unsigned int orig, const bool resize_disp,
- const bool exit_on_rightbutton, const bool exit_on_wheel) const {
+ CImg<intT> _select(CImgDisplay &disp, const char *const title, const bool feature_type,
+ const char axis, const float align, const bool exit_on_anykey,
+ const unsigned int orig, const bool resize_disp,
+ const bool exit_on_rightbutton, const bool exit_on_wheel) const {
if (is_empty())
throw CImgInstanceException(_cimglist_instance
"select(): Empty instance.",
@@ -54841,7 +55220,7 @@ namespace cimg_library_suffixed {
CImg<charT> tmp(256), str_pixeltype(256), str_endian(256);
*tmp = *str_pixeltype = *str_endian = 0;
unsigned int j, N = 0, W, H, D, C;
- ulongT csiz;
+ unsigned long csiz;
int i, err;
do {
j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0;
@@ -55890,7 +56269,7 @@ namespace cimg_library_suffixed {
} else {
bool disp_resize = !is_first_call;
while (!disp.is_closed() && !is_exit) {
- const CImg<intT> s = _get_select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true);
+ const CImg<intT> s = _select(disp,0,true,axis,align,exit_on_anykey,orig,disp_resize,!is_first_call,true);
disp_resize = true;
if (s[0]<0 && !disp.wheel()) { // No selections done.
if (disp.button()&2) { disp.flush(); break; }
@@ -58057,7 +58436,7 @@ namespace cimg {
inline const char *strbuffersize(const cimg_ulong size) {
static CImg<char> res(256);
cimg::mutex(5);
- if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",size,size>1?"s":"");
+ if (size<1024LU) cimg_snprintf(res,res._width,"%lu byte%s",(unsigned long)size,size>1?"s":"");
else if (size<1024*1024LU) { const float nsize = size/1024.0f; cimg_snprintf(res,res._width,"%.1f Kio",nsize); }
else if (size<1024*1024*1024LU) {
const float nsize = size/(1024*1024.0f); cimg_snprintf(res,res._width,"%.1f Mio",nsize);
diff --git a/examples/CImg_demo.cpp b/examples/CImg_demo.cpp
index 08b77ff..b9f4218 100644
--- a/examples/CImg_demo.cpp
+++ b/examples/CImg_demo.cpp
@@ -868,7 +868,7 @@ void* item_blobs_editor() {
for (unsigned int x = x0; x<=x1; ++x) {
float dist = dx*dx + dy*dy;
if (dist<precision) {
- const float val = (float)exp(-dist/sigma2);
+ const float val = (float)std::exp(-dist/sigma2);
*ptr+=(unsigned int)(val*col1);
*(ptr + wh)+=(unsigned int)(val*col2);
*(ptr + 2*wh)+=(unsigned int)(val*col3);
diff --git a/examples/edge_explorer2d.cpp b/examples/edge_explorer2d.cpp
index b8188f8..7e620c4 100644
--- a/examples/edge_explorer2d.cpp
+++ b/examples/edge_explorer2d.cpp
@@ -133,13 +133,13 @@ int main(int argc, char** argv) {
// s corresponds to the x-ordinate of the pixel while t corresponds to the y-ordinate.
if ( 1 <= s && s <= visu_bw.width() - 1 && 1 <= t && t <=visu_bw.height() - 1) { // if - good points
double
- Gs = grad[0](s,t), //
- Gt = grad[1](s,t), // The actual pixel is (s,t)
- Gst = cimg::abs(Gs) + cimg::abs(Gt), //
+ Gs = grad[0](s,t), //
+ Gt = grad[1](s,t), // The actual pixel is (s,t)
+ Gst = cimg::abs(Gs) + cimg::abs(Gt), //
// ^-- For efficient computation we observe that |Gs|+ |Gt| ~=~ sqrt( Gs^2 + Gt^2)
Gr, Gur, Gu, Gul, Gl, Gdl, Gd, Gdr;
// ^-- right, up right, up, up left, left, down left, down, down right.
- double theta = std::atan2(Gt,Gs) + pi; // theta is from the interval [0,Pi]
+ double theta = std::atan2(std::max(1e-8,Gt),Gs) + pi; // theta is from the interval [0,Pi]
switch(mode) {
case 1: // Hysterese is applied
if (Gst>=thresH) { edge.draw_point(s,t,black); }
diff --git a/html/header.html b/html/header.html
index af71d0d..73b0d5f 100644
--- a/html/header.html
+++ b/html/header.html
@@ -47,8 +47,8 @@
</center>
<center><font size="-1" color="#777777">
Latest stable version: <b><a href="http://cimg.eu/files">1.7.8</a></b>
- <!-- - -->
- <!-- Development snapshot: <b><a href="http://cimg.eu/files">1.7.9_pre</a></b> -->
+ -
+ Development snapshot: <b><a href="http://cimg.eu/files">1.7.9_pre</a></b>
</font></center>
</td></tr>
<tr bgcolor="#FFFFFF"><td><hr noshade size="1" style="border-top: 1px solid #ccc;"/></td></tr>
diff --git a/html/header_reference.html b/html/header_reference.html
index 7717d96..a13c005 100644
--- a/html/header_reference.html
+++ b/html/header_reference.html
@@ -46,8 +46,8 @@
</center>
<center><font size="-1" color="#777777">
Latest stable version: <b><a href="http://cimg.eu/files">1.7.8</a></b>
- <!-- - -->
- <!-- Development snapshot: <b><a href="http://cimg.eu/files">1.7.8_pre</a></b> -->
+ -
+ Development snapshot: <b><a href="http://cimg.eu/files">1.7.8_pre</a></b>
</font></center>
</td></tr>
<tr bgcolor="#FFFFFF"><td><hr noshade size="1" style="border-top: 1px solid #ccc;"/></td></tr>
diff --git a/html/img/CImgLogo2.jpg b/html/img/CImgLogo2.jpg
index a8586b2..0a6927b 100644
Binary files a/html/img/CImgLogo2.jpg and b/html/img/CImgLogo2.jpg differ
diff --git a/html/img/postcard65.jpg b/html/img/postcard65.jpg
new file mode 100644
index 0000000..a5eef4e
Binary files /dev/null and b/html/img/postcard65.jpg differ
diff --git a/html/index.shtml b/html/index.shtml
index 48cecdf..332107d 100644
--- a/html/index.shtml
+++ b/html/index.shtml
@@ -250,7 +250,7 @@
or parts of the <a href="reference/index.html">documentation</a>.</li>
<li>If you just want to say you've been happy with the library, you can send me a postcard from your place, to the following address : <br/>
<i>David Tschumperlé, GREYC (UMR CNRS 6072), Equipe IMAGE, 6 Bd du Maréchal Juin, 14050 Caen Cedex, FRANCE.</i><br/><br/>
- 63 postcards received yet (I still have empty space on my wall ! :) ), from :<br/><br/>
+ 65 postcards received yet (I still have empty space on my wall ! :) ), from :<br/><br/>
<ul>
<li><a href="img/postcard1.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
Comissao Nacional de Energia Nuclear, Rio de Janeiro, Brazil.</a></li>
@@ -378,6 +378,9 @@
Konstanz/Germany, from Sébastien Fourey.</a></li>
<li><a href="img/postcard64.jpg" onclick="NewWindow(this.href,'name','320','420','yes');return false;">
Bilbao/Spain, from Patrick Wauters.</a></li>
+ <li><a href="img/postcard65.jpg" onclick="NewWindow(this.href,'name','420','320','yes');return false;">
+ Haldern/Germany, from Volker Doebel.</a></li>
+
<br/><br/></li>
</ul></li>
</ul>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/cimg.git
More information about the debian-science-commits
mailing list