From c5ff78d0a9cdd68dfbcf86f9fc19aa15b8b0324c Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Fri, 18 Aug 2023 11:45:05 +0200 Subject: [PATCH 1/4] . --- CImg.h | 418 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 212 insertions(+), 206 deletions(-) diff --git a/CImg.h b/CImg.h index c237b210..25964c29 100644 --- a/CImg.h +++ b/CImg.h @@ -36937,224 +36937,230 @@ namespace cimg_library { return _permute_axes(axes_order,foo); } + unsigned int __permute_axes(const char *const axes_order) const { // Convert axes to integer code + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { }; + bool is_error = false; + if (axes_order) for (unsigned int l = 0; axes_order[l]; ++l) { + int c = cimg::lowercase(axes_order[l]); + if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { is_error = true; break; } + else { ++n_code[c%=4]; s_code[l] = (unsigned char)c; } + } + is_error|=(*n_code>1) || (n_code[1]>1) || (n_code[2]>1) || (n_code[3]>1); + if (is_error) + throw CImgArgumentException(_cimg_instance + "permute_axes(): Invalid specified axes order '%s'.", + cimg_instance, + axes_order); + return (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + } + template CImg _permute_axes(const char *const axes_order, const t&) const { if (is_empty() || !axes_order) return CImg(*this,false); - CImg res; + const unsigned code = __permute_axes(axes_order); const T* ptrs = _data; - unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = {}; - for (unsigned int l = 0; axes_order[l]; ++l) { - int c = cimg::lowercase(axes_order[l]); - if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { *s_code = 4; break; } - else { ++n_code[c%=4]; s_code[l] = (unsigned char)c; } - } - if (*axes_order && *s_code<4 && *n_code<=1 && n_code[1]<=1 && n_code[2]<=1 && n_code[3]<=1) { - const unsigned int code = (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); - ulongT wh, whd; - switch (code) { - case 0x0123 : // xyzc - return +*this; - case 0x0132 : // xycz - res.assign(_width,_height,_spectrum,_depth); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++); - break; - case 0x0213 : // xzyc - res.assign(_width,_depth,_height,_spectrum); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++); - break; - case 0x0231 : // xzcy - res.assign(_width,_depth,_spectrum,_height); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++); - break; - case 0x0312 : // xcyz - res.assign(_width,_spectrum,_height,_depth); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++); - break; - case 0x0321 : // xczy - res.assign(_width,_spectrum,_depth,_height); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++); - break; - case 0x1023 : // yxzc - res.assign(_height,_width,_depth,_spectrum); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++); - break; - case 0x1032 : // yxcz - res.assign(_height,_width,_spectrum,_depth); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++); - break; - case 0x1203 : // yzxc - res.assign(_height,_depth,_width,_spectrum); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++); - break; - case 0x1230 : // yzcx - res.assign(_height,_depth,_spectrum,_width); - switch (_width) { - case 1 : { - t *ptr_r = res.data(0,0,0,0); - for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { - *(ptr_r++) = (t)*(ptrs++); - } - } break; - case 2 : { - t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1); - for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { - *(ptr_r++) = (t)ptrs[0]; - *(ptr_g++) = (t)ptrs[1]; - ptrs+=2; - } - } break; - case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB - t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2); - for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { - *(ptr_r++) = (t)ptrs[0]; - *(ptr_g++) = (t)ptrs[1]; - *(ptr_b++) = (t)ptrs[2]; - ptrs+=3; - } - } break; - case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA - t - *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), - *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3); - for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { - *(ptr_r++) = (t)ptrs[0]; - *(ptr_g++) = (t)ptrs[1]; - *(ptr_b++) = (t)ptrs[2]; - *(ptr_a++) = (t)ptrs[3]; - ptrs+=4; - } - } break; - default : { - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++); - return res; + ulongT wh, whd; + CImg res; + + switch (code) { + case 0x0123 : // xyzc + return +*this; + case 0x0132 : // xycz + res.assign(_width,_height,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,y,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0213 : // xzyc + res.assign(_width,_depth,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x0231 : // xzcy + res.assign(_width,_depth,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,z,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x0312 : // xcyz + res.assign(_width,_spectrum,_height,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,y,z,wh,whd) = (t)*(ptrs++); + break; + case 0x0321 : // xczy + res.assign(_width,_spectrum,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(x,c,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x1023 : // yxzc + res.assign(_height,_width,_depth,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,z,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1032 : // yxcz + res.assign(_height,_width,_spectrum,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,x,c,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1203 : // yzxc + res.assign(_height,_depth,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,z,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x1230 : // yzcx + res.assign(_height,_depth,_spectrum,_width); + switch (_width) { + case 1 : { + t *ptr_r = res.data(0,0,0,0); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)*(ptrs++); } + } break; + case 2 : { + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + ptrs+=2; } - break; - case 0x1302 : // ycxz - res.assign(_height,_spectrum,_width,_depth); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++); - break; - case 0x1320 : // yczx - res.assign(_height,_spectrum,_depth,_width); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++); - break; - case 0x2013 : // zxyc - res.assign(_depth,_width,_height,_spectrum); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++); - break; - case 0x2031 : // zxcy - res.assign(_depth,_width,_spectrum,_height); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++); - break; - case 0x2103 : // zyxc - res.assign(_depth,_height,_width,_spectrum); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++); - break; - case 0x2130 : // zycx - res.assign(_depth,_height,_spectrum,_width); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++); - break; - case 0x2301 : // zcxy - res.assign(_depth,_spectrum,_width,_height); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++); - break; - case 0x2310 : // zcyx - res.assign(_depth,_spectrum,_height,_width); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++); - break; - case 0x3012 : // cxyz - res.assign(_spectrum,_width,_height,_depth); - switch (_spectrum) { - case 1 : { - const T *ptr_r = data(0,0,0,0); - t *ptrd = res._data; - for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++); - } break; - case 2 : { - const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1); - t *ptrd = res._data; - for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { - ptrd[0] = (t)*(ptr_r++); - ptrd[1] = (t)*(ptr_g++); - ptrd+=2; - } - } break; - case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB - const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); - t *ptrd = res._data; - for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { - ptrd[0] = (t)*(ptr_r++); - ptrd[1] = (t)*(ptr_g++); - ptrd[2] = (t)*(ptr_b++); - ptrd+=3; - } - } break; - case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA - const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); - t *ptrd = res._data; - for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { - ptrd[0] = (t)*(ptr_r++); - ptrd[1] = (t)*(ptr_g++); - ptrd[2] = (t)*(ptr_b++); - ptrd[3] = (t)*(ptr_a++); - ptrd+=4; - } - } break; - default : { - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++); + } break; + case 3 : { // Optimization for the classical conversion from interleaved RGB to planar RGB + t *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), *ptr_b = res.data(0,0,0,2); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + ptrs+=3; } + } break; + case 4 : { // Optimization for the classical conversion from interleaved RGBA to planar RGBA + t + *ptr_r = res.data(0,0,0,0), *ptr_g = res.data(0,0,0,1), + *ptr_b = res.data(0,0,0,2), *ptr_a = res.data(0,0,0,3); + for (unsigned int siz = _height*_depth*_spectrum; siz; --siz) { + *(ptr_r++) = (t)ptrs[0]; + *(ptr_g++) = (t)ptrs[1]; + *(ptr_b++) = (t)ptrs[2]; + *(ptr_a++) = (t)ptrs[3]; + ptrs+=4; } - break; - case 0x3021 : // cxzy - res.assign(_spectrum,_width,_depth,_height); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++); - break; - case 0x3102 : // cyxz - res.assign(_spectrum,_height,_width,_depth); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++); - break; - case 0x3120 : // cyzx - res.assign(_spectrum,_height,_depth,_width); - wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++); - break; - case 0x3201 : // czxy - res.assign(_spectrum,_depth,_width,_height); + } break; + default : { wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++); - break; - case 0x3210 : // czyx - res.assign(_spectrum,_depth,_height,_width); + cimg_forXYZC(*this,x,y,z,c) res(y,z,c,x,wh,whd) = *(ptrs++); + return res; + } + } + break; + case 0x1302 : // ycxz + res.assign(_height,_spectrum,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x1320 : // yczx + res.assign(_height,_spectrum,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(y,c,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2013 : // zxyc + res.assign(_depth,_width,_height,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,y,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2031 : // zxcy + res.assign(_depth,_width,_spectrum,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,x,c,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2103 : // zyxc + res.assign(_depth,_height,_width,_spectrum); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,x,c,wh,whd) = (t)*(ptrs++); + break; + case 0x2130 : // zycx + res.assign(_depth,_height,_spectrum,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,y,c,x,wh,whd) = (t)*(ptrs++); + break; + case 0x2301 : // zcxy + res.assign(_depth,_spectrum,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x2310 : // zcyx + res.assign(_depth,_spectrum,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(z,c,y,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3012 : // cxyz + res.assign(_spectrum,_width,_height,_depth); + switch (_spectrum) { + case 1 : { + const T *ptr_r = data(0,0,0,0); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) *(ptrd++) = (t)*(ptr_r++); + } break; + case 2 : { + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd+=2; + } + } break; + case 3 : { // Optimization for the classical conversion from planar RGB to interleaved RGB + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd+=3; + } + } break; + case 4 : { // Optimization for the classical conversion from planar RGBA to interleaved RGBA + const T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3); + t *ptrd = res._data; + for (ulongT siz = (ulongT)_width*_height*_depth; siz; --siz) { + ptrd[0] = (t)*(ptr_r++); + ptrd[1] = (t)*(ptr_g++); + ptrd[2] = (t)*(ptr_b++); + ptrd[3] = (t)*(ptr_a++); + ptrd+=4; + } + } break; + default : { wh = (ulongT)res._width*res._height; whd = wh*res._depth; - cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++); - break; + cimg_forXYZC(*this,x,y,z,c) res(c,x,y,z,wh,whd) = (t)*(ptrs++); + } } + break; + case 0x3021 : // cxzy + res.assign(_spectrum,_width,_depth,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,x,z,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3102 : // cyxz + res.assign(_spectrum,_height,_width,_depth); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,x,z,wh,whd) = (t)*(ptrs++); + break; + case 0x3120 : // cyzx + res.assign(_spectrum,_height,_depth,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,y,z,x,wh,whd) = (t)*(ptrs++); + break; + case 0x3201 : // czxy + res.assign(_spectrum,_depth,_width,_height); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,x,y,wh,whd) = (t)*(ptrs++); + break; + case 0x3210 : // czyx + res.assign(_spectrum,_depth,_height,_width); + wh = (ulongT)res._width*res._height; whd = wh*res._depth; + cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++); + break; } - if (!res) - throw CImgArgumentException(_cimg_instance - "permute_axes(): Invalid specified axes order '%s'.", - cimg_instance, - axes_order); + return res; } From 86d96b213d2bcfe274e8527ea9b6c94ff498aab6 Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Fri, 18 Aug 2023 12:48:39 +0200 Subject: [PATCH 2/4] . --- CImg.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CImg.h b/CImg.h index 25964c29..84b4af52 100644 --- a/CImg.h +++ b/CImg.h @@ -36937,32 +36937,32 @@ namespace cimg_library { return _permute_axes(axes_order,foo); } - unsigned int __permute_axes(const char *const axes_order) const { // Convert axes to integer code - unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { }; + unsigned int __permute_axes(const char *const axes_order) const { // Convert axes to integer case number + unsigned char s_axes[4] = { 0,1,2,3 }, n_axes[4] = { }; bool is_error = false; if (axes_order) for (unsigned int l = 0; axes_order[l]; ++l) { int c = cimg::lowercase(axes_order[l]); if (l>=4 || (c!='x' && c!='y' && c!='z' && c!='c')) { is_error = true; break; } - else { ++n_code[c%=4]; s_code[l] = (unsigned char)c; } + else { ++n_axes[c%=4]; s_axes[l] = (unsigned char)c; } } - is_error|=(*n_code>1) || (n_code[1]>1) || (n_code[2]>1) || (n_code[3]>1); + is_error|=(*n_axes>1) || (n_axes[1]>1) || (n_axes[2]>1) || (n_axes[3]>1); if (is_error) throw CImgArgumentException(_cimg_instance "permute_axes(): Invalid specified axes order '%s'.", cimg_instance, axes_order); - return (s_code[0]<<12) | (s_code[1]<<8) | (s_code[2]<<4) | (s_code[3]); + return (s_axes[0]<<12) | (s_axes[1]<<8) | (s_axes[2]<<4) | (s_axes[3]); } template CImg _permute_axes(const char *const axes_order, const t&) const { if (is_empty() || !axes_order) return CImg(*this,false); - const unsigned code = __permute_axes(axes_order); + const unsigned uicase = __permute_axes(axes_order); const T* ptrs = _data; ulongT wh, whd; CImg res; - switch (code) { + switch (uicase) { case 0x0123 : // xyzc return +*this; case 0x0132 : // xycz From 9f000af299bb1013ec3e96a910b872501b6393b5 Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Fri, 18 Aug 2023 14:14:01 +0200 Subject: [PATCH 3/4] CImg::permute_axes(): Detect particular cases that can be optimized. --- CImg.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/CImg.h b/CImg.h index 84b4af52..5f4b7e86 100644 --- a/CImg.h +++ b/CImg.h @@ -36928,6 +36928,17 @@ namespace cimg_library { This function permutes image content regarding the specified axes permutation. **/ CImg& permute_axes(const char *const axes_order) { + if (is_empty() || !axes_order) return *this; + const unsigned uicase = _permute_axes_uicase(axes_order); + if (_permute_axes_is_optim(uicase)) { // Data layout allow to do nothing but set the new dimensions + CImg res(*this,true); + for (unsigned int i = 0; i<4; ++i) { + const unsigned int axis = (uicase>>(4*(3 - i)))&15, value = !axis?_width:axis==1?_height:axis==2?_depth:_spectrum; + if (!i) res._width = value; else if (i==1) res._height = value; else if (i==2) res._depth = value; else res._spectrum = value; + } + _width = res._width; _height = res._height; _depth = res._depth; _spectrum = res._spectrum; + return *this; + } return get_permute_axes(axes_order).move_to(*this); } @@ -36937,7 +36948,7 @@ namespace cimg_library { return _permute_axes(axes_order,foo); } - unsigned int __permute_axes(const char *const axes_order) const { // Convert axes to integer case number + unsigned int _permute_axes_uicase(const char *const axes_order) const { // Convert axes to integer case number unsigned char s_axes[4] = { 0,1,2,3 }, n_axes[4] = { }; bool is_error = false; if (axes_order) for (unsigned int l = 0; axes_order[l]; ++l) { @@ -36954,13 +36965,54 @@ namespace cimg_library { return (s_axes[0]<<12) | (s_axes[1]<<8) | (s_axes[2]<<4) | (s_axes[3]); } + bool _permute_axes_is_optim(const unsigned int uicase) const { // Determine cases where nothing has to be done + const unsigned int co = ((_width>1)<<3)|((_height>1)<<2)|((_depth>1)<<1)|(_spectrum>1); + if (co<=2 || uicase==0x0123) return true; + switch (uicase) { + case (0x0132) : if ((co>=4 && co<=6) || (co>=8 && co<=10) || (co>=12 && co<=14)) return true; break; + case (0x0213) : if ((co>=3 && co<=5) || (co>=8 && co<=13)) return true; break; + case (0x0231) : if (co==3 || co==4 || (co>=8 && co<=12)) return true; break; + case (0x0312) : if (co==4 || co==6 || co==8 || co==9 || co==10 || co==12 || co==14) return true; break; + case (0x0321) : if (co==4 || (co>=8 && co<=10) || co==12) return true; break; + case (0x1023) : if (co>=3 && co<=11) return true; break; + case (0x1032) : if ((co>=4 && co<=6) || (co>=8 && co<=10)) return true; break; + case (0x1203) : if (co>=3 && co<=9) return true; break; + case (0x1230) : if (co>=3 && co<=8) return true; break; + case (0x1302) : if ((co>=4 && co<=6) || co==8 || co==10) return true; break; + case (0x1320) : if ((co>=4 && co<=6) || co==8) return true; break; + case (0x2013) : if ((co>=3 && co<=5) || co==8 || co==9 || co==12 || co==13) return true; break; + case (0x2031) : if (co==3 || co==4 || co==8 || co==9 || co==12) return true; break; + case (0x2103) : if ((co>=3 && co<=5) || co==8 || co==9) return true; break; + case (0x2130) : if ((co>=3 && co<=5) || co==8) return true; break; + case (0x2301) : if (co==3 || co==4 || co==8 || co==12) return true; break; + case (0x2310) : if (co==3 || co==4 || co==8) return true; break; + case (0x3012) : if (co==4 || co==6 || co==8 || co==10 || co==12 || co==14) return true; break; + case (0x3021) : if (co==4 || co==8 || co==10 || co==12) return true; break; + case (0x3102) : if (co==4 || co==6 || co==8 || co==10) return true; break; + case (0x3120) : if (co==4 || co==6 || co==8) return true; break; + case (0x3201) : if (co==4 || co==8 || co==12) return true; break; + case (0x3210) : if (co==4 || co==8) return true; break; + } + return false; + } + template CImg _permute_axes(const char *const axes_order, const t&) const { if (is_empty() || !axes_order) return CImg(*this,false); - const unsigned uicase = __permute_axes(axes_order); + CImg res; + const unsigned uicase = _permute_axes_uicase(axes_order); + + if (_permute_axes_is_optim(uicase)) { // Data layout allow to do nothing but set the new dimensions + res.assign(*this,false); + for (unsigned int i = 0; i<4; ++i) { + const unsigned int axis = (uicase>>(4*(3 - i)))&15, value = !axis?_width:axis==1?_height:axis==2?_depth:_spectrum; + if (!i) res._width = value; else if (i==1) res._height = value; else if (i==2) res._depth = value; else res._spectrum = value; + } + return res; + } + const T* ptrs = _data; ulongT wh, whd; - CImg res; switch (uicase) { case 0x0123 : // xyzc @@ -37160,7 +37212,6 @@ namespace cimg_library { cimg_forXYZC(*this,x,y,z,c) res(c,z,y,x,wh,whd) = (t)*(ptrs++); break; } - return res; } From d21762166bd3f1caeff3a1b8b9ec9e70bc760787 Mon Sep 17 00:00:00 2001 From: David Tschumperle Date: Fri, 18 Aug 2023 14:32:25 +0200 Subject: [PATCH 4/4] . --- CImg.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/CImg.h b/CImg.h index 5f4b7e86..8dcadbbf 100644 --- a/CImg.h +++ b/CImg.h @@ -36933,8 +36933,11 @@ namespace cimg_library { if (_permute_axes_is_optim(uicase)) { // Data layout allow to do nothing but set the new dimensions CImg res(*this,true); for (unsigned int i = 0; i<4; ++i) { - const unsigned int axis = (uicase>>(4*(3 - i)))&15, value = !axis?_width:axis==1?_height:axis==2?_depth:_spectrum; - if (!i) res._width = value; else if (i==1) res._height = value; else if (i==2) res._depth = value; else res._spectrum = value; + const unsigned int + axis = (uicase>>(4*(3 - i)))&15, + value = !axis?_width:axis==1?_height:axis==2?_depth:_spectrum; + if (!i) res._width = value; else if (i==1) res._height = value; + else if (i==2) res._depth = value; else res._spectrum = value; } _width = res._width; _height = res._height; _depth = res._depth; _spectrum = res._spectrum; return *this; @@ -37005,8 +37008,11 @@ namespace cimg_library { if (_permute_axes_is_optim(uicase)) { // Data layout allow to do nothing but set the new dimensions res.assign(*this,false); for (unsigned int i = 0; i<4; ++i) { - const unsigned int axis = (uicase>>(4*(3 - i)))&15, value = !axis?_width:axis==1?_height:axis==2?_depth:_spectrum; - if (!i) res._width = value; else if (i==1) res._height = value; else if (i==2) res._depth = value; else res._spectrum = value; + const unsigned int + axis = (uicase>>(4*(3 - i)))&15, + value = !axis?_width:axis==1?_height:axis==2?_depth:_spectrum; + if (!i) res._width = value; else if (i==1) res._height = value; + else if (i==2) res._depth = value; else res._spectrum = value; } return res; }