From 49ee6b0d1ab65afa4cc60b07ea617a31c2c1db0e Mon Sep 17 00:00:00 2001 From: Dmitry Vorotilin Date: Tue, 28 Feb 2017 00:14:12 +0300 Subject: [PATCH 1/2] Update CImg to 179 because it fixes leaking file descriptors --- ext/phashion_ext/CImg.h | 58690 ++++++++++++++++++++++++++ ext/phashion_ext/extconf.rb | 7 +- ext/phashion_ext/pHash-0.9.6.tar.gz | Bin 1900046 -> 1315965 bytes 3 files changed, 58695 insertions(+), 2 deletions(-) create mode 100644 ext/phashion_ext/CImg.h diff --git a/ext/phashion_ext/CImg.h b/ext/phashion_ext/CImg.h new file mode 100644 index 0000000..b2b378e --- /dev/null +++ b/ext/phashion_ext/CImg.h @@ -0,0 +1,58690 @@ +/* + # + # File : CImg.h + # ( C++ header file ) + # + # Description : The C++ Template Image Processing Toolkit. + # This file is the main component of the CImg Library project. + # ( http://cimg.eu ) + # + # Project manager : David Tschumperle. + # ( http://tschumperle.users.greyc.fr/ ) + # + # A complete list of contributors is available in file 'README.txt' + # distributed within the CImg package. + # + # Licenses : This file is 'dual-licensed', you have to choose one + # of the two licenses below to apply. + # + # CeCILL-C + # The CeCILL-C license is close to the GNU LGPL. + # ( http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html ) + # + # or CeCILL v2.0 + # The CeCILL license is compatible with the GNU GPL. + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) + # + # This software is governed either by the CeCILL or the CeCILL-C license + # under French law and abiding by the rules of distribution of free software. + # You can use, modify and or redistribute the software under the terms of + # the CeCILL or CeCILL-C licenses as circulated by CEA, CNRS and INRIA + # at the following URL: "http://www.cecill.info". + # + # As a counterpart to the access to the source code and rights to copy, + # modify and redistribute granted by the license, users are provided only + # with a limited warranty and the software's author, the holder of the + # economic rights, and the successive licensors have only limited + # liability. + # + # In this respect, the user's attention is drawn to the risks associated + # with loading, using, modifying and/or developing or reproducing the + # software by the user in light of its specific status of free software, + # that may mean that it is complicated to manipulate, and that also + # therefore means that it is reserved for developers and experienced + # professionals having in-depth computer knowledge. Users are therefore + # encouraged to load and test the software's suitability as regards their + # requirements in conditions enabling the security of their systems and/or + # data to be ensured and, more generally, to use and operate it in the + # same conditions as regards security. + # + # The fact that you are presently reading this means that you have had + # knowledge of the CeCILL and CeCILL-C licenses and that you accept its terms. + # +*/ + +// Set version number of the library. +#ifndef cimg_version +#define cimg_version 179 + +/*----------------------------------------------------------- + # + # Test and possibly auto-set CImg configuration variables + # and include required headers. + # + # If you find that the default configuration variables are + # not adapted to your system, you can override their values + # before including the header file "CImg.h" + # (use the #define directive). + # + ------------------------------------------------------------*/ + +// Include standard C++ headers. +// This is the minimal set of required headers to make CImg-based codes compile. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Detect/configure OS variables. +// +// Define 'cimg_OS' to: '0' for an unknown OS (will try to minize library dependencies). +// '1' for a Unix-like OS (Linux, Solaris, BSD, MacOSX, Irix, ...). +// '2' for Microsoft Windows. +// (auto-detection is performed if 'cimg_OS' is not set by the user). +#ifndef cimg_OS +#if defined(unix) || defined(__unix) || defined(__unix__) \ + || defined(linux) || defined(__linux) || defined(__linux__) \ + || defined(sun) || defined(__sun) \ + || defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \ + || defined(__FreeBSD__) || defined (__DragonFly__) \ + || defined(sgi) || defined(__sgi) \ + || defined(__MACOSX__) || defined(__APPLE__) \ + || defined(__CYGWIN__) +#define cimg_OS 1 +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) +#define cimg_OS 2 +#else +#define cimg_OS 0 +#endif +#elif !(cimg_OS==0 || cimg_OS==1 || cimg_OS==2) +#error CImg Library: Invalid configuration variable 'cimg_OS'. +#error (correct values are '0 = unknown OS', '1 = Unix-like OS', '2 = Microsoft Windows'). +#endif +#ifndef cimg_date +#define cimg_date __DATE__ +#endif +#ifndef cimg_time +#define cimg_time __TIME__ +#endif + +// Disable silly warnings on some Microsoft VC++ compilers. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4127) +#pragma warning(disable:4244) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#pragma warning(disable:4512) +#pragma warning(disable:4571) +#pragma warning(disable:4640) +#pragma warning(disable:4706) +#pragma warning(disable:4710) +#pragma warning(disable:4800) +#pragma warning(disable:4804) +#pragma warning(disable:4820) +#pragma warning(disable:4996) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_WARNINGS 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +// Define correct string functions for each compiler and OS. +#if cimg_OS==2 && defined(_MSC_VER) +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#include +#if defined(__MACOSX__) || defined(__APPLE__) +#define cimg_sscanf cimg::_sscanf +#define cimg_sprintf cimg::_sprintf +#define cimg_snprintf cimg::_snprintf +#define cimg_vsnprintf cimg::_vsnprintf +#else +#define cimg_sscanf std::sscanf +#define cimg_sprintf std::sprintf +#define cimg_snprintf snprintf +#define cimg_vsnprintf vsnprintf +#endif +#endif + +// Include OS-specific headers. +#if cimg_OS==1 +#include +#include +#include +#include +#include +#include +#elif cimg_OS==2 +#ifndef std_fopen +#define std_fopen cimg::win_fopen +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#ifndef _WIN32_IE +#define _WIN32_IE 0x0400 +#endif +#include +#include +#include +#endif + +// Look for C++11 features. +#ifndef cimg_use_cpp11 +#if __cplusplus>201100 +#define cimg_use_cpp11 1 +#else +#define cimg_use_cpp11 0 +#endif +#endif +#if cimg_use_cpp11==1 +#include +#include +#endif + +// Convenient macro to define pragma +#ifdef _MSC_VER +#define cimg_pragma(x) __pragma(x) +#else +#define cimg_pragma(x) _Pragma(#x) +#endif + +// Define own types 'cimg_long/ulong' and 'cimg_int64/uint64' to ensure portability. +// ( constrained to 'sizeof(cimg_ulong/cimg_long) = sizeof(void*)' and 'sizeof(cimg_int64/cimg_uint64)=8' ). +#if cimg_OS==2 +#define cimg_uint64 unsigned __int64 +#define cimg_int64 __int64 +#define cimg_ulong UINT_PTR +#define cimg_long INT_PTR +#else +#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. +// +// Filename separator is set by default to '/', except for Windows where it is '\'. +#ifndef cimg_file_separator +#if cimg_OS==2 +#define cimg_file_separator '\\' +#else +#define cimg_file_separator '/' +#endif +#endif + +// Configure verbosity of output messages. +// +// Define 'cimg_verbosity' to: '0' to hide library messages (quiet mode). +// '1' to output library messages on the console. +// '2' to output library messages on a basic dialog window (default behavior). +// '3' to do as '1' + add extra warnings (may slow down the code!). +// '4' to do as '2' + add extra warnings (may slow down the code!). +// +// Define 'cimg_strict_warnings' to replace warning messages by exception throwns. +// +// Define 'cimg_use_vt100' to allow output of color messages on VT100-compatible terminals. +#ifndef cimg_verbosity +#if cimg_OS==2 +#define cimg_verbosity 2 +#else +#define cimg_verbosity 1 +#endif +#elif !(cimg_verbosity==0 || cimg_verbosity==1 || cimg_verbosity==2 || cimg_verbosity==3 || cimg_verbosity==4) +#error CImg Library: Configuration variable 'cimg_verbosity' is badly defined. +#error (should be { 0=quiet | 1=console | 2=dialog | 3=console+warnings | 4=dialog+warnings }). +#endif + +// Configure display framework. +// +// Define 'cimg_display' to: '0' to disable display capabilities. +// '1' to use the X-Window framework (X11). +// '2' to use the Microsoft GDI32 framework. +#ifndef cimg_display +#if cimg_OS==0 +#define cimg_display 0 +#elif cimg_OS==1 +#define cimg_display 1 +#elif cimg_OS==2 +#define cimg_display 2 +#endif +#elif !(cimg_display==0 || cimg_display==1 || cimg_display==2) +#error CImg Library: Configuration variable 'cimg_display' is badly defined. +#error (should be { 0=none | 1=X-Window (X11) | 2=Microsoft GDI32 }). +#endif + +// Configure the 'abort' signal handler (does nothing by default). +// A typical signal handler can be defined in your own source like this: +// #define cimg_abort_test() if (is_abort) throw CImgAbortException("") +// +// where 'is_abort' is a boolean variable defined somewhere in your code and reachable in the method. +// 'cimg_abort_test2()' does the same but is called more often (in inner loops). +#if defined(cimg_abort_test) && defined(cimg_use_openmp) + +// Define abort macros to be used with OpenMP. +#ifndef cimg_abort_init +#define cimg_abort_init bool cimg_abort_go = true; cimg::unused(cimg_abort_go) +#endif +#ifndef cimg_abort_try +#define cimg_abort_try if (cimg_abort_go) try +#endif +#ifndef cimg_abort_catch +#define cimg_abort_catch() catch (...) { cimg_pragma(omp atomic) cimg_abort_go&=false; } +#endif +#ifdef cimg_abort_test2 +#ifndef cimg_abort_try2 +#define cimg_abort_try2 cimg_abort_try +#endif +#ifndef cimg_abort_catch2 +#define cimg_abort_catch2() cimg_abort_catch() +#endif +#endif + +#endif + +#ifndef cimg_abort_test +#define cimg_abort_test() +#endif +#ifndef cimg_abort_test2 +#define cimg_abort_test2() +#endif +#ifndef cimg_abort_init +#define cimg_abort_init +#endif +#ifndef cimg_abort_try +#define cimg_abort_try +#endif +#ifndef cimg_abort_catch +#define cimg_abort_catch() +#endif +#ifndef cimg_abort_try2 +#define cimg_abort_try2 +#endif +#ifndef cimg_abort_catch2 +#define cimg_abort_catch2() +#endif +#ifndef std_fopen +#define std_fopen std::fopen +#endif + +// Include display-specific headers. +#if cimg_display==1 +#include +#include +#include +#include +#ifdef cimg_use_xshm +#include +#include +#include +#endif +#ifdef cimg_use_xrandr +#include +#endif +#endif +#ifndef cimg_appname +#define cimg_appname "CImg" +#endif + +// Configure OpenMP support. +// (http://www.openmp.org) +// +// Define 'cimg_use_openmp' to enable OpenMP support. +// +// OpenMP directives may be used in a (very) few CImg functions to get +// advantages of multi-core CPUs. +#ifdef cimg_use_openmp +#include +#define cimg_pragma_openmp(p) cimg_pragma(omp p) +#else +#define cimg_pragma_openmp(p) +#endif + +// Configure OpenCV support. +// (http://opencv.willowgarage.com/wiki/) +// +// Define 'cimg_use_opencv' to enable OpenCV support. +// +// OpenCV library may be used to access images from cameras +// (see method 'CImg::load_camera()'). +#ifdef cimg_use_opencv +#ifdef True +#undef True +#define _cimg_redefine_True +#endif +#ifdef False +#undef False +#define _cimg_redefine_False +#endif +#include +#include "cv.h" +#include "highgui.h" +#endif + +// Configure LibPNG support. +// (http://www.libpng.org) +// +// Define 'cimg_use_png' to enable LibPNG support. +// +// PNG library may be used to get a native support of '.png' files. +// (see methods 'CImg::{load,save}_png()'. +#ifdef cimg_use_png +extern "C" { +#include "png.h" +} +#endif + +// Configure LibJPEG support. +// (http://en.wikipedia.org/wiki/Libjpeg) +// +// Define 'cimg_use_jpeg' to enable LibJPEG support. +// +// JPEG library may be used to get a native support of '.jpg' files. +// (see methods 'CImg::{load,save}_jpeg()'). +#ifdef cimg_use_jpeg +extern "C" { +#include "jpeglib.h" +#include "setjmp.h" +} +#endif + +// Configure LibTIFF support. +// (http://www.libtiff.org) +// +// Define 'cimg_use_tiff' to enable LibTIFF support. +// +// TIFF library may be used to get a native support of '.tif' files. +// (see methods 'CImg[List]::{load,save}_tiff()'). +#ifdef cimg_use_tiff +extern "C" { +#define uint64 uint64_hack_ +#define int64 int64_hack_ +#include "tiffio.h" +#undef uint64 +#undef int64 +} +#endif + +// Configure LibMINC2 support. +// (http://en.wikibooks.org/wiki/MINC/Reference/MINC2.0_File_Format_Reference) +// +// Define 'cimg_use_minc2' to enable LibMINC2 support. +// +// MINC2 library may be used to get a native support of '.mnc' files. +// (see methods 'CImg::{load,save}_minc2()'). +#ifdef cimg_use_minc2 +#include "minc_io_simple_volume.h" +#include "minc_1_simple.h" +#include "minc_1_simple_rw.h" +#endif + +// Configure Zlib support. +// (http://www.zlib.net) +// +// Define 'cimg_use_zlib' to enable Zlib support. +// +// Zlib library may be used to allow compressed data in '.cimgz' files +// (see methods 'CImg[List]::{load,save}_cimg()'). +#ifdef cimg_use_zlib +extern "C" { +#include "zlib.h" +} +#endif + +// Configure libcurl support. +// (http://curl.haxx.se/libcurl/) +// +// Define 'cimg_use_curl' to enable libcurl support. +// +// Libcurl may be used to get a native support of file downloading from the network. +// (see method 'cimg::load_network()'.) +#ifdef cimg_use_curl +#include "curl/curl.h" +#endif + +// Configure Magick++ support. +// (http://www.imagemagick.org/Magick++) +// +// Define 'cimg_use_magick' to enable Magick++ support. +// +// Magick++ library may be used to get a native support of various image file formats. +// (see methods 'CImg::{load,save}()'). +#ifdef cimg_use_magick +#include "Magick++.h" +#endif + +// Configure FFTW3 support. +// (http://www.fftw.org) +// +// Define 'cimg_use_fftw3' to enable libFFTW3 support. +// +// FFTW3 library may be used to efficiently compute the Fast Fourier Transform +// of image data, without restriction on the image size. +// (see method 'CImg[List]::FFT()'). +#ifdef cimg_use_fftw3 +extern "C" { +#include "fftw3.h" +} +#endif + +// Configure LibBoard support. +// (http://libboard.sourceforge.net/) +// +// Define 'cimg_use_board' to enable Board support. +// +// Board library may be used to draw 3d objects in vector-graphics canvas +// that can be saved as '.ps' or '.svg' files afterwards. +// (see method 'CImg::draw_object3d()'). +#ifdef cimg_use_board +#ifdef None +#undef None +#define _cimg_redefine_None +#endif +#include "Board.h" +#endif + +// Configure OpenEXR support. +// (http://www.openexr.com/) +// +// Define 'cimg_use_openexr' to enable OpenEXR support. +// +// OpenEXR library may be used to get a native support of '.exr' files. +// (see methods 'CImg::{load,save}_exr()'). +#ifdef cimg_use_openexr +#include "ImfRgbaFile.h" +#include "ImfInputFile.h" +#include "ImfChannelList.h" +#include "ImfMatrixAttribute.h" +#include "ImfArray.h" +#endif + +// Configure TinyEXR support. +// (https://github.com/syoyo/tinyexr) +// +// Define 'cimg_use_tinyexr' to enable TinyEXR support. +// +// TinyEXR is a small, single header-only library to load and save OpenEXR(.exr) images. +#ifdef cimg_use_tinyexr +#ifndef TINYEXR_IMPLEMENTATION +#define TINYEXR_IMPLEMENTATION +#endif +#include "tinyexr.h" +#endif + +// Lapack configuration. +// (http://www.netlib.org/lapack) +// +// Define 'cimg_use_lapack' to enable LAPACK support. +// +// Lapack library may be used in several CImg methods to speed up +// matrix computations (eigenvalues, inverse, ...). +#ifdef cimg_use_lapack +extern "C" { + extern void sgetrf_(int*, int*, float*, int*, int*, int*); + extern void sgetri_(int*, float*, int*, int*, float*, int*, int*); + extern void sgetrs_(char*, int*, int*, float*, int*, int*, float*, int*, int*); + extern void sgesvd_(char*, char*, int*, int*, float*, int*, float*, float*, int*, float*, int*, float*, int*, int*); + extern void ssyev_(char*, char*, int*, float*, int*, float*, float*, int*, int*); + extern void dgetrf_(int*, int*, double*, int*, int*, int*); + extern void dgetri_(int*, double*, int*, int*, double*, int*, int*); + extern void dgetrs_(char*, int*, int*, double*, int*, int*, double*, int*, int*); + extern void dgesvd_(char*, char*, int*, int*, double*, int*, double*, double*, + int*, double*, int*, double*, int*, int*); + extern void dsyev_(char*, char*, int*, double*, int*, double*, double*, int*, int*); + extern void dgels_(char*, int*,int*,int*,double*,int*,double*,int*,double*,int*,int*); + extern void sgels_(char*, int*,int*,int*,float*,int*,float*,int*,float*,int*,int*); +} +#endif + +// Check if min/max/PI macros are defined. +// +// CImg does not compile if macros 'min', 'max' or 'PI' are defined, +// because it redefines functions min(), max() and const variable PI in the cimg:: namespace. +// so it '#undef' these macros if necessary, and restore them to reasonable +// values at the end of this file. +#ifdef min +#undef min +#define _cimg_redefine_min +#endif +#ifdef max +#undef max +#define _cimg_redefine_max +#endif +#ifdef PI +#undef PI +#define _cimg_redefine_PI +#endif + +// Define 'cimg_library' namespace suffix. +// +// You may want to add a suffix to the 'cimg_library' namespace, for instance if you need to work +// with several versions of the library at the same time. +#ifdef cimg_namespace_suffix +#define __cimg_library_suffixed(s) cimg_library_##s +#define _cimg_library_suffixed(s) __cimg_library_suffixed(s) +#define cimg_library_suffixed _cimg_library_suffixed(cimg_namespace_suffix) +#else +#define cimg_library_suffixed cimg_library +#endif + +/*------------------------------------------------------------------------------ + # + # Define user-friendly macros. + # + # These CImg macros are prefixed by 'cimg_' and can be used safely in your own + # code. They are useful to parse command line options, or to write image loops. + # + ------------------------------------------------------------------------------*/ + +// Macros to define program usage, and retrieve command line arguments. +#define cimg_usage(usage) cimg_library_suffixed::cimg::option((char*)0,argc,argv,(char*)0,usage,false) +#define cimg_help(str) cimg_library_suffixed::cimg::option((char*)0,argc,argv,str,(char*)0) +#define cimg_option(name,defaut,usage) cimg_library_suffixed::cimg::option(name,argc,argv,defaut,usage) + +// Macros to define and manipulate local neighborhoods. +#define CImg_2x2(I,T) T I[4]; \ + T& I##cc = I[0]; T& I##nc = I[1]; \ + T& I##cn = I[2]; T& I##nn = I[3]; \ + I##cc = I##nc = \ + I##cn = I##nn = 0 + +#define CImg_3x3(I,T) T I[9]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; \ + T& I##pc = I[3]; T& I##cc = I[4]; T& I##nc = I[5]; \ + T& I##pn = I[6]; T& I##cn = I[7]; T& I##nn = I[8]; \ + I##pp = I##cp = I##np = \ + I##pc = I##cc = I##nc = \ + I##pn = I##cn = I##nn = 0 + +#define CImg_4x4(I,T) T I[16]; \ + T& I##pp = I[0]; T& I##cp = I[1]; T& I##np = I[2]; T& I##ap = I[3]; \ + T& I##pc = I[4]; T& I##cc = I[5]; T& I##nc = I[6]; T& I##ac = I[7]; \ + T& I##pn = I[8]; T& I##cn = I[9]; T& I##nn = I[10]; T& I##an = I[11]; \ + T& I##pa = I[12]; T& I##ca = I[13]; T& I##na = I[14]; T& I##aa = I[15]; \ + I##pp = I##cp = I##np = I##ap = \ + I##pc = I##cc = I##nc = I##ac = \ + I##pn = I##cn = I##nn = I##an = \ + I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_5x5(I,T) T I[25]; \ + T& I##bb = I[0]; T& I##pb = I[1]; T& I##cb = I[2]; T& I##nb = I[3]; T& I##ab = I[4]; \ + T& I##bp = I[5]; T& I##pp = I[6]; T& I##cp = I[7]; T& I##np = I[8]; T& I##ap = I[9]; \ + T& I##bc = I[10]; T& I##pc = I[11]; T& I##cc = I[12]; T& I##nc = I[13]; T& I##ac = I[14]; \ + T& I##bn = I[15]; T& I##pn = I[16]; T& I##cn = I[17]; T& I##nn = I[18]; T& I##an = I[19]; \ + T& I##ba = I[20]; T& I##pa = I[21]; T& I##ca = I[22]; T& I##na = I[23]; T& I##aa = I[24]; \ + I##bb = I##pb = I##cb = I##nb = I##ab = \ + I##bp = I##pp = I##cp = I##np = I##ap = \ + I##bc = I##pc = I##cc = I##nc = I##ac = \ + I##bn = I##pn = I##cn = I##nn = I##an = \ + I##ba = I##pa = I##ca = I##na = I##aa = 0 + +#define CImg_2x2x2(I,T) T I[8]; \ + T& I##ccc = I[0]; T& I##ncc = I[1]; \ + T& I##cnc = I[2]; T& I##nnc = I[3]; \ + T& I##ccn = I[4]; T& I##ncn = I[5]; \ + T& I##cnn = I[6]; T& I##nnn = I[7]; \ + I##ccc = I##ncc = \ + I##cnc = I##nnc = \ + I##ccn = I##ncn = \ + I##cnn = I##nnn = 0 + +#define CImg_3x3x3(I,T) T I[27]; \ + T& I##ppp = I[0]; T& I##cpp = I[1]; T& I##npp = I[2]; \ + T& I##pcp = I[3]; T& I##ccp = I[4]; T& I##ncp = I[5]; \ + T& I##pnp = I[6]; T& I##cnp = I[7]; T& I##nnp = I[8]; \ + T& I##ppc = I[9]; T& I##cpc = I[10]; T& I##npc = I[11]; \ + T& I##pcc = I[12]; T& I##ccc = I[13]; T& I##ncc = I[14]; \ + T& I##pnc = I[15]; T& I##cnc = I[16]; T& I##nnc = I[17]; \ + T& I##ppn = I[18]; T& I##cpn = I[19]; T& I##npn = I[20]; \ + T& I##pcn = I[21]; T& I##ccn = I[22]; T& I##ncn = I[23]; \ + T& I##pnn = I[24]; T& I##cnn = I[25]; T& I##nnn = I[26]; \ + I##ppp = I##cpp = I##npp = \ + I##pcp = I##ccp = I##ncp = \ + I##pnp = I##cnp = I##nnp = \ + I##ppc = I##cpc = I##npc = \ + I##pcc = I##ccc = I##ncc = \ + I##pnc = I##cnc = I##nnc = \ + I##ppn = I##cpn = I##npn = \ + I##pcn = I##ccn = I##ncn = \ + I##pnn = I##cnn = I##nnn = 0 + +#define cimg_get2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_p1##x,y,z,c), I[4] = (T)(img)(x,y,z,c), I[5] = (T)(img)(_n1##x,y,z,c), \ + I[6] = (T)(img)(_p1##x,_n1##y,z,c), I[7] = (T)(img)(x,_n1##y,z,c), I[8] = (T)(img)(_n1##x,_n1##y,z,c) + +#define cimg_get4x4(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,z,c), I[1] = (T)(img)(x,_p1##y,z,c), I[2] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[3] = (T)(img)(_n2##x,_p1##y,z,c), I[4] = (T)(img)(_p1##x,y,z,c), I[5] = (T)(img)(x,y,z,c), \ + I[6] = (T)(img)(_n1##x,y,z,c), I[7] = (T)(img)(_n2##x,y,z,c), I[8] = (T)(img)(_p1##x,_n1##y,z,c), \ + I[9] = (T)(img)(x,_n1##y,z,c), I[10] = (T)(img)(_n1##x,_n1##y,z,c), I[11] = (T)(img)(_n2##x,_n1##y,z,c), \ + I[12] = (T)(img)(_p1##x,_n2##y,z,c), I[13] = (T)(img)(x,_n2##y,z,c), I[14] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[15] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get5x5(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[6] = (T)(img)(_p1##x,_p1##y,z,c), I[7] = (T)(img)(x,_p1##y,z,c), I[8] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[9] = (T)(img)(_n2##x,_p1##y,z,c), I[10] = (T)(img)(_p2##x,y,z,c), I[11] = (T)(img)(_p1##x,y,z,c), \ + I[12] = (T)(img)(x,y,z,c), I[13] = (T)(img)(_n1##x,y,z,c), I[14] = (T)(img)(_n2##x,y,z,c), \ + I[15] = (T)(img)(_p2##x,_n1##y,z,c), I[16] = (T)(img)(_p1##x,_n1##y,z,c), I[17] = (T)(img)(x,_n1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_n1##y,z,c), I[19] = (T)(img)(_n2##x,_n1##y,z,c), I[20] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_n2##y,z,c), I[22] = (T)(img)(x,_n2##y,z,c), I[23] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_n2##y,z,c) + +#define cimg_get6x6(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p2##x,_p2##y,z,c), I[1] = (T)(img)(_p1##x,_p2##y,z,c), I[2] = (T)(img)(x,_p2##y,z,c), \ + I[3] = (T)(img)(_n1##x,_p2##y,z,c), I[4] = (T)(img)(_n2##x,_p2##y,z,c), I[5] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[6] = (T)(img)(_p2##x,_p1##y,z,c), I[7] = (T)(img)(_p1##x,_p1##y,z,c), I[8] = (T)(img)(x,_p1##y,z,c), \ + I[9] = (T)(img)(_n1##x,_p1##y,z,c), I[10] = (T)(img)(_n2##x,_p1##y,z,c), I[11] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[12] = (T)(img)(_p2##x,y,z,c), I[13] = (T)(img)(_p1##x,y,z,c), I[14] = (T)(img)(x,y,z,c), \ + I[15] = (T)(img)(_n1##x,y,z,c), I[16] = (T)(img)(_n2##x,y,z,c), I[17] = (T)(img)(_n3##x,y,z,c), \ + I[18] = (T)(img)(_p2##x,_n1##y,z,c), I[19] = (T)(img)(_p1##x,_n1##y,z,c), I[20] = (T)(img)(x,_n1##y,z,c), \ + I[21] = (T)(img)(_n1##x,_n1##y,z,c), I[22] = (T)(img)(_n2##x,_n1##y,z,c), I[23] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[24] = (T)(img)(_p2##x,_n2##y,z,c), I[25] = (T)(img)(_p1##x,_n2##y,z,c), I[26] = (T)(img)(x,_n2##y,z,c), \ + I[27] = (T)(img)(_n1##x,_n2##y,z,c), I[28] = (T)(img)(_n2##x,_n2##y,z,c), I[29] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[30] = (T)(img)(_p2##x,_n3##y,z,c), I[31] = (T)(img)(_p1##x,_n3##y,z,c), I[32] = (T)(img)(x,_n3##y,z,c), \ + I[33] = (T)(img)(_n1##x,_n3##y,z,c), I[34] = (T)(img)(_n2##x,_n3##y,z,c), I[35] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get7x7(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_p3##x,_p2##y,z,c), I[8] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p1##x,_p2##y,z,c), I[10] = (T)(img)(x,_p2##y,z,c), I[11] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[12] = (T)(img)(_n2##x,_p2##y,z,c), I[13] = (T)(img)(_n3##x,_p2##y,z,c), I[14] = (T)(img)(_p3##x,_p1##y,z,c), \ + I[15] = (T)(img)(_p2##x,_p1##y,z,c), I[16] = (T)(img)(_p1##x,_p1##y,z,c), I[17] = (T)(img)(x,_p1##y,z,c), \ + I[18] = (T)(img)(_n1##x,_p1##y,z,c), I[19] = (T)(img)(_n2##x,_p1##y,z,c), I[20] = (T)(img)(_n3##x,_p1##y,z,c), \ + I[21] = (T)(img)(_p3##x,y,z,c), I[22] = (T)(img)(_p2##x,y,z,c), I[23] = (T)(img)(_p1##x,y,z,c), \ + I[24] = (T)(img)(x,y,z,c), I[25] = (T)(img)(_n1##x,y,z,c), I[26] = (T)(img)(_n2##x,y,z,c), \ + I[27] = (T)(img)(_n3##x,y,z,c), I[28] = (T)(img)(_p3##x,_n1##y,z,c), I[29] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_n1##y,z,c), I[31] = (T)(img)(x,_n1##y,z,c), I[32] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_n1##y,z,c), I[34] = (T)(img)(_n3##x,_n1##y,z,c), I[35] = (T)(img)(_p3##x,_n2##y,z,c), \ + I[36] = (T)(img)(_p2##x,_n2##y,z,c), I[37] = (T)(img)(_p1##x,_n2##y,z,c), I[38] = (T)(img)(x,_n2##y,z,c), \ + I[39] = (T)(img)(_n1##x,_n2##y,z,c), I[40] = (T)(img)(_n2##x,_n2##y,z,c), I[41] = (T)(img)(_n3##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p3##x,_n3##y,z,c), I[43] = (T)(img)(_p2##x,_n3##y,z,c), I[44] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[45] = (T)(img)(x,_n3##y,z,c), I[46] = (T)(img)(_n1##x,_n3##y,z,c), I[47] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[48] = (T)(img)(_n3##x,_n3##y,z,c) + +#define cimg_get8x8(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p3##x,_p3##y,z,c), I[1] = (T)(img)(_p2##x,_p3##y,z,c), I[2] = (T)(img)(_p1##x,_p3##y,z,c), \ + I[3] = (T)(img)(x,_p3##y,z,c), I[4] = (T)(img)(_n1##x,_p3##y,z,c), I[5] = (T)(img)(_n2##x,_p3##y,z,c), \ + I[6] = (T)(img)(_n3##x,_p3##y,z,c), I[7] = (T)(img)(_n4##x,_p3##y,z,c), I[8] = (T)(img)(_p3##x,_p2##y,z,c), \ + I[9] = (T)(img)(_p2##x,_p2##y,z,c), I[10] = (T)(img)(_p1##x,_p2##y,z,c), I[11] = (T)(img)(x,_p2##y,z,c), \ + I[12] = (T)(img)(_n1##x,_p2##y,z,c), I[13] = (T)(img)(_n2##x,_p2##y,z,c), I[14] = (T)(img)(_n3##x,_p2##y,z,c), \ + I[15] = (T)(img)(_n4##x,_p2##y,z,c), I[16] = (T)(img)(_p3##x,_p1##y,z,c), I[17] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[18] = (T)(img)(_p1##x,_p1##y,z,c), I[19] = (T)(img)(x,_p1##y,z,c), I[20] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[21] = (T)(img)(_n2##x,_p1##y,z,c), I[22] = (T)(img)(_n3##x,_p1##y,z,c), I[23] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[24] = (T)(img)(_p3##x,y,z,c), I[25] = (T)(img)(_p2##x,y,z,c), I[26] = (T)(img)(_p1##x,y,z,c), \ + I[27] = (T)(img)(x,y,z,c), I[28] = (T)(img)(_n1##x,y,z,c), I[29] = (T)(img)(_n2##x,y,z,c), \ + I[30] = (T)(img)(_n3##x,y,z,c), I[31] = (T)(img)(_n4##x,y,z,c), I[32] = (T)(img)(_p3##x,_n1##y,z,c), \ + I[33] = (T)(img)(_p2##x,_n1##y,z,c), I[34] = (T)(img)(_p1##x,_n1##y,z,c), I[35] = (T)(img)(x,_n1##y,z,c), \ + I[36] = (T)(img)(_n1##x,_n1##y,z,c), I[37] = (T)(img)(_n2##x,_n1##y,z,c), I[38] = (T)(img)(_n3##x,_n1##y,z,c), \ + I[39] = (T)(img)(_n4##x,_n1##y,z,c), I[40] = (T)(img)(_p3##x,_n2##y,z,c), I[41] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[42] = (T)(img)(_p1##x,_n2##y,z,c), I[43] = (T)(img)(x,_n2##y,z,c), I[44] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[45] = (T)(img)(_n2##x,_n2##y,z,c), I[46] = (T)(img)(_n3##x,_n2##y,z,c), I[47] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[48] = (T)(img)(_p3##x,_n3##y,z,c), I[49] = (T)(img)(_p2##x,_n3##y,z,c), I[50] = (T)(img)(_p1##x,_n3##y,z,c), \ + I[51] = (T)(img)(x,_n3##y,z,c), I[52] = (T)(img)(_n1##x,_n3##y,z,c), I[53] = (T)(img)(_n2##x,_n3##y,z,c), \ + I[54] = (T)(img)(_n3##x,_n3##y,z,c), I[55] = (T)(img)(_n4##x,_n3##y,z,c), I[56] = (T)(img)(_p3##x,_n4##y,z,c), \ + I[57] = (T)(img)(_p2##x,_n4##y,z,c), I[58] = (T)(img)(_p1##x,_n4##y,z,c), I[59] = (T)(img)(x,_n4##y,z,c), \ + I[60] = (T)(img)(_n1##x,_n4##y,z,c), I[61] = (T)(img)(_n2##x,_n4##y,z,c), I[62] = (T)(img)(_n3##x,_n4##y,z,c), \ + I[63] = (T)(img)(_n4##x,_n4##y,z,c); + +#define cimg_get9x9(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p4##x,_p4##y,z,c), I[1] = (T)(img)(_p3##x,_p4##y,z,c), I[2] = (T)(img)(_p2##x,_p4##y,z,c), \ + I[3] = (T)(img)(_p1##x,_p4##y,z,c), I[4] = (T)(img)(x,_p4##y,z,c), I[5] = (T)(img)(_n1##x,_p4##y,z,c), \ + I[6] = (T)(img)(_n2##x,_p4##y,z,c), I[7] = (T)(img)(_n3##x,_p4##y,z,c), I[8] = (T)(img)(_n4##x,_p4##y,z,c), \ + I[9] = (T)(img)(_p4##x,_p3##y,z,c), I[10] = (T)(img)(_p3##x,_p3##y,z,c), I[11] = (T)(img)(_p2##x,_p3##y,z,c), \ + I[12] = (T)(img)(_p1##x,_p3##y,z,c), I[13] = (T)(img)(x,_p3##y,z,c), I[14] = (T)(img)(_n1##x,_p3##y,z,c), \ + I[15] = (T)(img)(_n2##x,_p3##y,z,c), I[16] = (T)(img)(_n3##x,_p3##y,z,c), I[17] = (T)(img)(_n4##x,_p3##y,z,c), \ + I[18] = (T)(img)(_p4##x,_p2##y,z,c), I[19] = (T)(img)(_p3##x,_p2##y,z,c), I[20] = (T)(img)(_p2##x,_p2##y,z,c), \ + I[21] = (T)(img)(_p1##x,_p2##y,z,c), I[22] = (T)(img)(x,_p2##y,z,c), I[23] = (T)(img)(_n1##x,_p2##y,z,c), \ + I[24] = (T)(img)(_n2##x,_p2##y,z,c), I[25] = (T)(img)(_n3##x,_p2##y,z,c), I[26] = (T)(img)(_n4##x,_p2##y,z,c), \ + I[27] = (T)(img)(_p4##x,_p1##y,z,c), I[28] = (T)(img)(_p3##x,_p1##y,z,c), I[29] = (T)(img)(_p2##x,_p1##y,z,c), \ + I[30] = (T)(img)(_p1##x,_p1##y,z,c), I[31] = (T)(img)(x,_p1##y,z,c), I[32] = (T)(img)(_n1##x,_p1##y,z,c), \ + I[33] = (T)(img)(_n2##x,_p1##y,z,c), I[34] = (T)(img)(_n3##x,_p1##y,z,c), I[35] = (T)(img)(_n4##x,_p1##y,z,c), \ + I[36] = (T)(img)(_p4##x,y,z,c), I[37] = (T)(img)(_p3##x,y,z,c), I[38] = (T)(img)(_p2##x,y,z,c), \ + I[39] = (T)(img)(_p1##x,y,z,c), I[40] = (T)(img)(x,y,z,c), I[41] = (T)(img)(_n1##x,y,z,c), \ + I[42] = (T)(img)(_n2##x,y,z,c), I[43] = (T)(img)(_n3##x,y,z,c), I[44] = (T)(img)(_n4##x,y,z,c), \ + I[45] = (T)(img)(_p4##x,_n1##y,z,c), I[46] = (T)(img)(_p3##x,_n1##y,z,c), I[47] = (T)(img)(_p2##x,_n1##y,z,c), \ + I[48] = (T)(img)(_p1##x,_n1##y,z,c), I[49] = (T)(img)(x,_n1##y,z,c), I[50] = (T)(img)(_n1##x,_n1##y,z,c), \ + I[51] = (T)(img)(_n2##x,_n1##y,z,c), I[52] = (T)(img)(_n3##x,_n1##y,z,c), I[53] = (T)(img)(_n4##x,_n1##y,z,c), \ + I[54] = (T)(img)(_p4##x,_n2##y,z,c), I[55] = (T)(img)(_p3##x,_n2##y,z,c), I[56] = (T)(img)(_p2##x,_n2##y,z,c), \ + I[57] = (T)(img)(_p1##x,_n2##y,z,c), I[58] = (T)(img)(x,_n2##y,z,c), I[59] = (T)(img)(_n1##x,_n2##y,z,c), \ + I[60] = (T)(img)(_n2##x,_n2##y,z,c), I[61] = (T)(img)(_n3##x,_n2##y,z,c), I[62] = (T)(img)(_n4##x,_n2##y,z,c), \ + I[63] = (T)(img)(_p4##x,_n3##y,z,c), I[64] = (T)(img)(_p3##x,_n3##y,z,c), I[65] = (T)(img)(_p2##x,_n3##y,z,c), \ + I[66] = (T)(img)(_p1##x,_n3##y,z,c), I[67] = (T)(img)(x,_n3##y,z,c), I[68] = (T)(img)(_n1##x,_n3##y,z,c), \ + I[69] = (T)(img)(_n2##x,_n3##y,z,c), I[70] = (T)(img)(_n3##x,_n3##y,z,c), I[71] = (T)(img)(_n4##x,_n3##y,z,c), \ + I[72] = (T)(img)(_p4##x,_n4##y,z,c), I[73] = (T)(img)(_p3##x,_n4##y,z,c), I[74] = (T)(img)(_p2##x,_n4##y,z,c), \ + I[75] = (T)(img)(_p1##x,_n4##y,z,c), I[76] = (T)(img)(x,_n4##y,z,c), I[77] = (T)(img)(_n1##x,_n4##y,z,c), \ + I[78] = (T)(img)(_n2##x,_n4##y,z,c), I[79] = (T)(img)(_n3##x,_n4##y,z,c), I[80] = (T)(img)(_n4##x,_n4##y,z,c) + +#define cimg_get2x2x2(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), \ + I[3] = (T)(img)(_n1##x,_n1##y,z,c), I[4] = (T)(img)(x,y,_n1##z,c), I[5] = (T)(img)(_n1##x,y,_n1##z,c), \ + I[6] = (T)(img)(x,_n1##y,_n1##z,c), I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +#define cimg_get3x3x3(img,x,y,z,c,I,T) \ + I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c), I[1] = (T)(img)(x,_p1##y,_p1##z,c), \ + I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c), I[3] = (T)(img)(_p1##x,y,_p1##z,c), I[4] = (T)(img)(x,y,_p1##z,c), \ + I[5] = (T)(img)(_n1##x,y,_p1##z,c), I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c), I[7] = (T)(img)(x,_n1##y,_p1##z,c), \ + I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c), I[9] = (T)(img)(_p1##x,_p1##y,z,c), I[10] = (T)(img)(x,_p1##y,z,c), \ + I[11] = (T)(img)(_n1##x,_p1##y,z,c), I[12] = (T)(img)(_p1##x,y,z,c), I[13] = (T)(img)(x,y,z,c), \ + I[14] = (T)(img)(_n1##x,y,z,c), I[15] = (T)(img)(_p1##x,_n1##y,z,c), I[16] = (T)(img)(x,_n1##y,z,c), \ + I[17] = (T)(img)(_n1##x,_n1##y,z,c), I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c), I[19] = (T)(img)(x,_p1##y,_n1##z,c), \ + I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c), I[21] = (T)(img)(_p1##x,y,_n1##z,c), I[22] = (T)(img)(x,y,_n1##z,c), \ + I[23] = (T)(img)(_n1##x,y,_n1##z,c), I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c), I[25] = (T)(img)(x,_n1##y,_n1##z,c), \ + I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c) + +// Macros to perform various image loops. +// +// These macros are simpler to use than loops with C++ iterators. +#define cimg_for(img,ptrs,T_ptrs) \ + for (T_ptrs *ptrs = (img)._data, *_max##ptrs = (img)._data + (img).size(); ptrs<_max##ptrs; ++ptrs) +#define cimg_rof(img,ptrs,T_ptrs) for (T_ptrs *ptrs = (img)._data + (img).size() - 1; ptrs>=(img)._data; --ptrs) +#define cimg_foroff(img,off) for (cimg_ulong off = 0, _max##off = (img).size(); off<_max##off; ++off) + +#define cimg_for1(bound,i) for (int i = 0; i<(int)(bound); ++i) +#define cimg_forX(img,x) cimg_for1((img)._width,x) +#define cimg_forY(img,y) cimg_for1((img)._height,y) +#define cimg_forZ(img,z) cimg_for1((img)._depth,z) +#define cimg_forC(img,c) cimg_for1((img)._spectrum,c) +#define cimg_forXY(img,x,y) cimg_forY(img,y) cimg_forX(img,x) +#define cimg_forXZ(img,x,z) cimg_forZ(img,z) cimg_forX(img,x) +#define cimg_forYZ(img,y,z) cimg_forZ(img,z) cimg_forY(img,y) +#define cimg_forXC(img,x,c) cimg_forC(img,c) cimg_forX(img,x) +#define cimg_forYC(img,y,c) cimg_forC(img,c) cimg_forY(img,y) +#define cimg_forZC(img,z,c) cimg_forC(img,c) cimg_forZ(img,z) +#define cimg_forXYZ(img,x,y,z) cimg_forZ(img,z) cimg_forXY(img,x,y) +#define cimg_forXYC(img,x,y,c) cimg_forC(img,c) cimg_forXY(img,x,y) +#define cimg_forXZC(img,x,z,c) cimg_forC(img,c) cimg_forXZ(img,x,z) +#define cimg_forYZC(img,y,z,c) cimg_forC(img,c) cimg_forYZ(img,y,z) +#define cimg_forXYZC(img,x,y,z,c) cimg_forC(img,c) cimg_forXYZ(img,x,y,z) + +#define cimg_rof1(bound,i) for (int i = (int)(bound) - 1; i>=0; --i) +#define cimg_rofX(img,x) cimg_rof1((img)._width,x) +#define cimg_rofY(img,y) cimg_rof1((img)._height,y) +#define cimg_rofZ(img,z) cimg_rof1((img)._depth,z) +#define cimg_rofC(img,c) cimg_rof1((img)._spectrum,c) +#define cimg_rofXY(img,x,y) cimg_rofY(img,y) cimg_rofX(img,x) +#define cimg_rofXZ(img,x,z) cimg_rofZ(img,z) cimg_rofX(img,x) +#define cimg_rofYZ(img,y,z) cimg_rofZ(img,z) cimg_rofY(img,y) +#define cimg_rofXC(img,x,c) cimg_rofC(img,c) cimg_rofX(img,x) +#define cimg_rofYC(img,y,c) cimg_rofC(img,c) cimg_rofY(img,y) +#define cimg_rofZC(img,z,c) cimg_rofC(img,c) cimg_rofZ(img,z) +#define cimg_rofXYZ(img,x,y,z) cimg_rofZ(img,z) cimg_rofXY(img,x,y) +#define cimg_rofXYC(img,x,y,c) cimg_rofC(img,c) cimg_rofXY(img,x,y) +#define cimg_rofXZC(img,x,z,c) cimg_rofC(img,c) cimg_rofXZ(img,x,z) +#define cimg_rofYZC(img,y,z,c) cimg_rofC(img,c) cimg_rofYZ(img,y,z) +#define cimg_rofXYZC(img,x,y,z,c) cimg_rofC(img,c) cimg_rofXYZ(img,x,y,z) + +#define cimg_for_in1(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), _max##i = (int)(i1)<(int)(bound)?(int)(i1):(int)(bound) - 1; i<=_max##i; ++i) +#define cimg_for_inX(img,x0,x1,x) cimg_for_in1((img)._width,x0,x1,x) +#define cimg_for_inY(img,y0,y1,y) cimg_for_in1((img)._height,y0,y1,y) +#define cimg_for_inZ(img,z0,z1,z) cimg_for_in1((img)._depth,z0,z1,z) +#define cimg_for_inC(img,c0,c1,c) cimg_for_in1((img)._spectrum,c0,c1,c) +#define cimg_for_inXY(img,x0,y0,x1,y1,x,y) cimg_for_inY(img,y0,y1,y) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXZ(img,x0,z0,x1,z1,x,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inXC(img,x0,c0,x1,c1,x,c) cimg_for_inC(img,c0,c1,c) cimg_for_inX(img,x0,x1,x) +#define cimg_for_inYZ(img,y0,z0,y1,z1,y,z) cimg_for_inZ(img,x0,z1,z) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inYC(img,y0,c0,y1,c1,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inY(img,y0,y1,y) +#define cimg_for_inZC(img,z0,c0,z1,c1,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inZ(img,z0,z1,z) +#define cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_inZ(img,z0,z1,z) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXY(img,x0,y0,x1,y1,x,y) +#define cimg_for_inXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inXZ(img,x0,z0,x1,z1,x,z) +#define cimg_for_inYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_inC(img,c0,c1,c) cimg_for_inYZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_inXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_inC(img,c0,c1,c) cimg_for_inXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_insideX(img,x,n) cimg_for_inX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_insideY(img,y,n) cimg_for_inY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_insideZ(img,z,n) cimg_for_inZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_insideC(img,c,n) cimg_for_inC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_insideXY(img,x,y,n) cimg_for_inXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_insideXYZ(img,x,y,z,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_insideXYZC(img,x,y,z,c,n) \ + cimg_for_inXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) + +#define cimg_for_out1(boundi,i0,i1,i) \ + for (int i = (int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); ++i, i = i==(int)(i0)?(int)(i1) + 1:i) +#define cimg_for_out2(boundi,boundj,i0,j0,i1,j1,i,j) \ + for (int j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out3(boundi,boundj,boundk,i0,j0,k0,i1,j1,k1,i,j,k) \ + for (int k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k?0:(int)(i0)>0?0:(int)(i1) + 1; i<(int)(boundi); \ + ++i, i = _n1j || _n1k?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_out4(boundi,boundj,boundk,boundl,i0,j0,k0,l0,i1,j1,k1,l1,i,j,k,l) \ + for (int l = 0; l<(int)(boundl); ++l) \ + for (int _n1l = (int)(l<(int)(l0) || l>(int)(l1)), k = 0; k<(int)(boundk); ++k) \ + for (int _n1k = (int)(k<(int)(k0) || k>(int)(k1)), j = 0; j<(int)(boundj); ++j) \ + for (int _n1j = (int)(j<(int)(j0) || j>(int)(j1)), i = _n1j || _n1k || _n1l?0:(int)(i0)>0?0:(int)(i1) + 1; \ + i<(int)(boundi); ++i, i = _n1j || _n1k || _n1l?i:(i==(int)(i0)?(int)(i1) + 1:i)) +#define cimg_for_outX(img,x0,x1,x) cimg_for_out1((img)._width,x0,x1,x) +#define cimg_for_outY(img,y0,y1,y) cimg_for_out1((img)._height,y0,y1,y) +#define cimg_for_outZ(img,z0,z1,z) cimg_for_out1((img)._depth,z0,z1,z) +#define cimg_for_outC(img,c0,c1,c) cimg_for_out1((img)._spectrum,c0,c1,c) +#define cimg_for_outXY(img,x0,y0,x1,y1,x,y) cimg_for_out2((img)._width,(img)._height,x0,y0,x1,y1,x,y) +#define cimg_for_outXZ(img,x0,z0,x1,z1,x,z) cimg_for_out2((img)._width,(img)._depth,x0,z0,x1,z1,x,z) +#define cimg_for_outXC(img,x0,c0,x1,c1,x,c) cimg_for_out2((img)._width,(img)._spectrum,x0,c0,x1,c1,x,c) +#define cimg_for_outYZ(img,y0,z0,y1,z1,y,z) cimg_for_out2((img)._height,(img)._depth,y0,z0,y1,z1,y,z) +#define cimg_for_outYC(img,y0,c0,y1,c1,y,c) cimg_for_out2((img)._height,(img)._spectrum,y0,c0,y1,c1,y,c) +#define cimg_for_outZC(img,z0,c0,z1,c1,z,c) cimg_for_out2((img)._depth,(img)._spectrum,z0,c0,z1,c1,z,c) +#define cimg_for_outXYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) \ + cimg_for_out3((img)._width,(img)._height,(img)._depth,x0,y0,z0,x1,y1,z1,x,y,z) +#define cimg_for_outXYC(img,x0,y0,c0,x1,y1,c1,x,y,c) \ + cimg_for_out3((img)._width,(img)._height,(img)._spectrum,x0,y0,c0,x1,y1,c1,x,y,c) +#define cimg_for_outXZC(img,x0,z0,c0,x1,z1,c1,x,z,c) \ + cimg_for_out3((img)._width,(img)._depth,(img)._spectrum,x0,z0,c0,x1,z1,c1,x,z,c) +#define cimg_for_outYZC(img,y0,z0,c0,y1,z1,c1,y,z,c) \ + cimg_for_out3((img)._height,(img)._depth,(img)._spectrum,y0,z0,c0,y1,z1,c1,y,z,c) +#define cimg_for_outXYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_out4((img)._width,(img)._height,(img)._depth,(img)._spectrum,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) +#define cimg_for_borderX(img,x,n) cimg_for_outX(img,n,(img)._width - 1 - (n),x) +#define cimg_for_borderY(img,y,n) cimg_for_outY(img,n,(img)._height - 1 - (n),y) +#define cimg_for_borderZ(img,z,n) cimg_for_outZ(img,n,(img)._depth - 1 - (n),z) +#define cimg_for_borderC(img,c,n) cimg_for_outC(img,n,(img)._spectrum - 1 - (n),c) +#define cimg_for_borderXY(img,x,y,n) cimg_for_outXY(img,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),x,y) +#define cimg_for_borderXYZ(img,x,y,z,n) \ + cimg_for_outXYZ(img,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n),(img)._depth - 1 - (n),x,y,z) +#define cimg_for_borderXYZC(img,x,y,z,c,n) \ + cimg_for_outXYZC(img,n,n,n,n,(img)._width - 1 - (n),(img)._height - 1 - (n), \ + (img)._depth - 1 - (n),(img)._spectrum - 1 - (n),x,y,z,c) + +#define cimg_for_spiralXY(img,x,y) \ + for (int x = 0, y = 0, _n1##x = 1, _n1##y = (img).width()*(img).height(); _n1##y; \ + --_n1##y, _n1##x+=(_n1##x>>2) - ((!(_n1##x&3)?--y:((_n1##x&3)==1?(img)._width - 1 - ++x:\ + ((_n1##x&3)==2?(img)._height - 1 - ++y:--x))))?0:1) + +#define cimg_for_lineXY(x,y,x0,y0,x1,y1) \ + for (int x = (int)(x0), y = (int)(y0), _sx = 1, _sy = 1, _steep = 0, \ + _dx=(x1)>(x0)?(int)(x1) - (int)(x0):(_sx=-1,(int)(x0) - (int)(x1)), \ + _dy=(y1)>(y0)?(int)(y1) - (int)(y0):(_sy=-1,(int)(y0) - (int)(y1)), \ + _counter = _dx, \ + _err = _dx>_dy?(_dy>>1):((_steep=1),(_counter=_dy),(_dx>>1)); \ + _counter>=0; \ + --_counter, x+=_steep? \ + (y+=_sy,(_err-=_dx)<0?_err+=_dy,_sx:0): \ + (y+=(_err-=_dy)<0?_err+=_dx,_sy:0,_sx)) + +#define cimg_for2(bound,i) \ + for (int i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + ++i, ++_n1##i) +#define cimg_for2X(img,x) cimg_for2((img)._width,x) +#define cimg_for2Y(img,y) cimg_for2((img)._height,y) +#define cimg_for2Z(img,z) cimg_for2((img)._depth,z) +#define cimg_for2C(img,c) cimg_for2((img)._spectrum,c) +#define cimg_for2XY(img,x,y) cimg_for2Y(img,y) cimg_for2X(img,x) +#define cimg_for2XZ(img,x,z) cimg_for2Z(img,z) cimg_for2X(img,x) +#define cimg_for2XC(img,x,c) cimg_for2C(img,c) cimg_for2X(img,x) +#define cimg_for2YZ(img,y,z) cimg_for2Z(img,z) cimg_for2Y(img,y) +#define cimg_for2YC(img,y,c) cimg_for2C(img,c) cimg_for2Y(img,y) +#define cimg_for2ZC(img,z,c) cimg_for2C(img,c) cimg_for2Z(img,z) +#define cimg_for2XYZ(img,x,y,z) cimg_for2Z(img,z) cimg_for2XY(img,x,y) +#define cimg_for2XZC(img,x,z,c) cimg_for2C(img,c) cimg_for2XZ(img,x,z) +#define cimg_for2YZC(img,y,z,c) cimg_for2C(img,c) cimg_for2YZ(img,y,z) +#define cimg_for2XYZC(img,x,y,z,c) cimg_for2C(img,c) cimg_for2XYZ(img,x,y,z) + +#define cimg_for_in2(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + ++i, ++_n1##i) +#define cimg_for_in2X(img,x0,x1,x) cimg_for_in2((img)._width,x0,x1,x) +#define cimg_for_in2Y(img,y0,y1,y) cimg_for_in2((img)._height,y0,y1,y) +#define cimg_for_in2Z(img,z0,z1,z) cimg_for_in2((img)._depth,z0,z1,z) +#define cimg_for_in2C(img,c0,c1,c) cimg_for_in2((img)._spectrum,c0,c1,c) +#define cimg_for_in2XY(img,x0,y0,x1,y1,x,y) cimg_for_in2Y(img,y0,y1,y) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XZ(img,x0,z0,x1,z1,x,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2XC(img,x0,c0,x1,c1,x,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2X(img,x0,x1,x) +#define cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2YC(img,y0,c0,y1,c1,y,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Y(img,y0,y1,y) +#define cimg_for_in2ZC(img,z0,c0,z1,c1,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2Z(img,z0,z1,z) +#define cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in2Z(img,z0,z1,z) cimg_for_in2XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in2XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in2YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in2C(img,c0,c1,c) cimg_for_in2YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in2XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in2C(img,c0,c1,c) cimg_for_in2XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i) +#define cimg_for3X(img,x) cimg_for3((img)._width,x) +#define cimg_for3Y(img,y) cimg_for3((img)._height,y) +#define cimg_for3Z(img,z) cimg_for3((img)._depth,z) +#define cimg_for3C(img,c) cimg_for3((img)._spectrum,c) +#define cimg_for3XY(img,x,y) cimg_for3Y(img,y) cimg_for3X(img,x) +#define cimg_for3XZ(img,x,z) cimg_for3Z(img,z) cimg_for3X(img,x) +#define cimg_for3XC(img,x,c) cimg_for3C(img,c) cimg_for3X(img,x) +#define cimg_for3YZ(img,y,z) cimg_for3Z(img,z) cimg_for3Y(img,y) +#define cimg_for3YC(img,y,c) cimg_for3C(img,c) cimg_for3Y(img,y) +#define cimg_for3ZC(img,z,c) cimg_for3C(img,c) cimg_for3Z(img,z) +#define cimg_for3XYZ(img,x,y,z) cimg_for3Z(img,z) cimg_for3XY(img,x,y) +#define cimg_for3XZC(img,x,z,c) cimg_for3C(img,c) cimg_for3XZ(img,x,z) +#define cimg_for3YZC(img,y,z,c) cimg_for3C(img,c) cimg_for3YZ(img,y,z) +#define cimg_for3XYZC(img,x,y,z,c) cimg_for3C(img,c) cimg_for3XYZ(img,x,y,z) + +#define cimg_for_in3(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1; \ + i<=(int)(i1) && (_n1##i<(int)(bound) || i==--_n1##i); \ + _p1##i = i++, ++_n1##i) +#define cimg_for_in3X(img,x0,x1,x) cimg_for_in3((img)._width,x0,x1,x) +#define cimg_for_in3Y(img,y0,y1,y) cimg_for_in3((img)._height,y0,y1,y) +#define cimg_for_in3Z(img,z0,z1,z) cimg_for_in3((img)._depth,z0,z1,z) +#define cimg_for_in3C(img,c0,c1,c) cimg_for_in3((img)._spectrum,c0,c1,c) +#define cimg_for_in3XY(img,x0,y0,x1,y1,x,y) cimg_for_in3Y(img,y0,y1,y) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XZ(img,x0,z0,x1,z1,x,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3XC(img,x0,c0,x1,c1,x,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3X(img,x0,x1,x) +#define cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3YC(img,y0,c0,y1,c1,y,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Y(img,y0,y1,y) +#define cimg_for_in3ZC(img,z0,c0,z1,c1,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3Z(img,z0,z1,z) +#define cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in3Z(img,z0,z1,z) cimg_for_in3XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in3XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in3YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in3C(img,c0,c1,c) cimg_for_in3YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in3XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in3C(img,c0,c1,c) cimg_for_in3XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for4(bound,i) \ + for (int i = 0, _p1##i = 0, _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for4X(img,x) cimg_for4((img)._width,x) +#define cimg_for4Y(img,y) cimg_for4((img)._height,y) +#define cimg_for4Z(img,z) cimg_for4((img)._depth,z) +#define cimg_for4C(img,c) cimg_for4((img)._spectrum,c) +#define cimg_for4XY(img,x,y) cimg_for4Y(img,y) cimg_for4X(img,x) +#define cimg_for4XZ(img,x,z) cimg_for4Z(img,z) cimg_for4X(img,x) +#define cimg_for4XC(img,x,c) cimg_for4C(img,c) cimg_for4X(img,x) +#define cimg_for4YZ(img,y,z) cimg_for4Z(img,z) cimg_for4Y(img,y) +#define cimg_for4YC(img,y,c) cimg_for4C(img,c) cimg_for4Y(img,y) +#define cimg_for4ZC(img,z,c) cimg_for4C(img,c) cimg_for4Z(img,z) +#define cimg_for4XYZ(img,x,y,z) cimg_for4Z(img,z) cimg_for4XY(img,x,y) +#define cimg_for4XZC(img,x,z,c) cimg_for4C(img,c) cimg_for4XZ(img,x,z) +#define cimg_for4YZC(img,y,z,c) cimg_for4C(img,c) cimg_for4YZ(img,y,z) +#define cimg_for4XYZC(img,x,y,z,c) cimg_for4C(img,c) cimg_for4XYZ(img,x,y,z) + +#define cimg_for_in4(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in4X(img,x0,x1,x) cimg_for_in4((img)._width,x0,x1,x) +#define cimg_for_in4Y(img,y0,y1,y) cimg_for_in4((img)._height,y0,y1,y) +#define cimg_for_in4Z(img,z0,z1,z) cimg_for_in4((img)._depth,z0,z1,z) +#define cimg_for_in4C(img,c0,c1,c) cimg_for_in4((img)._spectrum,c0,c1,c) +#define cimg_for_in4XY(img,x0,y0,x1,y1,x,y) cimg_for_in4Y(img,y0,y1,y) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XZ(img,x0,z0,x1,z1,x,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4XC(img,x0,c0,x1,c1,x,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4X(img,x0,x1,x) +#define cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4YC(img,y0,c0,y1,c1,y,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Y(img,y0,y1,y) +#define cimg_for_in4ZC(img,z0,c0,z1,c1,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4Z(img,z0,z1,z) +#define cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in4Z(img,z0,z1,z) cimg_for_in4XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in4XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in4YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in4C(img,c0,c1,c) cimg_for_in4YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in4XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in4C(img,c0,c1,c) cimg_for_in4XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for5(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2; \ + _n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for5X(img,x) cimg_for5((img)._width,x) +#define cimg_for5Y(img,y) cimg_for5((img)._height,y) +#define cimg_for5Z(img,z) cimg_for5((img)._depth,z) +#define cimg_for5C(img,c) cimg_for5((img)._spectrum,c) +#define cimg_for5XY(img,x,y) cimg_for5Y(img,y) cimg_for5X(img,x) +#define cimg_for5XZ(img,x,z) cimg_for5Z(img,z) cimg_for5X(img,x) +#define cimg_for5XC(img,x,c) cimg_for5C(img,c) cimg_for5X(img,x) +#define cimg_for5YZ(img,y,z) cimg_for5Z(img,z) cimg_for5Y(img,y) +#define cimg_for5YC(img,y,c) cimg_for5C(img,c) cimg_for5Y(img,y) +#define cimg_for5ZC(img,z,c) cimg_for5C(img,c) cimg_for5Z(img,z) +#define cimg_for5XYZ(img,x,y,z) cimg_for5Z(img,z) cimg_for5XY(img,x,y) +#define cimg_for5XZC(img,x,z,c) cimg_for5C(img,c) cimg_for5XZ(img,x,z) +#define cimg_for5YZC(img,y,z,c) cimg_for5C(img,c) cimg_for5YZ(img,y,z) +#define cimg_for5XYZC(img,x,y,z,c) cimg_for5C(img,c) cimg_for5XYZ(img,x,y,z) + +#define cimg_for_in5(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2; \ + i<=(int)(i1) && (_n2##i<(int)(bound) || _n1##i==--_n2##i || i==(_n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i) +#define cimg_for_in5X(img,x0,x1,x) cimg_for_in5((img)._width,x0,x1,x) +#define cimg_for_in5Y(img,y0,y1,y) cimg_for_in5((img)._height,y0,y1,y) +#define cimg_for_in5Z(img,z0,z1,z) cimg_for_in5((img)._depth,z0,z1,z) +#define cimg_for_in5C(img,c0,c1,c) cimg_for_in5((img)._spectrum,c0,c1,c) +#define cimg_for_in5XY(img,x0,y0,x1,y1,x,y) cimg_for_in5Y(img,y0,y1,y) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XZ(img,x0,z0,x1,z1,x,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5XC(img,x0,c0,x1,c1,x,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5X(img,x0,x1,x) +#define cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5YC(img,y0,c0,y1,c1,y,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Y(img,y0,y1,y) +#define cimg_for_in5ZC(img,z0,c0,z1,c1,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5Z(img,z0,z1,z) +#define cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in5Z(img,z0,z1,z) cimg_for_in5XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in5XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in5YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in5C(img,c0,c1,c) cimg_for_in5YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in5XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in5C(img,c0,c1,c) cimg_for_in5XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for6(bound,i) \ + for (int i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for6X(img,x) cimg_for6((img)._width,x) +#define cimg_for6Y(img,y) cimg_for6((img)._height,y) +#define cimg_for6Z(img,z) cimg_for6((img)._depth,z) +#define cimg_for6C(img,c) cimg_for6((img)._spectrum,c) +#define cimg_for6XY(img,x,y) cimg_for6Y(img,y) cimg_for6X(img,x) +#define cimg_for6XZ(img,x,z) cimg_for6Z(img,z) cimg_for6X(img,x) +#define cimg_for6XC(img,x,c) cimg_for6C(img,c) cimg_for6X(img,x) +#define cimg_for6YZ(img,y,z) cimg_for6Z(img,z) cimg_for6Y(img,y) +#define cimg_for6YC(img,y,c) cimg_for6C(img,c) cimg_for6Y(img,y) +#define cimg_for6ZC(img,z,c) cimg_for6C(img,c) cimg_for6Z(img,z) +#define cimg_for6XYZ(img,x,y,z) cimg_for6Z(img,z) cimg_for6XY(img,x,y) +#define cimg_for6XZC(img,x,z,c) cimg_for6C(img,c) cimg_for6XZ(img,x,z) +#define cimg_for6YZC(img,y,z,c) cimg_for6C(img,c) cimg_for6YZ(img,y,z) +#define cimg_for6XYZC(img,x,y,z,c) cimg_for6C(img,c) cimg_for6XYZ(img,x,y,z) + +#define cimg_for_in6(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in6X(img,x0,x1,x) cimg_for_in6((img)._width,x0,x1,x) +#define cimg_for_in6Y(img,y0,y1,y) cimg_for_in6((img)._height,y0,y1,y) +#define cimg_for_in6Z(img,z0,z1,z) cimg_for_in6((img)._depth,z0,z1,z) +#define cimg_for_in6C(img,c0,c1,c) cimg_for_in6((img)._spectrum,c0,c1,c) +#define cimg_for_in6XY(img,x0,y0,x1,y1,x,y) cimg_for_in6Y(img,y0,y1,y) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XZ(img,x0,z0,x1,z1,x,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6XC(img,x0,c0,x1,c1,x,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6X(img,x0,x1,x) +#define cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6YC(img,y0,c0,y1,c1,y,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Y(img,y0,y1,y) +#define cimg_for_in6ZC(img,z0,c0,z1,c1,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6Z(img,z0,z1,z) +#define cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in6Z(img,z0,z1,z) cimg_for_in6XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in6XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in6YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in6C(img,c0,c1,c) cimg_for_in6YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in6XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in6C(img,c0,c1,c) cimg_for_in6XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for7(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3; \ + _n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for7X(img,x) cimg_for7((img)._width,x) +#define cimg_for7Y(img,y) cimg_for7((img)._height,y) +#define cimg_for7Z(img,z) cimg_for7((img)._depth,z) +#define cimg_for7C(img,c) cimg_for7((img)._spectrum,c) +#define cimg_for7XY(img,x,y) cimg_for7Y(img,y) cimg_for7X(img,x) +#define cimg_for7XZ(img,x,z) cimg_for7Z(img,z) cimg_for7X(img,x) +#define cimg_for7XC(img,x,c) cimg_for7C(img,c) cimg_for7X(img,x) +#define cimg_for7YZ(img,y,z) cimg_for7Z(img,z) cimg_for7Y(img,y) +#define cimg_for7YC(img,y,c) cimg_for7C(img,c) cimg_for7Y(img,y) +#define cimg_for7ZC(img,z,c) cimg_for7C(img,c) cimg_for7Z(img,z) +#define cimg_for7XYZ(img,x,y,z) cimg_for7Z(img,z) cimg_for7XY(img,x,y) +#define cimg_for7XZC(img,x,z,c) cimg_for7C(img,c) cimg_for7XZ(img,x,z) +#define cimg_for7YZC(img,y,z,c) cimg_for7C(img,c) cimg_for7YZ(img,y,z) +#define cimg_for7XYZC(img,x,y,z,c) cimg_for7C(img,c) cimg_for7XYZ(img,x,y,z) + +#define cimg_for_in7(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3; \ + i<=(int)(i1) && \ + (_n3##i<(int)(bound) || _n2##i==--_n3##i || _n1##i==--_n2##i || i==(_n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i) +#define cimg_for_in7X(img,x0,x1,x) cimg_for_in7((img)._width,x0,x1,x) +#define cimg_for_in7Y(img,y0,y1,y) cimg_for_in7((img)._height,y0,y1,y) +#define cimg_for_in7Z(img,z0,z1,z) cimg_for_in7((img)._depth,z0,z1,z) +#define cimg_for_in7C(img,c0,c1,c) cimg_for_in7((img)._spectrum,c0,c1,c) +#define cimg_for_in7XY(img,x0,y0,x1,y1,x,y) cimg_for_in7Y(img,y0,y1,y) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XZ(img,x0,z0,x1,z1,x,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7XC(img,x0,c0,x1,c1,x,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7X(img,x0,x1,x) +#define cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7YC(img,y0,c0,y1,c1,y,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Y(img,y0,y1,y) +#define cimg_for_in7ZC(img,z0,c0,z1,c1,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7Z(img,z0,z1,z) +#define cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in7Z(img,z0,z1,z) cimg_for_in7XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in7XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in7YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in7C(img,c0,c1,c) cimg_for_in7YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in7XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in7C(img,c0,c1,c) cimg_for_in7XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for8(bound,i) \ + for (int i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for8X(img,x) cimg_for8((img)._width,x) +#define cimg_for8Y(img,y) cimg_for8((img)._height,y) +#define cimg_for8Z(img,z) cimg_for8((img)._depth,z) +#define cimg_for8C(img,c) cimg_for8((img)._spectrum,c) +#define cimg_for8XY(img,x,y) cimg_for8Y(img,y) cimg_for8X(img,x) +#define cimg_for8XZ(img,x,z) cimg_for8Z(img,z) cimg_for8X(img,x) +#define cimg_for8XC(img,x,c) cimg_for8C(img,c) cimg_for8X(img,x) +#define cimg_for8YZ(img,y,z) cimg_for8Z(img,z) cimg_for8Y(img,y) +#define cimg_for8YC(img,y,c) cimg_for8C(img,c) cimg_for8Y(img,y) +#define cimg_for8ZC(img,z,c) cimg_for8C(img,c) cimg_for8Z(img,z) +#define cimg_for8XYZ(img,x,y,z) cimg_for8Z(img,z) cimg_for8XY(img,x,y) +#define cimg_for8XZC(img,x,z,c) cimg_for8C(img,c) cimg_for8XZ(img,x,z) +#define cimg_for8YZC(img,y,z,c) cimg_for8C(img,c) cimg_for8YZ(img,y,z) +#define cimg_for8XYZC(img,x,y,z,c) cimg_for8C(img,c) cimg_for8XYZ(img,x,y,z) + +#define cimg_for_in8(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in8X(img,x0,x1,x) cimg_for_in8((img)._width,x0,x1,x) +#define cimg_for_in8Y(img,y0,y1,y) cimg_for_in8((img)._height,y0,y1,y) +#define cimg_for_in8Z(img,z0,z1,z) cimg_for_in8((img)._depth,z0,z1,z) +#define cimg_for_in8C(img,c0,c1,c) cimg_for_in8((img)._spectrum,c0,c1,c) +#define cimg_for_in8XY(img,x0,y0,x1,y1,x,y) cimg_for_in8Y(img,y0,y1,y) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XZ(img,x0,z0,x1,z1,x,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8XC(img,x0,c0,x1,c1,x,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8X(img,x0,x1,x) +#define cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8YC(img,y0,c0,y1,c1,y,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Y(img,y0,y1,y) +#define cimg_for_in8ZC(img,z0,c0,z1,c1,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8Z(img,z0,z1,z) +#define cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in8Z(img,z0,z1,z) cimg_for_in8XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in8XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in8YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in8C(img,c0,c1,c) cimg_for_in8YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in8XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in8C(img,c0,c1,c) cimg_for_in8XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for9(bound,i) \ + for (int i = 0, _p4##i = 0, _p3##i = 0, _p2##i = 0, _p1##i = 0, \ + _n1##i = 1>=(int)(bound)?(int)(bound) - 1:1, \ + _n2##i = 2>=(int)(bound)?(int)(bound) - 1:2, \ + _n3##i = 3>=(int)(bound)?(int)(bound) - 1:3, \ + _n4##i = 4>=(int)(bound)?(int)(bound) - 1:4; \ + _n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for9X(img,x) cimg_for9((img)._width,x) +#define cimg_for9Y(img,y) cimg_for9((img)._height,y) +#define cimg_for9Z(img,z) cimg_for9((img)._depth,z) +#define cimg_for9C(img,c) cimg_for9((img)._spectrum,c) +#define cimg_for9XY(img,x,y) cimg_for9Y(img,y) cimg_for9X(img,x) +#define cimg_for9XZ(img,x,z) cimg_for9Z(img,z) cimg_for9X(img,x) +#define cimg_for9XC(img,x,c) cimg_for9C(img,c) cimg_for9X(img,x) +#define cimg_for9YZ(img,y,z) cimg_for9Z(img,z) cimg_for9Y(img,y) +#define cimg_for9YC(img,y,c) cimg_for9C(img,c) cimg_for9Y(img,y) +#define cimg_for9ZC(img,z,c) cimg_for9C(img,c) cimg_for9Z(img,z) +#define cimg_for9XYZ(img,x,y,z) cimg_for9Z(img,z) cimg_for9XY(img,x,y) +#define cimg_for9XZC(img,x,z,c) cimg_for9C(img,c) cimg_for9XZ(img,x,z) +#define cimg_for9YZC(img,y,z,c) cimg_for9C(img,c) cimg_for9YZ(img,y,z) +#define cimg_for9XYZC(img,x,y,z,c) cimg_for9C(img,c) cimg_for9XYZ(img,x,y,z) + +#define cimg_for_in9(bound,i0,i1,i) \ + for (int i = (int)(i0)<0?0:(int)(i0), \ + _p4##i = i - 4<0?0:i - 4, \ + _p3##i = i - 3<0?0:i - 3, \ + _p2##i = i - 2<0?0:i - 2, \ + _p1##i = i - 1<0?0:i - 1, \ + _n1##i = i + 1>=(int)(bound)?(int)(bound) - 1:i + 1, \ + _n2##i = i + 2>=(int)(bound)?(int)(bound) - 1:i + 2, \ + _n3##i = i + 3>=(int)(bound)?(int)(bound) - 1:i + 3, \ + _n4##i = i + 4>=(int)(bound)?(int)(bound) - 1:i + 4; \ + i<=(int)(i1) && (_n4##i<(int)(bound) || _n3##i==--_n4##i || _n2##i==--_n3##i || _n1##i==--_n2##i || \ + i==(_n4##i = _n3##i = _n2##i = --_n1##i)); \ + _p4##i = _p3##i, _p3##i = _p2##i, _p2##i = _p1##i, _p1##i = i++, ++_n1##i, ++_n2##i, ++_n3##i, ++_n4##i) +#define cimg_for_in9X(img,x0,x1,x) cimg_for_in9((img)._width,x0,x1,x) +#define cimg_for_in9Y(img,y0,y1,y) cimg_for_in9((img)._height,y0,y1,y) +#define cimg_for_in9Z(img,z0,z1,z) cimg_for_in9((img)._depth,z0,z1,z) +#define cimg_for_in9C(img,c0,c1,c) cimg_for_in9((img)._spectrum,c0,c1,c) +#define cimg_for_in9XY(img,x0,y0,x1,y1,x,y) cimg_for_in9Y(img,y0,y1,y) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XZ(img,x0,z0,x1,z1,x,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9XC(img,x0,c0,x1,c1,x,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9X(img,x0,x1,x) +#define cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9YC(img,y0,c0,y1,c1,y,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Y(img,y0,y1,y) +#define cimg_for_in9ZC(img,z0,c0,z1,c1,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9Z(img,z0,z1,z) +#define cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) cimg_for_in9Z(img,z0,z1,z) cimg_for_in9XY(img,x0,y0,x1,y1,x,y) +#define cimg_for_in9XZC(img,x0,z0,c0,x1,y1,c1,x,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9XZ(img,x0,y0,x1,y1,x,z) +#define cimg_for_in9YZC(img,y0,z0,c0,y1,z1,c1,y,z,c) cimg_for_in9C(img,c0,c1,c) cimg_for_in9YZ(img,y0,z0,y1,z1,y,z) +#define cimg_for_in9XYZC(img,x0,y0,z0,c0,x1,y1,z1,c1,x,y,z,c) \ + cimg_for_in9C(img,c0,c1,c) cimg_for_in9XYZ(img,x0,y0,z0,x1,y1,z1,x,y,z) + +#define cimg_for2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], \ + I[2] = I[3], \ + ++x, ++_n1##x) + +#define cimg_for3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[4] = (T)(img)(x,y,z,c)), \ + (I[7] = (T)(img)(x,_n1##y,z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for4x4(img,x,y,z,c,I,T) \ + cimg_for4((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = I[5] = (T)(img)(0,y,z,c)), \ + (I[8] = I[9] = (T)(img)(0,_n1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in4x4(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in4((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[4] = (T)(img)(_p1##x,y,z,c)), \ + (I[8] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(x,_p1##y,z,c)), \ + (I[5] = (T)(img)(x,y,z,c)), \ + (I[9] = (T)(img)(x,_n1##y,z,c)), \ + (I[13] = (T)(img)(x,_n2##y,z,c)), \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[6] = (T)(img)(_n1##x,y,z,c)), \ + (I[10] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[3] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[7] = (T)(img)(_n2##x,y,z,c)), \ + (I[11] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], \ + I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for5x5(img,x,y,z,c,I,T) \ + cimg_for5((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = I[6] = I[7] = (T)(img)(0,_p1##y,z,c)), \ + (I[10] = I[11] = I[12] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = I[17] = (T)(img)(0,_n1##y,z,c)), \ + (I[20] = I[21] = I[22] = (T)(img)(0,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + 2>=(img)._width?(img).width() - 1:2); \ + (_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for_in5x5(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in5((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[5] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[10] = (T)(img)(_p2##x,y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[11] = (T)(img)(_p1##x,y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[7] = (T)(img)(x,_p1##y,z,c)), \ + (I[12] = (T)(img)(x,y,z,c)), \ + (I[17] = (T)(img)(x,_n1##y,z,c)), \ + (I[22] = (T)(img)(x,_n2##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_n1##x,y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_n2##y,z,c)), \ + x + 2>=(int)(img)._width?(img).width() - 1:x + 2); \ + x<=(int)(x1) && ((_n2##x<(img).width() && ( \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n2##x,y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_n2##y,z,c)),1)) || \ + _n1##x==--_n2##x || x==(_n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], \ + I[5] = I[6], I[6] = I[7], I[7] = I[8], I[8] = I[9], \ + I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], \ + I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], \ + I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x) + +#define cimg_for6x6(img,x,y,z,c,I,T) \ + cimg_for6((img)._height,y) for (int x = 0, \ + _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = I[7] = I[8] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = I[14] = (T)(img)(0,y,z,c)), \ + (I[18] = I[19] = I[20] = (T)(img)(0,_n1##y,z,c)), \ + (I[24] = I[25] = I[26] = (T)(img)(0,_n2##y,z,c)), \ + (I[30] = I[31] = I[32] = (T)(img)(0,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in6x6(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in6((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)x0, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[6] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p2##x,y,z,c)), \ + (I[18] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[24] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[30] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[7] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[13] = (T)(img)(_p1##x,y,z,c)), \ + (I[19] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[25] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[31] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(x,_p2##y,z,c)), \ + (I[8] = (T)(img)(x,_p1##y,z,c)), \ + (I[14] = (T)(img)(x,y,z,c)), \ + (I[20] = (T)(img)(x,_n1##y,z,c)), \ + (I[26] = (T)(img)(x,_n2##y,z,c)), \ + (I[32] = (T)(img)(x,_n3##y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[9] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[15] = (T)(img)(_n1##x,y,z,c)), \ + (I[21] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[27] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[33] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[10] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[16] = (T)(img)(_n2##x,y,z,c)), \ + (I[22] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[28] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[34] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[5] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[11] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[17] = (T)(img)(_n3##x,y,z,c)), \ + (I[23] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[29] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[35] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3## x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], \ + I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], \ + I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], I[34] = I[35], \ + _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for7x7(img,x,y,z,c,I,T) \ + cimg_for7((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=(img)._width?(img).width() - 1:1, \ + _n2##x = 2>=(img)._width?(img).width() - 1:2, \ + _n3##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = I[8] = I[9] = I[10] = (T)(img)(0,_p2##y,z,c)), \ + (I[14] = I[15] = I[16] = I[17] = (T)(img)(0,_p1##y,z,c)), \ + (I[21] = I[22] = I[23] = I[24] = (T)(img)(0,y,z,c)), \ + (I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_n1##y,z,c)), \ + (I[35] = I[36] = I[37] = I[38] = (T)(img)(0,_n2##y,z,c)), \ + (I[42] = I[43] = I[44] = I[45] = (T)(img)(0,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + 3>=(img)._width?(img).width() - 1:3); \ + (_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for_in7x7(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in7((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(int)(img)._width?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(int)(img)._width?(img).width() - 1:x + 2, \ + _n3##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[7] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[14] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[21] = (T)(img)(_p3##x,y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[35] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[42] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[15] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[22] = (T)(img)(_p2##x,y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[36] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[43] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[23] = (T)(img)(_p1##x,y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[37] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[44] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[10] = (T)(img)(x,_p2##y,z,c)), \ + (I[17] = (T)(img)(x,_p1##y,z,c)), \ + (I[24] = (T)(img)(x,y,z,c)), \ + (I[31] = (T)(img)(x,_n1##y,z,c)), \ + (I[38] = (T)(img)(x,_n2##y,z,c)), \ + (I[45] = (T)(img)(x,_n3##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[11] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_n1##x,y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[39] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[46] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[19] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_n2##x,y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[47] = (T)(img)(_n2##x,_n3##y,z,c)), \ + x + 3>=(int)(img)._width?(img).width() - 1:x + 3); \ + x<=(int)(x1) && ((_n3##x<(img).width() && ( \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[27] = (T)(img)(_n3##x,y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_n3##x,_n3##y,z,c)),1)) || \ + _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], \ + I[7] = I[8], I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], \ + I[14] = I[15], I[15] = I[16], I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], \ + I[21] = I[22], I[22] = I[23], I[23] = I[24], I[24] = I[25], I[25] = I[26], I[26] = I[27], \ + I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], I[32] = I[33], I[33] = I[34], \ + I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], I[40] = I[41], \ + I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x) + +#define cimg_for8x8(img,x,y,z,c,I,T) \ + cimg_for8((img)._height,y) for (int x = 0, \ + _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = I[9] = I[10] = I[11] = (T)(img)(0,_p2##y,z,c)), \ + (I[16] = I[17] = I[18] = I[19] = (T)(img)(0,_p1##y,z,c)), \ + (I[24] = I[25] = I[26] = I[27] = (T)(img)(0,y,z,c)), \ + (I[32] = I[33] = I[34] = I[35] = (T)(img)(0,_n1##y,z,c)), \ + (I[40] = I[41] = I[42] = I[43] = (T)(img)(0,_n2##y,z,c)), \ + (I[48] = I[49] = I[50] = I[51] = (T)(img)(0,_n3##y,z,c)), \ + (I[56] = I[57] = I[58] = I[59] = (T)(img)(0,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in8x8(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in8((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[8] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[16] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[24] = (T)(img)(_p3##x,y,z,c)), \ + (I[32] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[40] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[48] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[56] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[9] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[17] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[25] = (T)(img)(_p2##x,y,z,c)), \ + (I[33] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[41] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[49] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[57] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[10] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[26] = (T)(img)(_p1##x,y,z,c)), \ + (I[34] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[42] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[50] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[58] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(x,_p3##y,z,c)), \ + (I[11] = (T)(img)(x,_p2##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,z,c)), \ + (I[27] = (T)(img)(x,y,z,c)), \ + (I[35] = (T)(img)(x,_n1##y,z,c)), \ + (I[43] = (T)(img)(x,_n2##y,z,c)), \ + (I[51] = (T)(img)(x,_n3##y,z,c)), \ + (I[59] = (T)(img)(x,_n4##y,z,c)), \ + (I[4] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[12] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[28] = (T)(img)(_n1##x,y,z,c)), \ + (I[36] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[44] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[52] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[60] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[13] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[21] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[29] = (T)(img)(_n2##x,y,z,c)), \ + (I[37] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[45] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[53] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[61] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[14] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[22] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[30] = (T)(img)(_n3##x,y,z,c)), \ + (I[38] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[46] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[54] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[62] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[7] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[15] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[23] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[31] = (T)(img)(_n4##x,y,z,c)), \ + (I[39] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[47] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[55] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[63] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], \ + I[8] = I[9], I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], \ + I[16] = I[17], I[17] = I[18], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], \ + I[24] = I[25], I[25] = I[26], I[26] = I[27], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[35] = I[36], I[36] = I[37], I[37] = I[38], I[38] = I[39], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[44] = I[45], I[45] = I[46], I[46] = I[47], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[53] = I[54], I[54] = I[55], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[62] = I[63], \ + _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for9x9(img,x,y,z,c,I,T) \ + cimg_for9((img)._height,y) for (int x = 0, \ + _p4##x = 0, _p3##x = 0, _p2##x = 0, _p1##x = 0, \ + _n1##x = 1>=((img)._width)?(img).width() - 1:1, \ + _n2##x = 2>=((img)._width)?(img).width() - 1:2, \ + _n3##x = 3>=((img)._width)?(img).width() - 1:3, \ + _n4##x = (int)( \ + (I[0] = I[1] = I[2] = I[3] = I[4] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = I[10] = I[11] = I[12] = I[13] = (T)(img)(0,_p3##y,z,c)), \ + (I[18] = I[19] = I[20] = I[21] = I[22] = (T)(img)(0,_p2##y,z,c)), \ + (I[27] = I[28] = I[29] = I[30] = I[31] = (T)(img)(0,_p1##y,z,c)), \ + (I[36] = I[37] = I[38] = I[39] = I[40] = (T)(img)(0,y,z,c)), \ + (I[45] = I[46] = I[47] = I[48] = I[49] = (T)(img)(0,_n1##y,z,c)), \ + (I[54] = I[55] = I[56] = I[57] = I[58] = (T)(img)(0,_n2##y,z,c)), \ + (I[63] = I[64] = I[65] = I[66] = I[67] = (T)(img)(0,_n3##y,z,c)), \ + (I[72] = I[73] = I[74] = I[75] = I[76] = (T)(img)(0,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + 4>=((img)._width)?(img).width() - 1:4); \ + (_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for_in9x9(img,x0,y0,x1,y1,x,y,z,c,I,T) \ + cimg_for_in9((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p4##x = x - 4<0?0:x - 4, \ + _p3##x = x - 3<0?0:x - 3, \ + _p2##x = x - 2<0?0:x - 2, \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = x + 1>=(img).width()?(img).width() - 1:x + 1, \ + _n2##x = x + 2>=(img).width()?(img).width() - 1:x + 2, \ + _n3##x = x + 3>=(img).width()?(img).width() - 1:x + 3, \ + _n4##x = (int)( \ + (I[0] = (T)(img)(_p4##x,_p4##y,z,c)), \ + (I[9] = (T)(img)(_p4##x,_p3##y,z,c)), \ + (I[18] = (T)(img)(_p4##x,_p2##y,z,c)), \ + (I[27] = (T)(img)(_p4##x,_p1##y,z,c)), \ + (I[36] = (T)(img)(_p4##x,y,z,c)), \ + (I[45] = (T)(img)(_p4##x,_n1##y,z,c)), \ + (I[54] = (T)(img)(_p4##x,_n2##y,z,c)), \ + (I[63] = (T)(img)(_p4##x,_n3##y,z,c)), \ + (I[72] = (T)(img)(_p4##x,_n4##y,z,c)), \ + (I[1] = (T)(img)(_p3##x,_p4##y,z,c)), \ + (I[10] = (T)(img)(_p3##x,_p3##y,z,c)), \ + (I[19] = (T)(img)(_p3##x,_p2##y,z,c)), \ + (I[28] = (T)(img)(_p3##x,_p1##y,z,c)), \ + (I[37] = (T)(img)(_p3##x,y,z,c)), \ + (I[46] = (T)(img)(_p3##x,_n1##y,z,c)), \ + (I[55] = (T)(img)(_p3##x,_n2##y,z,c)), \ + (I[64] = (T)(img)(_p3##x,_n3##y,z,c)), \ + (I[73] = (T)(img)(_p3##x,_n4##y,z,c)), \ + (I[2] = (T)(img)(_p2##x,_p4##y,z,c)), \ + (I[11] = (T)(img)(_p2##x,_p3##y,z,c)), \ + (I[20] = (T)(img)(_p2##x,_p2##y,z,c)), \ + (I[29] = (T)(img)(_p2##x,_p1##y,z,c)), \ + (I[38] = (T)(img)(_p2##x,y,z,c)), \ + (I[47] = (T)(img)(_p2##x,_n1##y,z,c)), \ + (I[56] = (T)(img)(_p2##x,_n2##y,z,c)), \ + (I[65] = (T)(img)(_p2##x,_n3##y,z,c)), \ + (I[74] = (T)(img)(_p2##x,_n4##y,z,c)), \ + (I[3] = (T)(img)(_p1##x,_p4##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,_p3##y,z,c)), \ + (I[21] = (T)(img)(_p1##x,_p2##y,z,c)), \ + (I[30] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[39] = (T)(img)(_p1##x,y,z,c)), \ + (I[48] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[57] = (T)(img)(_p1##x,_n2##y,z,c)), \ + (I[66] = (T)(img)(_p1##x,_n3##y,z,c)), \ + (I[75] = (T)(img)(_p1##x,_n4##y,z,c)), \ + (I[4] = (T)(img)(x,_p4##y,z,c)), \ + (I[13] = (T)(img)(x,_p3##y,z,c)), \ + (I[22] = (T)(img)(x,_p2##y,z,c)), \ + (I[31] = (T)(img)(x,_p1##y,z,c)), \ + (I[40] = (T)(img)(x,y,z,c)), \ + (I[49] = (T)(img)(x,_n1##y,z,c)), \ + (I[58] = (T)(img)(x,_n2##y,z,c)), \ + (I[67] = (T)(img)(x,_n3##y,z,c)), \ + (I[76] = (T)(img)(x,_n4##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,_p4##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,_p3##y,z,c)), \ + (I[23] = (T)(img)(_n1##x,_p2##y,z,c)), \ + (I[32] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[41] = (T)(img)(_n1##x,y,z,c)), \ + (I[50] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[59] = (T)(img)(_n1##x,_n2##y,z,c)), \ + (I[68] = (T)(img)(_n1##x,_n3##y,z,c)), \ + (I[77] = (T)(img)(_n1##x,_n4##y,z,c)), \ + (I[6] = (T)(img)(_n2##x,_p4##y,z,c)), \ + (I[15] = (T)(img)(_n2##x,_p3##y,z,c)), \ + (I[24] = (T)(img)(_n2##x,_p2##y,z,c)), \ + (I[33] = (T)(img)(_n2##x,_p1##y,z,c)), \ + (I[42] = (T)(img)(_n2##x,y,z,c)), \ + (I[51] = (T)(img)(_n2##x,_n1##y,z,c)), \ + (I[60] = (T)(img)(_n2##x,_n2##y,z,c)), \ + (I[69] = (T)(img)(_n2##x,_n3##y,z,c)), \ + (I[78] = (T)(img)(_n2##x,_n4##y,z,c)), \ + (I[7] = (T)(img)(_n3##x,_p4##y,z,c)), \ + (I[16] = (T)(img)(_n3##x,_p3##y,z,c)), \ + (I[25] = (T)(img)(_n3##x,_p2##y,z,c)), \ + (I[34] = (T)(img)(_n3##x,_p1##y,z,c)), \ + (I[43] = (T)(img)(_n3##x,y,z,c)), \ + (I[52] = (T)(img)(_n3##x,_n1##y,z,c)), \ + (I[61] = (T)(img)(_n3##x,_n2##y,z,c)), \ + (I[70] = (T)(img)(_n3##x,_n3##y,z,c)), \ + (I[79] = (T)(img)(_n3##x,_n4##y,z,c)), \ + x + 4>=(img).width()?(img).width() - 1:x + 4); \ + x<=(int)(x1) && ((_n4##x<(img).width() && ( \ + (I[8] = (T)(img)(_n4##x,_p4##y,z,c)), \ + (I[17] = (T)(img)(_n4##x,_p3##y,z,c)), \ + (I[26] = (T)(img)(_n4##x,_p2##y,z,c)), \ + (I[35] = (T)(img)(_n4##x,_p1##y,z,c)), \ + (I[44] = (T)(img)(_n4##x,y,z,c)), \ + (I[53] = (T)(img)(_n4##x,_n1##y,z,c)), \ + (I[62] = (T)(img)(_n4##x,_n2##y,z,c)), \ + (I[71] = (T)(img)(_n4##x,_n3##y,z,c)), \ + (I[80] = (T)(img)(_n4##x,_n4##y,z,c)),1)) || \ + _n3##x==--_n4##x || _n2##x==--_n3##x || _n1##x==--_n2##x || x==(_n4##x = _n3##x = _n2##x = --_n1##x)); \ + I[0] = I[1], I[1] = I[2], I[2] = I[3], I[3] = I[4], I[4] = I[5], I[5] = I[6], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[11] = I[12], I[12] = I[13], I[13] = I[14], I[14] = I[15], I[15] = I[16], \ + I[16] = I[17], I[18] = I[19], I[19] = I[20], I[20] = I[21], I[21] = I[22], I[22] = I[23], I[23] = I[24], \ + I[24] = I[25], I[25] = I[26], I[27] = I[28], I[28] = I[29], I[29] = I[30], I[30] = I[31], I[31] = I[32], \ + I[32] = I[33], I[33] = I[34], I[34] = I[35], I[36] = I[37], I[37] = I[38], I[38] = I[39], I[39] = I[40], \ + I[40] = I[41], I[41] = I[42], I[42] = I[43], I[43] = I[44], I[45] = I[46], I[46] = I[47], I[47] = I[48], \ + I[48] = I[49], I[49] = I[50], I[50] = I[51], I[51] = I[52], I[52] = I[53], I[54] = I[55], I[55] = I[56], \ + I[56] = I[57], I[57] = I[58], I[58] = I[59], I[59] = I[60], I[60] = I[61], I[61] = I[62], I[63] = I[64], \ + I[64] = I[65], I[65] = I[66], I[66] = I[67], I[67] = I[68], I[68] = I[69], I[69] = I[70], I[70] = I[71], \ + I[72] = I[73], I[73] = I[74], I[74] = I[75], I[75] = I[76], I[76] = I[77], I[77] = I[78], I[78] = I[79], \ + I[79] = I[80], \ + _p4##x = _p3##x, _p3##x = _p2##x, _p2##x = _p1##x, _p1##x = x++, ++_n1##x, ++_n2##x, ++_n3##x, ++_n4##x) + +#define cimg_for2x2x2(img,x,y,z,c,I,T) \ + cimg_for2((img)._depth,z) cimg_for2((img)._height,y) for (int x = 0, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(0,y,z,c)), \ + (I[2] = (T)(img)(0,_n1##y,z,c)), \ + (I[4] = (T)(img)(0,y,_n1##z,c)), \ + (I[6] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for_in2x2x2(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in2((img)._depth,z0,z1,z) cimg_for_in2((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _n1##x = (int)( \ + (I[0] = (T)(img)(x,y,z,c)), \ + (I[2] = (T)(img)(x,_n1##y,z,c)), \ + (I[4] = (T)(img)(x,y,_n1##z,c)), \ + (I[6] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[1] = (T)(img)(_n1##x,y,z,c)), \ + (I[3] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[7] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[2] = I[3], I[4] = I[5], I[6] = I[7], \ + ++x, ++_n1##x) + +#define cimg_for3x3x3(img,x,y,z,c,I,T) \ + cimg_for3((img)._depth,z) cimg_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,_p1##z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,_p1##z,c)), \ + (I[9] = I[10] = (T)(img)(0,_p1##y,z,c)), \ + (I[12] = I[13] = (T)(img)(0,y,z,c)), \ + (I[15] = I[16] = (T)(img)(0,_n1##y,z,c)), \ + (I[18] = I[19] = (T)(img)(0,_p1##y,_n1##z,c)), \ + (I[21] = I[22] = (T)(img)(0,y,_n1##z,c)), \ + (I[24] = I[25] = (T)(img)(0,_n1##y,_n1##z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimg_for_in3x3x3(img,x0,y0,z0,x1,y1,z1,x,y,z,c,I,T) \ + cimg_for_in3((img)._depth,z0,z1,z) cimg_for_in3((img)._height,y0,y1,y) for (int x = (int)(x0)<0?0:(int)(x0), \ + _p1##x = x - 1<0?0:x - 1, \ + _n1##x = (int)( \ + (I[0] = (T)(img)(_p1##x,_p1##y,_p1##z,c)), \ + (I[3] = (T)(img)(_p1##x,y,_p1##z,c)), \ + (I[6] = (T)(img)(_p1##x,_n1##y,_p1##z,c)), \ + (I[9] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[12] = (T)(img)(_p1##x,y,z,c)), \ + (I[15] = (T)(img)(_p1##x,_n1##y,z,c)), \ + (I[18] = (T)(img)(_p1##x,_p1##y,_n1##z,c)), \ + (I[21] = (T)(img)(_p1##x,y,_n1##z,c)), \ + (I[24] = (T)(img)(_p1##x,_n1##y,_n1##z,c)), \ + (I[1] = (T)(img)(x,_p1##y,_p1##z,c)), \ + (I[4] = (T)(img)(x,y,_p1##z,c)), \ + (I[7] = (T)(img)(x,_n1##y,_p1##z,c)), \ + (I[10] = (T)(img)(x,_p1##y,z,c)), \ + (I[13] = (T)(img)(x,y,z,c)), \ + (I[16] = (T)(img)(x,_n1##y,z,c)), \ + (I[19] = (T)(img)(x,_p1##y,_n1##z,c)), \ + (I[22] = (T)(img)(x,y,_n1##z,c)), \ + (I[25] = (T)(img)(x,_n1##y,_n1##z,c)), \ + x + 1>=(int)(img)._width?(img).width() - 1:x + 1); \ + x<=(int)(x1) && ((_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,_p1##z,c)), \ + (I[5] = (T)(img)(_n1##x,y,_p1##z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,_p1##z,c)), \ + (I[11] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[14] = (T)(img)(_n1##x,y,z,c)), \ + (I[17] = (T)(img)(_n1##x,_n1##y,z,c)), \ + (I[20] = (T)(img)(_n1##x,_p1##y,_n1##z,c)), \ + (I[23] = (T)(img)(_n1##x,y,_n1##z,c)), \ + (I[26] = (T)(img)(_n1##x,_n1##y,_n1##z,c)),1)) || \ + x==--_n1##x); \ + I[0] = I[1], I[1] = I[2], I[3] = I[4], I[4] = I[5], I[6] = I[7], I[7] = I[8], \ + I[9] = I[10], I[10] = I[11], I[12] = I[13], I[13] = I[14], I[15] = I[16], I[16] = I[17], \ + I[18] = I[19], I[19] = I[20], I[21] = I[22], I[22] = I[23], I[24] = I[25], I[25] = I[26], \ + _p1##x = x++, ++_n1##x) + +#define cimglist_for(list,l) for (int l = 0; l<(int)(list)._width; ++l) +#define cimglist_for_in(list,l0,l1,l) \ + for (int l = (int)(l0)<0?0:(int)(l0), _max##l = (unsigned int)l1<(list)._width?(int)(l1):(int)(list)._width - 1; \ + l<=_max##l; ++l) + +#define cimglist_apply(list,fn) cimglist_for(list,__##fn) (list)[__##fn].fn + +// Macros used to display error messages when exceptions are thrown. +// You should not use these macros is your own code. +#define _cimgdisplay_instance "[instance(%u,%u,%u,%c%s%c)] CImgDisplay::" +#define cimgdisplay_instance _width,_height,_normalization,_title?'\"':'[',_title?_title:"untitled",_title?'\"':']' +#define _cimg_instance "[instance(%u,%u,%u,%u,%p,%sshared)] CImg<%s>::" +#define cimg_instance _width,_height,_depth,_spectrum,_data,_is_shared?"":"non-",pixel_type() +#define _cimglist_instance "[instance(%u,%u,%p)] CImgList<%s>::" +#define cimglist_instance _width,_allocated_width,_data,pixel_type() + +/*------------------------------------------------ + # + # + # Define cimg_library:: namespace + # + # + -------------------------------------------------*/ +//! Contains all classes and functions of the \CImg library. +/** + This namespace is defined to avoid functions and class names collisions + that could happen with the inclusion of other C++ header files. + Anyway, it should not happen often and you should reasonnably start most of your + \CImg-based programs with + \code + #include "CImg.h" + using namespace cimg_library; + \endcode + to simplify the declaration of \CImg Library objects afterwards. +**/ +namespace cimg_library_suffixed { + + // Declare the four classes of the CImg Library. + template struct CImg; + template struct CImgList; + struct CImgDisplay; + struct CImgException; + + // Declare cimg:: namespace. + // This is an uncomplete namespace definition here. It only contains some + // necessary stuff to ensure a correct declaration order of the classes and functions + // defined afterwards. + namespace cimg { + + // Define ascii sequences for colored terminal output. +#ifdef cimg_use_vt100 + static const char t_normal[] = { 0x1b, '[', '0', ';', '0', ';', '0', 'm', 0 }; + static const char t_black[] = { 0x1b, '[', '0', ';', '3', '0', ';', '5', '9', 'm', 0 }; + static const char t_red[] = { 0x1b, '[', '0', ';', '3', '1', ';', '5', '9', 'm', 0 }; + static const char t_green[] = { 0x1b, '[', '0', ';', '3', '2', ';', '5', '9', 'm', 0 }; + static const char t_yellow[] = { 0x1b, '[', '0', ';', '3', '3', ';', '5', '9', 'm', 0 }; + static const char t_blue[] = { 0x1b, '[', '0', ';', '3', '4', ';', '5', '9', 'm', 0 }; + static const char t_magenta[] = { 0x1b, '[', '0', ';', '3', '5', ';', '5', '9', 'm', 0 }; + static const char t_cyan[] = { 0x1b, '[', '0', ';', '3', '6', ';', '5', '9', 'm', 0 }; + static const char t_white[] = { 0x1b, '[', '0', ';', '3', '7', ';', '5', '9', 'm', 0 }; + static const char t_bold[] = { 0x1b, '[', '1', 'm', 0 }; + static const char t_underscore[] = { 0x1b, '[', '4', 'm', 0 }; +#else + static const char t_normal[] = { 0 }; + static const char *const t_black = cimg::t_normal, + *const t_red = cimg::t_normal, + *const t_green = cimg::t_normal, + *const t_yellow = cimg::t_normal, + *const t_blue = cimg::t_normal, + *const t_magenta = cimg::t_normal, + *const t_cyan = cimg::t_normal, + *const t_white = cimg::t_normal, + *const t_bold = cimg::t_normal, + *const t_underscore = cimg::t_normal; +#endif + + inline std::FILE* output(std::FILE *file=0); + inline void info(); + + //! Avoid warning messages due to unused parameters. Do nothing actually. + template + inline void unused(const T&, ...) {} + + // [internal] Lock/unlock a mutex for managing concurrent threads. + // 'lock_mode' can be { 0=unlock | 1=lock | 2=trylock }. + // 'n' can be in [0,31] but mutex range [0,15] is reserved by CImg. + inline int mutex(const unsigned int n, const int lock_mode=1); + + inline unsigned int& _exception_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = cimg_verbosity; + if (is_set) { cimg::mutex(0); mode = value<4?value:4; cimg::mutex(0,0); } + return mode; + } + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + inline FILE* _stdin(); + inline FILE* _stdout(); + inline FILE* _stderr(); + + // Mandatory because Microsoft's _snprintf() and _vsnprintf() do not add the '\0' character + // at the end of the string. +#if cimg_OS==2 && defined(_MSC_VER) + inline int _snprintf(char *const s, const size_t size, const char *const format, ...) { + va_list ap; + va_start(ap,format); + const int result = _vsnprintf(s,size,format,ap); + va_end(ap); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char *const format, va_list ap) { + int result = -1; + cimg::mutex(6); + if (size) result = _vsnprintf_s(s,size,_TRUNCATE,format,ap); + if (result==-1) result = _vscprintf(format,ap); + cimg::mutex(6,0); + return result; + } + + // Mutex-protected version of sscanf, sprintf and snprintf. + // Used only MacOSX, as it seems those functions are not re-entrant on MacOSX. +#elif defined(__MACOSX__) || defined(__APPLE__) + inline int _sscanf(const char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsscanf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _sprintf(char *const s, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsprintf(s,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _snprintf(char *const s, const size_t n, const char *const format, ...) { + cimg::mutex(6); + va_list args; + va_start(args,format); + const int result = std::vsnprintf(s,n,format,args); + va_end(args); + cimg::mutex(6,0); + return result; + } + + inline int _vsnprintf(char *const s, const size_t size, const char* format, va_list ap) { + cimg::mutex(6); + const int result = std::vsnprintf(s,size,format,ap); + cimg::mutex(6,0); + return result; + } +#endif + + //! Set current \CImg exception mode. + /** + The way error messages are handled by \CImg can be changed dynamically, using this function. + \param mode Desired exception mode. Possible values are: + - \c 0: Hide library messages (quiet mode). + - \c 1: Print library messages on the console. + - \c 2: Display library messages on a dialog window. + - \c 3: Do as \c 1 + add extra debug warnings (slow down the code!). + - \c 4: Do as \c 2 + add extra debug warnings (slow down the code!). + **/ + inline unsigned int& exception_mode(const unsigned int mode) { + return _exception_mode(mode,true); + } + + //! Return current \CImg exception mode. + /** + \note By default, return the value of configuration macro \c cimg_verbosity + **/ + inline unsigned int& exception_mode() { + return _exception_mode(0,false); + } + + //! Set current \CImg openmp mode. + /** + The way openmp-based methods are handled by \CImg can be changed dynamically, using this function. + \param mode Desired openmp mode. Possible values are: + - \c 0: Never parallelize. + - \c 1: Always parallelize. + - \c 2: Adaptive parallelization mode (default behavior). + **/ + inline unsigned int& _openmp_mode(const unsigned int value, const bool is_set) { + static unsigned int mode = 2; + if (is_set) { cimg::mutex(0); mode = value<2?value:2; cimg::mutex(0,0); } + return mode; + } + + inline unsigned int& openmp_mode(const unsigned int mode) { + return _openmp_mode(mode,true); + } + + //! Return current \CImg openmp mode. + inline unsigned int& openmp_mode() { + return _openmp_mode(0,false); + } + +#define cimg_openmp_if(cond) if (cimg::openmp_mode()==1 || (cimg::openmp_mode()>1 && (cond))) + + // Display a simple dialog box, and wait for the user's response. + inline int dialog(const char *const title, const char *const msg, const char *const button1_label="OK", + const char *const button2_label=0, const char *const button3_label=0, + const char *const button4_label=0, const char *const button5_label=0, + const char *const button6_label=0, const bool centering=false); + + // Evaluate math expression. + inline double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0); + + } + + /*--------------------------------------- + # + # Define the CImgException structures + # + --------------------------------------*/ + //! Instances of \c CImgException are thrown when errors are encountered in a \CImg function call. + /** + \par Overview + + CImgException is the base class of all exceptions thrown by \CImg (except \b CImgAbortException). + CImgException is never thrown itself. Derived classes that specify the type of errord are thrown instead. + These classes can be: + + - \b CImgAbortException: Thrown when a computationally-intensive function is aborted by an external signal. + This is the only \c non-derived exception class. + + - \b CImgArgumentException: Thrown when one argument of a called \CImg function is invalid. + This is probably one of the most thrown exception by \CImg. + For instance, the following example throws a \c CImgArgumentException: + \code + CImg img(100,100,1,3); // Define a 100x100 color image with float-valued pixels. + img.mirror('e'); // Try to mirror image along the (non-existing) 'e'-axis. + \endcode + + - \b CImgDisplayException: Thrown when something went wrong during the display of images in CImgDisplay instances. + + - \b CImgInstanceException: Thrown when an instance associated to a called \CImg method does not fit + the function requirements. For instance, the following example throws a \c CImgInstanceException: + \code + const CImg img; // Define an empty image. + const float value = img.at(0); // Try to read first pixel value (does not exist). + \endcode + + - \b CImgIOException: Thrown when an error occured when trying to load or save image files. + This happens when trying to read files that do not exist or with invalid formats. + For instance, the following example throws a \c CImgIOException: + \code + const CImg img("missing_file.jpg"); // Try to load a file that does not exist. + \endcode + + - \b CImgWarningException: Thrown only if configuration macro \c cimg_strict_warnings is set, and + when a \CImg function has to display a warning message (see cimg::warn()). + + It is not recommended to throw CImgException instances by yourself, + since they are expected to be thrown only by \CImg. + When an error occurs in a library function call, \CImg may display error messages on the screen or on the + standard output, depending on the current \CImg exception mode. + The \CImg exception mode can be get and set by functions cimg::exception_mode() and + cimg::exception_mode(unsigned int). + + \par Exceptions handling + + In all cases, when an error occurs in \CImg, an instance of the corresponding exception class is thrown. + This may lead the program to break (this is the default behavior), but you can bypass this behavior by + handling the exceptions by yourself, + using a usual try { ... } catch () { ... } bloc, as in the following example: + \code + #define "CImg.h" + using namespace cimg_library; + int main() { + cimg::exception_mode(0); // Enable quiet exception mode. + try { + ... // Here, do what you want to stress CImg. + } catch (CImgException& e) { // You succeeded: something went wrong! + std::fprintf(stderr,"CImg Library Error: %s",e.what()); // Display your custom error message. + ... // Do what you want now to save the ship! + } + } + \endcode + **/ + struct CImgException : public std::exception { +#define _cimg_exception_err(etype,disp_flag) \ + std::va_list ap, ap2; \ + va_start(ap,format); va_start(ap2,format); \ + int size = cimg_vsnprintf(0,0,format,ap2); \ + if (size++>=0) { \ + delete[] _message; \ + _message = new char[size]; \ + cimg_vsnprintf(_message,size,format,ap); \ + if (cimg::exception_mode()) { \ + std::fprintf(cimg::output(),"\n%s[CImg] *** %s ***%s %s\n",cimg::t_red,etype,cimg::t_normal,_message); \ + if (cimg_display && disp_flag && !(cimg::exception_mode()%2)) try { cimg::dialog(etype,_message,"Abort"); } \ + catch (CImgException&) {} \ + if (cimg::exception_mode()>=3) cimg_library_suffixed::cimg::info(); \ + } \ + } \ + va_end(ap); va_end(ap2); \ + + char *_message; + CImgException() { _message = new char[1]; *_message = 0; } + CImgException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgException",true); } + CImgException(const CImgException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgException() throw() { delete[] _message; } + CImgException& operator=(const CImgException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; + + // The CImgAbortException class is used to throw an exception when + // a computationally-intensive function has been aborted by an external signal. + struct CImgAbortException : public std::exception { + char *_message; + CImgAbortException() { _message = new char[1]; *_message = 0; } + CImgAbortException(const char *const format, ...):_message(0) { _cimg_exception_err("CImgAbortException",true); } + CImgAbortException(const CImgAbortException& e):std::exception(e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + } + ~CImgAbortException() throw() { delete[] _message; } + CImgAbortException& operator=(const CImgAbortException& e) { + const size_t size = std::strlen(e._message); + _message = new char[size + 1]; + std::strncpy(_message,e._message,size); + _message[size] = 0; + return *this; + } + //! Return a C-string containing the error message associated to the thrown exception. + const char *what() const throw() { return _message; } + }; + + // The CImgArgumentException class is used to throw an exception related + // to invalid arguments encountered in a library function call. + struct CImgArgumentException : public CImgException { + CImgArgumentException(const char *const format, ...) { _cimg_exception_err("CImgArgumentException",true); } + }; + + // The CImgDisplayException class is used to throw an exception related + // to display problems encountered in a library function call. + struct CImgDisplayException : public CImgException { + CImgDisplayException(const char *const format, ...) { _cimg_exception_err("CImgDisplayException",false); } + }; + + // The CImgInstanceException class is used to throw an exception related + // to an invalid instance encountered in a library function call. + struct CImgInstanceException : public CImgException { + CImgInstanceException(const char *const format, ...) { _cimg_exception_err("CImgInstanceException",true); } + }; + + // The CImgIOException class is used to throw an exception related + // to input/output file problems encountered in a library function call. + struct CImgIOException : public CImgException { + CImgIOException(const char *const format, ...) { _cimg_exception_err("CImgIOException",true); } + }; + + // The CImgWarningException class is used to throw an exception for warnings + // encountered in a library function call. + struct CImgWarningException : public CImgException { + CImgWarningException(const char *const format, ...) { _cimg_exception_err("CImgWarningException",false); } + }; + + /*------------------------------------- + # + # Define cimg:: namespace + # + -----------------------------------*/ + //! Contains \a low-level functions and variables of the \CImg Library. + /** + Most of the functions and variables within this namespace are used by the \CImg library for low-level operations. + You may use them to access specific const values or environment variables internally used by \CImg. + \warning Never write using namespace cimg_library::cimg; in your source code. Lot of functions in the + cimg:: namespace have the same names as standard C functions that may be defined in the global + namespace ::. + **/ + namespace cimg { + + // Define traits that will be used to determine the best data type to work in CImg functions. + // + template struct type { + static const char* string() { + static const char* s[] = { "unknown", "unknown8", "unknown16", "unknown24", + "unknown32", "unknown40", "unknown48", "unknown56", + "unknown64", "unknown72", "unknown80", "unknown88", + "unknown96", "unknown104", "unknown112", "unknown120", + "unknown128" }; + return s[(sizeof(T)<17)?sizeof(T):0]; + } + static bool is_float() { return false; } + static bool is_inf(const T) { return false; } + static bool is_nan(const T) { return false; } + static T min() { return ~max(); } + static T max() { return (T)1<<(8*sizeof(T) - 1); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "bool"; return s; } + static bool is_float() { return false; } + static bool is_inf(const bool) { return false; } + static bool is_nan(const bool) { return false; } + static bool min() { return false; } + static bool max() { return true; } + static bool inf() { return max(); } + 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]; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned char) { return false; } + static bool is_nan(const unsigned char) { return false; } + static unsigned char min() { return 0; } + static unsigned char max() { return (unsigned char)-1; } + static unsigned char inf() { return max(); } + 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; } + }; + +#if defined(CHAR_MAX) && CHAR_MAX==255 + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static char min() { return 0; } + static char max() { return (char)-1; } + static char inf() { return max(); } + 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 + template<> struct type { + static const char* string() { static const char *const s = "char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const char) { return false; } + static bool is_nan(const char) { return false; } + static char min() { return ~max(); } + static char max() { return (char)((unsigned char)-1>>1); } + 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 + + template<> struct type { + static const char* string() { static const char *const s = "signed char"; return s; } + static bool is_float() { return false; } + static bool is_inf(const signed char) { return false; } + static bool is_nan(const signed char) { return false; } + static signed char min() { return ~max(); } + static signed char max() { return (signed char)((unsigned char)-1>>1); } + static signed char inf() { return max(); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned short) { return false; } + static bool is_nan(const unsigned short) { return false; } + static unsigned short min() { return 0; } + static unsigned short max() { return (unsigned short)-1; } + static unsigned short inf() { return max(); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "short"; return s; } + static bool is_float() { return false; } + static bool is_inf(const short) { return false; } + static bool is_nan(const short) { return false; } + static short min() { return ~max(); } + static short max() { return (short)((unsigned short)-1>>1); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const unsigned int) { return false; } + static bool is_nan(const unsigned int) { return false; } + static unsigned int min() { return 0; } + static unsigned int max() { return (unsigned int)-1; } + static unsigned int inf() { return max(); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int"; return s; } + static bool is_float() { return false; } + static bool is_inf(const int) { return false; } + static bool is_nan(const int) { return false; } + static int min() { return ~max(); } + static int max() { return (int)((unsigned int)-1>>1); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "unsigned int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_uint64) { return false; } + static bool is_nan(const cimg_uint64) { return false; } + static cimg_uint64 min() { return 0; } + static cimg_uint64 max() { return (cimg_uint64)-1; } + static cimg_uint64 inf() { return max(); } + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "int64"; return s; } + static bool is_float() { return false; } + static bool is_inf(const cimg_int64) { return false; } + static bool is_nan(const cimg_int64) { return false; } + static cimg_int64 min() { return ~max(); } + static cimg_int64 max() { return (cimg_int64)((cimg_uint64)-1>>1); } + static cimg_int64 inf() { return max(); } + static cimg_int64 cut(const double val) { + 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; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const double val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static double min() { return -DBL_MAX; } + static double max() { return DBL_MAX; } + static double inf() { +#ifdef INFINITY + return (double)INFINITY; +#else + return max()*max(); +#endif + } + static double nan() { +#ifdef NAN + return (double)NAN; +#else + const double val_nan = -std::sqrt(-1.0); return val_nan; +#endif + } + static double cut(const double val) { return val; } + static const char* format() { return "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const double val) { return val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "float"; return s; } + static bool is_float() { return true; } + static bool is_inf(const float val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const float val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static float min() { return -FLT_MAX; } + static float max() { return FLT_MAX; } + static float inf() { return (float)cimg::type::inf(); } + static float nan() { return (float)cimg::type::nan(); } + static float cut(const double val) { return (float)val; } + static float cut(const float val) { return (float)val; } + static const char* format() { return "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const float val) { return (double)val; } + }; + + template<> struct type { + static const char* string() { static const char *const s = "long double"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const long double val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static long double min() { return -LDBL_MAX; } + static long double max() { return LDBL_MAX; } + 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 "%.17g"; } + static const char* format_s() { return "%g"; } + static double format(const long double val) { return (double)val; } + }; + +#ifdef cimg_use_half + template<> struct type { + static const char* string() { static const char *const s = "half"; return s; } + static bool is_float() { return true; } + static bool is_inf(const long double val) { +#ifdef isinf + return (bool)isinf(val); +#else + return !is_nan(val) && (val::min() || val>cimg::type::max()); +#endif + } + static bool is_nan(const long double val) { +#ifdef isnan + return (bool)isnan(val); +#else + return !(val==val); +#endif + } + static half min() { return (half)-65504; } + static half max() { return (half)65504; } + 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 "%.9g"; } + static const char* format_s() { return "%g"; } + static double format(const half val) { return (double)val; } + }; +#endif + + template struct superset { typedef T type; }; + template<> struct superset { typedef unsigned char type; }; + template<> struct superset { typedef char type; }; + template<> struct superset { typedef signed char type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef short type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef unsigned int type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef int type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_uint64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef cimg_int64 type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; + template<> struct superset { typedef double type; }; +#ifdef cimg_use_half + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef float type; }; + template<> struct superset { typedef double type; }; +#endif + + template struct superset2 { + typedef typename superset::type>::type type; + }; + + template struct superset3 { + typedef typename superset::type>::type type; + }; + + template struct last { typedef t2 type; }; + +#define _cimg_Tt typename cimg::superset::type +#define _cimg_Tfloat typename cimg::superset::type +#define _cimg_Ttfloat typename cimg::superset2::type +#define _cimg_Ttdouble typename cimg::superset2::type + + // Define variables used internally by CImg. +#if cimg_display==1 + struct X11_info { + unsigned int nb_wins; + pthread_t *events_thread; + pthread_cond_t wait_event; + pthread_mutex_t wait_event_mutex; + CImgDisplay **wins; + Display *display; + unsigned int nb_bits; + bool is_blue_first; + bool is_shm_enabled; + bool byte_order; +#ifdef cimg_use_xrandr + XRRScreenSize *resolutions; + Rotation curr_rotation; + unsigned int curr_resolution; + unsigned int nb_resolutions; +#endif + X11_info():nb_wins(0),events_thread(0),display(0), + nb_bits(0),is_blue_first(false),is_shm_enabled(false),byte_order(false) { +#ifdef __FreeBSD__ + XInitThreads(); +#endif + wins = new CImgDisplay*[1024]; + pthread_mutex_init(&wait_event_mutex,0); + pthread_cond_init(&wait_event,0); +#ifdef cimg_use_xrandr + resolutions = 0; + curr_rotation = 0; + curr_resolution = nb_resolutions = 0; +#endif + } + + ~X11_info() { + delete[] wins; + /* + if (events_thread) { + pthread_cancel(*events_thread); + delete events_thread; + } + if (display) { } // XCloseDisplay(display); } + pthread_cond_destroy(&wait_event); + pthread_mutex_unlock(&wait_event_mutex); + pthread_mutex_destroy(&wait_event_mutex); + */ + } + }; +#if defined(cimg_module) + X11_info& X11_attr(); +#elif defined(cimg_main) + X11_info& X11_attr() { static X11_info val; return val; } +#else + inline X11_info& X11_attr() { static X11_info val; return val; } +#endif +#define cimg_lock_display() cimg::mutex(15) +#define cimg_unlock_display() cimg::mutex(15,0) + +#elif cimg_display==2 + struct Win32_info { + HANDLE wait_event; + Win32_info() { wait_event = CreateEvent(0,FALSE,FALSE,0); } + }; +#if defined(cimg_module) + Win32_info& Win32_attr(); +#elif defined(cimg_main) + Win32_info& Win32_attr() { static Win32_info val; return val; } +#else + inline Win32_info& Win32_attr() { static Win32_info val; return val; } +#endif +#endif + + struct Mutex_info { +#if cimg_OS==2 + HANDLE mutex[32]; + Mutex_info() { for (unsigned int i = 0; i<32; ++i) mutex[i] = CreateMutex(0,FALSE,0); } + void lock(const unsigned int n) { WaitForSingleObject(mutex[n],INFINITE); } + void unlock(const unsigned int n) { ReleaseMutex(mutex[n]); } + int trylock(const unsigned int) { return 0; } +#elif defined(_PTHREAD_H) + pthread_mutex_t mutex[32]; + Mutex_info() { for (unsigned int i = 0; i<32; ++i) pthread_mutex_init(&mutex[i],0); } + void lock(const unsigned int n) { pthread_mutex_lock(&mutex[n]); } + void unlock(const unsigned int n) { pthread_mutex_unlock(&mutex[n]); } + int trylock(const unsigned int n) { return pthread_mutex_trylock(&mutex[n]); } +#else + Mutex_info() {} + void lock(const unsigned int) {} + void unlock(const unsigned int) {} + int trylock(const unsigned int) { return 0; } +#endif + }; +#if defined(cimg_module) + Mutex_info& Mutex_attr(); +#elif defined(cimg_main) + Mutex_info& Mutex_attr() { static Mutex_info val; return val; } +#else + inline Mutex_info& Mutex_attr() { static Mutex_info val; return val; } +#endif + +#if defined(cimg_use_magick) + static struct Magick_info { + Magick_info() { + Magick::InitializeMagick(""); + } + } _Magick_info; +#endif + +#if cimg_display==1 + // Define keycodes for X11-based graphical systems. + const unsigned int keyESC = XK_Escape; + const unsigned int keyF1 = XK_F1; + const unsigned int keyF2 = XK_F2; + const unsigned int keyF3 = XK_F3; + const unsigned int keyF4 = XK_F4; + const unsigned int keyF5 = XK_F5; + const unsigned int keyF6 = XK_F6; + const unsigned int keyF7 = XK_F7; + const unsigned int keyF8 = XK_F8; + const unsigned int keyF9 = XK_F9; + const unsigned int keyF10 = XK_F10; + const unsigned int keyF11 = XK_F11; + const unsigned int keyF12 = XK_F12; + const unsigned int keyPAUSE = XK_Pause; + const unsigned int key1 = XK_1; + const unsigned int key2 = XK_2; + const unsigned int key3 = XK_3; + const unsigned int key4 = XK_4; + const unsigned int key5 = XK_5; + const unsigned int key6 = XK_6; + const unsigned int key7 = XK_7; + const unsigned int key8 = XK_8; + const unsigned int key9 = XK_9; + const unsigned int key0 = XK_0; + const unsigned int keyBACKSPACE = XK_BackSpace; + const unsigned int keyINSERT = XK_Insert; + const unsigned int keyHOME = XK_Home; + const unsigned int keyPAGEUP = XK_Page_Up; + const unsigned int keyTAB = XK_Tab; + const unsigned int keyQ = XK_q; + const unsigned int keyW = XK_w; + const unsigned int keyE = XK_e; + const unsigned int keyR = XK_r; + const unsigned int keyT = XK_t; + const unsigned int keyY = XK_y; + const unsigned int keyU = XK_u; + const unsigned int keyI = XK_i; + const unsigned int keyO = XK_o; + const unsigned int keyP = XK_p; + const unsigned int keyDELETE = XK_Delete; + const unsigned int keyEND = XK_End; + const unsigned int keyPAGEDOWN = XK_Page_Down; + const unsigned int keyCAPSLOCK = XK_Caps_Lock; + const unsigned int keyA = XK_a; + const unsigned int keyS = XK_s; + const unsigned int keyD = XK_d; + const unsigned int keyF = XK_f; + const unsigned int keyG = XK_g; + const unsigned int keyH = XK_h; + const unsigned int keyJ = XK_j; + const unsigned int keyK = XK_k; + const unsigned int keyL = XK_l; + const unsigned int keyENTER = XK_Return; + const unsigned int keySHIFTLEFT = XK_Shift_L; + const unsigned int keyZ = XK_z; + const unsigned int keyX = XK_x; + const unsigned int keyC = XK_c; + const unsigned int keyV = XK_v; + const unsigned int keyB = XK_b; + const unsigned int keyN = XK_n; + const unsigned int keyM = XK_m; + const unsigned int keySHIFTRIGHT = XK_Shift_R; + const unsigned int keyARROWUP = XK_Up; + const unsigned int keyCTRLLEFT = XK_Control_L; + const unsigned int keyAPPLEFT = XK_Super_L; + const unsigned int keyALT = XK_Alt_L; + const unsigned int keySPACE = XK_space; + const unsigned int keyALTGR = XK_Alt_R; + const unsigned int keyAPPRIGHT = XK_Super_R; + const unsigned int keyMENU = XK_Menu; + const unsigned int keyCTRLRIGHT = XK_Control_R; + const unsigned int keyARROWLEFT = XK_Left; + const unsigned int keyARROWDOWN = XK_Down; + const unsigned int keyARROWRIGHT = XK_Right; + const unsigned int keyPAD0 = XK_KP_0; + const unsigned int keyPAD1 = XK_KP_1; + const unsigned int keyPAD2 = XK_KP_2; + const unsigned int keyPAD3 = XK_KP_3; + const unsigned int keyPAD4 = XK_KP_4; + const unsigned int keyPAD5 = XK_KP_5; + const unsigned int keyPAD6 = XK_KP_6; + const unsigned int keyPAD7 = XK_KP_7; + const unsigned int keyPAD8 = XK_KP_8; + const unsigned int keyPAD9 = XK_KP_9; + const unsigned int keyPADADD = XK_KP_Add; + const unsigned int keyPADSUB = XK_KP_Subtract; + const unsigned int keyPADMUL = XK_KP_Multiply; + const unsigned int keyPADDIV = XK_KP_Divide; + +#elif cimg_display==2 + // Define keycodes for Windows. + const unsigned int keyESC = VK_ESCAPE; + const unsigned int keyF1 = VK_F1; + const unsigned int keyF2 = VK_F2; + const unsigned int keyF3 = VK_F3; + const unsigned int keyF4 = VK_F4; + const unsigned int keyF5 = VK_F5; + const unsigned int keyF6 = VK_F6; + const unsigned int keyF7 = VK_F7; + const unsigned int keyF8 = VK_F8; + const unsigned int keyF9 = VK_F9; + const unsigned int keyF10 = VK_F10; + const unsigned int keyF11 = VK_F11; + const unsigned int keyF12 = VK_F12; + const unsigned int keyPAUSE = VK_PAUSE; + const unsigned int key1 = '1'; + const unsigned int key2 = '2'; + const unsigned int key3 = '3'; + const unsigned int key4 = '4'; + const unsigned int key5 = '5'; + const unsigned int key6 = '6'; + const unsigned int key7 = '7'; + const unsigned int key8 = '8'; + const unsigned int key9 = '9'; + const unsigned int key0 = '0'; + const unsigned int keyBACKSPACE = VK_BACK; + const unsigned int keyINSERT = VK_INSERT; + const unsigned int keyHOME = VK_HOME; + const unsigned int keyPAGEUP = VK_PRIOR; + const unsigned int keyTAB = VK_TAB; + const unsigned int keyQ = 'Q'; + const unsigned int keyW = 'W'; + const unsigned int keyE = 'E'; + const unsigned int keyR = 'R'; + const unsigned int keyT = 'T'; + const unsigned int keyY = 'Y'; + const unsigned int keyU = 'U'; + const unsigned int keyI = 'I'; + const unsigned int keyO = 'O'; + const unsigned int keyP = 'P'; + const unsigned int keyDELETE = VK_DELETE; + const unsigned int keyEND = VK_END; + const unsigned int keyPAGEDOWN = VK_NEXT; + const unsigned int keyCAPSLOCK = VK_CAPITAL; + const unsigned int keyA = 'A'; + const unsigned int keyS = 'S'; + const unsigned int keyD = 'D'; + const unsigned int keyF = 'F'; + const unsigned int keyG = 'G'; + const unsigned int keyH = 'H'; + const unsigned int keyJ = 'J'; + const unsigned int keyK = 'K'; + const unsigned int keyL = 'L'; + const unsigned int keyENTER = VK_RETURN; + const unsigned int keySHIFTLEFT = VK_SHIFT; + const unsigned int keyZ = 'Z'; + const unsigned int keyX = 'X'; + const unsigned int keyC = 'C'; + const unsigned int keyV = 'V'; + const unsigned int keyB = 'B'; + const unsigned int keyN = 'N'; + const unsigned int keyM = 'M'; + const unsigned int keySHIFTRIGHT = VK_SHIFT; + const unsigned int keyARROWUP = VK_UP; + const unsigned int keyCTRLLEFT = VK_CONTROL; + const unsigned int keyAPPLEFT = VK_LWIN; + const unsigned int keyALT = VK_LMENU; + const unsigned int keySPACE = VK_SPACE; + const unsigned int keyALTGR = VK_CONTROL; + const unsigned int keyAPPRIGHT = VK_RWIN; + const unsigned int keyMENU = VK_APPS; + const unsigned int keyCTRLRIGHT = VK_CONTROL; + const unsigned int keyARROWLEFT = VK_LEFT; + const unsigned int keyARROWDOWN = VK_DOWN; + const unsigned int keyARROWRIGHT = VK_RIGHT; + const unsigned int keyPAD0 = 0x60; + const unsigned int keyPAD1 = 0x61; + const unsigned int keyPAD2 = 0x62; + const unsigned int keyPAD3 = 0x63; + const unsigned int keyPAD4 = 0x64; + const unsigned int keyPAD5 = 0x65; + const unsigned int keyPAD6 = 0x66; + const unsigned int keyPAD7 = 0x67; + const unsigned int keyPAD8 = 0x68; + const unsigned int keyPAD9 = 0x69; + const unsigned int keyPADADD = VK_ADD; + const unsigned int keyPADSUB = VK_SUBTRACT; + const unsigned int keyPADMUL = VK_MULTIPLY; + const unsigned int keyPADDIV = VK_DIVIDE; + +#else + // Define random keycodes when no display is available. + // (should rarely be used then!). + const unsigned int keyESC = 1U; //!< Keycode for the \c ESC key (architecture-dependent). + const unsigned int keyF1 = 2U; //!< Keycode for the \c F1 key (architecture-dependent). + const unsigned int keyF2 = 3U; //!< Keycode for the \c F2 key (architecture-dependent). + const unsigned int keyF3 = 4U; //!< Keycode for the \c F3 key (architecture-dependent). + const unsigned int keyF4 = 5U; //!< Keycode for the \c F4 key (architecture-dependent). + const unsigned int keyF5 = 6U; //!< Keycode for the \c F5 key (architecture-dependent). + const unsigned int keyF6 = 7U; //!< Keycode for the \c F6 key (architecture-dependent). + const unsigned int keyF7 = 8U; //!< Keycode for the \c F7 key (architecture-dependent). + const unsigned int keyF8 = 9U; //!< Keycode for the \c F8 key (architecture-dependent). + const unsigned int keyF9 = 10U; //!< Keycode for the \c F9 key (architecture-dependent). + const unsigned int keyF10 = 11U; //!< Keycode for the \c F10 key (architecture-dependent). + const unsigned int keyF11 = 12U; //!< Keycode for the \c F11 key (architecture-dependent). + const unsigned int keyF12 = 13U; //!< Keycode for the \c F12 key (architecture-dependent). + const unsigned int keyPAUSE = 14U; //!< Keycode for the \c PAUSE key (architecture-dependent). + const unsigned int key1 = 15U; //!< Keycode for the \c 1 key (architecture-dependent). + const unsigned int key2 = 16U; //!< Keycode for the \c 2 key (architecture-dependent). + const unsigned int key3 = 17U; //!< Keycode for the \c 3 key (architecture-dependent). + const unsigned int key4 = 18U; //!< Keycode for the \c 4 key (architecture-dependent). + const unsigned int key5 = 19U; //!< Keycode for the \c 5 key (architecture-dependent). + const unsigned int key6 = 20U; //!< Keycode for the \c 6 key (architecture-dependent). + const unsigned int key7 = 21U; //!< Keycode for the \c 7 key (architecture-dependent). + const unsigned int key8 = 22U; //!< Keycode for the \c 8 key (architecture-dependent). + const unsigned int key9 = 23U; //!< Keycode for the \c 9 key (architecture-dependent). + const unsigned int key0 = 24U; //!< Keycode for the \c 0 key (architecture-dependent). + const unsigned int keyBACKSPACE = 25U; //!< Keycode for the \c BACKSPACE key (architecture-dependent). + const unsigned int keyINSERT = 26U; //!< Keycode for the \c INSERT key (architecture-dependent). + const unsigned int keyHOME = 27U; //!< Keycode for the \c HOME key (architecture-dependent). + const unsigned int keyPAGEUP = 28U; //!< Keycode for the \c PAGEUP key (architecture-dependent). + const unsigned int keyTAB = 29U; //!< Keycode for the \c TAB key (architecture-dependent). + const unsigned int keyQ = 30U; //!< Keycode for the \c Q key (architecture-dependent). + const unsigned int keyW = 31U; //!< Keycode for the \c W key (architecture-dependent). + const unsigned int keyE = 32U; //!< Keycode for the \c E key (architecture-dependent). + const unsigned int keyR = 33U; //!< Keycode for the \c R key (architecture-dependent). + const unsigned int keyT = 34U; //!< Keycode for the \c T key (architecture-dependent). + const unsigned int keyY = 35U; //!< Keycode for the \c Y key (architecture-dependent). + const unsigned int keyU = 36U; //!< Keycode for the \c U key (architecture-dependent). + const unsigned int keyI = 37U; //!< Keycode for the \c I key (architecture-dependent). + const unsigned int keyO = 38U; //!< Keycode for the \c O key (architecture-dependent). + const unsigned int keyP = 39U; //!< Keycode for the \c P key (architecture-dependent). + const unsigned int keyDELETE = 40U; //!< Keycode for the \c DELETE key (architecture-dependent). + const unsigned int keyEND = 41U; //!< Keycode for the \c END key (architecture-dependent). + const unsigned int keyPAGEDOWN = 42U; //!< Keycode for the \c PAGEDOWN key (architecture-dependent). + const unsigned int keyCAPSLOCK = 43U; //!< Keycode for the \c CAPSLOCK key (architecture-dependent). + const unsigned int keyA = 44U; //!< Keycode for the \c A key (architecture-dependent). + const unsigned int keyS = 45U; //!< Keycode for the \c S key (architecture-dependent). + const unsigned int keyD = 46U; //!< Keycode for the \c D key (architecture-dependent). + const unsigned int keyF = 47U; //!< Keycode for the \c F key (architecture-dependent). + const unsigned int keyG = 48U; //!< Keycode for the \c G key (architecture-dependent). + const unsigned int keyH = 49U; //!< Keycode for the \c H key (architecture-dependent). + const unsigned int keyJ = 50U; //!< Keycode for the \c J key (architecture-dependent). + const unsigned int keyK = 51U; //!< Keycode for the \c K key (architecture-dependent). + const unsigned int keyL = 52U; //!< Keycode for the \c L key (architecture-dependent). + const unsigned int keyENTER = 53U; //!< Keycode for the \c ENTER key (architecture-dependent). + const unsigned int keySHIFTLEFT = 54U; //!< Keycode for the \c SHIFTLEFT key (architecture-dependent). + const unsigned int keyZ = 55U; //!< Keycode for the \c Z key (architecture-dependent). + const unsigned int keyX = 56U; //!< Keycode for the \c X key (architecture-dependent). + const unsigned int keyC = 57U; //!< Keycode for the \c C key (architecture-dependent). + const unsigned int keyV = 58U; //!< Keycode for the \c V key (architecture-dependent). + const unsigned int keyB = 59U; //!< Keycode for the \c B key (architecture-dependent). + const unsigned int keyN = 60U; //!< Keycode for the \c N key (architecture-dependent). + const unsigned int keyM = 61U; //!< Keycode for the \c M key (architecture-dependent). + const unsigned int keySHIFTRIGHT = 62U; //!< Keycode for the \c SHIFTRIGHT key (architecture-dependent). + const unsigned int keyARROWUP = 63U; //!< Keycode for the \c ARROWUP key (architecture-dependent). + const unsigned int keyCTRLLEFT = 64U; //!< Keycode for the \c CTRLLEFT key (architecture-dependent). + const unsigned int keyAPPLEFT = 65U; //!< Keycode for the \c APPLEFT key (architecture-dependent). + const unsigned int keyALT = 66U; //!< Keycode for the \c ALT key (architecture-dependent). + const unsigned int keySPACE = 67U; //!< Keycode for the \c SPACE key (architecture-dependent). + const unsigned int keyALTGR = 68U; //!< Keycode for the \c ALTGR key (architecture-dependent). + const unsigned int keyAPPRIGHT = 69U; //!< Keycode for the \c APPRIGHT key (architecture-dependent). + const unsigned int keyMENU = 70U; //!< Keycode for the \c MENU key (architecture-dependent). + const unsigned int keyCTRLRIGHT = 71U; //!< Keycode for the \c CTRLRIGHT key (architecture-dependent). + const unsigned int keyARROWLEFT = 72U; //!< Keycode for the \c ARROWLEFT key (architecture-dependent). + const unsigned int keyARROWDOWN = 73U; //!< Keycode for the \c ARROWDOWN key (architecture-dependent). + const unsigned int keyARROWRIGHT = 74U; //!< Keycode for the \c ARROWRIGHT key (architecture-dependent). + const unsigned int keyPAD0 = 75U; //!< Keycode for the \c PAD0 key (architecture-dependent). + const unsigned int keyPAD1 = 76U; //!< Keycode for the \c PAD1 key (architecture-dependent). + const unsigned int keyPAD2 = 77U; //!< Keycode for the \c PAD2 key (architecture-dependent). + const unsigned int keyPAD3 = 78U; //!< Keycode for the \c PAD3 key (architecture-dependent). + const unsigned int keyPAD4 = 79U; //!< Keycode for the \c PAD4 key (architecture-dependent). + const unsigned int keyPAD5 = 80U; //!< Keycode for the \c PAD5 key (architecture-dependent). + const unsigned int keyPAD6 = 81U; //!< Keycode for the \c PAD6 key (architecture-dependent). + const unsigned int keyPAD7 = 82U; //!< Keycode for the \c PAD7 key (architecture-dependent). + const unsigned int keyPAD8 = 83U; //!< Keycode for the \c PAD8 key (architecture-dependent). + const unsigned int keyPAD9 = 84U; //!< Keycode for the \c PAD9 key (architecture-dependent). + const unsigned int keyPADADD = 85U; //!< Keycode for the \c PADADD key (architecture-dependent). + const unsigned int keyPADSUB = 86U; //!< Keycode for the \c PADSUB key (architecture-dependent). + const unsigned int keyPADMUL = 87U; //!< Keycode for the \c PADMUL key (architecture-dependent). + const unsigned int keyPADDIV = 88U; //!< Keycode for the \c PADDDIV key (architecture-dependent). +#endif + + const double PI = 3.14159265358979323846; //!< Value of the mathematical constant PI + + // Define a 12x13 font (small size). + static const char *const data_font12x13 = +" .wjwlwmyuw>wjwkwbwjwkwRxuwmwjwkwmyuwJwjwlx`w Fw mwlwlwuwnwuynwuwmyTwlwkwuwmwuwnwlwkwuwmwuw_wuxl" +"wlwkwuwnwuynwuwTwlwlwtwnwtwnw my Qw +wlw b{ \\w Wx`xTw_w[wbxawSwkw nynwkyw bwswcwkwuwjwuwozpwtwuwnwtwowkwjwmwuwuwkwIxmxuxowuwmwswowswmxnwjwhwowswowsw0wmwowswuwnwrwowswpwswowkwjwrwqw" +"rwpwkwkwtwnwkxsxqxswowswpwswnwswpwswowrwnwmwrwqwqwqwswswrwswowswjwpwlxjwkxuxLw[wcw_wSwkw mw\"wlwiw=wtwmxlwFw cwswnwuwnwkwjwswo{pwrwpwtwtwpwswby`w`yUwlw" +"twpwqwpwswowlw\\wrwrxuwHwrwfwuwjwlwlwTyuwVwlwtwawswowswowswcwuwmwuwmwuwmwuwmwuwlwkwuwnwswpwkwkwkwkwkwkwkwkwswoxswowswowswowswowswowswowrwpwswpwrwpwrwpw" +"rwpwrwpwswoznwtw Ww (wGwtwtwqwqwqwuwuwuwqwswuwqwqw=wqxtw`{nzp~q{ozowrwnxmwtwow bzawkwuwl}rwuwnwtwuwnwtwowkwjwlyjwIwlwswmwiwkwnwuwnwkwhwnwswowswowkwew" +"ewixnwsytwswuwnwrwpwkwrwpwkwkwkwrwpwkwkwuwmwkxsxqwuwtwpwqwqwswowqwqwswowiwmwrwpwswowtwtwpwuwmwuwjwowkwjwlxsxXynzmymznyozlzoznwkwkwtwnwkzuyrzmynzmzowux" +"myozmwswpwrwowtwtwrwrwpwrwp{mwlwiwHyuwpwtwkwmxlynzoxswmwmwswnwswowtxq|owtwtwpym{p{owswnwuwmwlwkwqwqxuwuxqwrwpwtwtwqwqwowlwuwuwkwmwlwtwowuwuwdwjznwl{nw" +"uwnwkx_wtxtwswtwlwtwWwuytwgyjwmwjwawswoyuwVwlwtwnwtwmwtwnwtwmwuwmwlwuwmwuwmwuwmwuwmwuwmwuwmxuwowkwkwkwkwkwkwkwkwkwrwpwuwtwpwqwqwqwqwqwqwqwqwqwowtwpwsw" +"uwqwrwpwrwpwrwpwrwowuwnwswowuwlymymymymymymyuyqymymymymynwkwkwkwjynzmymymymymykwmzowswowswowswowswpwrwozowrwW}q}qwtwtwqwtwtwqwtwtwA}rwuw_{p~r~r}pwtwow" +"rwnxmwtwow aw_w]wtwpwuwmxuwmybwjwlyjwIwlwswmwiwnynwtwnznzkwmynwswTyp}pylwmwtwtwtwswuwn{owkwrwp{o{owk|pwkwkxlwkwuwuwuwqwuwtwpwqwqwswowqwqwswoykwmwrwpws" +"wowuwuwuwowkwjwnwkwjwDwowswowkwswowswowkwswowswowkwkwuwmwkwswswswswowswowswowswoxlwswowkwswpwrwowtwtwqwtwowrwlwoxkwhxVxuxpwtypwuwjwnwtwnwkwswowtxnxmws" +"wowqwqwtwuxqwtwnwtwtwqwswowswmwm{nwuwlxnwkwqwqwtwtwqwrwpwtwtwqwuyuwpwiwhwnwmwrwnwbwkwuwlwlwswoxuxowlwtw`wuwrwszmwtwo}dwuwtwuw[}qymx`wswoyuwow_ylxlwtwo" +"yuwoyuwoyuwmwlwuwmwuwmwuwmwuwmwuwmwuwmwt{swk{o{o{o{owkwkwkwlztwpwuwtwpwqwqwqwqwqwqwqwqwqwnxowtwtwqwrwpwrwpwrwpwrwnwmwswowuwiwkwkwkwkwkwkwswswkwswowswo" +"wswowswowkwkwkwkwswowswowswowswowswowswowswcwtxowswowswowswowswpwrwowswpwrwWwtwtwqwqwqwuwuwuwqwuwswqwqw>wowuw`}q~q|q}qwrwpwrwowtwnwtwo~ izaw]wtwoykwux" +"qwtwswfwjwmwuwuwn}eyaxlwswmwjwjwpwswjwowswmwmwswnzWy]ypwlwtwtwuwswswowrwpwkwrwpwkwkwsyqwrwpwkwkwuwmwkwuwuwuwqwtwuwpwqwqznwqwqzkynwmwrwowuwnwuwuwuwowkw" +"jwnwkxkwGzowswowkwswo{owkwswowswowkwkxlwkwswswswswowswowswowswowjxmwkwswowtwnwuwuwuwpxmwtwlwlwlwiwlytwewtwtwqwswowtxoznwswnxmwswnwuwmwuwnwswowtwtwqwtw" +"twqwtwnwtwtwqwswowswmwmwswowswmwmwkwqwqwtwtwqwrwowuwuwpwuyuwq~own~own~owbwkwuwmznwswmwbwswawuwrwgwtwhwdwuytwXwJwswnxuw=wtwmwswowtxowswqxmwswowswowswow" +"swowswowswnwtwowkwkwkwkwkwkwkwkwkwrwpwtwuwpwqwqwqwqwqwqwqwqwqwnxowtwtwqwrwpwrwpwrwpwrwnwmwswowtwmznznznznznzn~swk{o{o{o{owkwkwkwkwswowswowswowswowswow" +"swowswo}qwuwuwowswowswowswowswowtwnwswowtwUwuwuwowswowswowswowsw@}qx`}q~pzo{pwrwpwrwowtwnwtwow aw_w_}owuwmwuwtwrwswuwewjwkwiwJwkwswmwkwiwp|kwowswmwmws" +"wkwWym}mypwlwszr{owrwpwkwrwpwkwkwqwqwrwpwkwkwtwnwkwtwtwqwtwuwpwqwqwkwqwqwtwiwnwmwrwowuwnwuwuwuwpwuwlwkwmwjwkwHwswowswowkwswowkwkwswowswowkwkwuwmwkwsws" +"wswswowswowswowswowhwnwkwswowtwnwuwuwuwpxmwtwmwkwlwiwmwtydwtwtwqwswowswowtwnwswowkwswnwuwnwtwnwswowtwtwqwtwtwqwtwnwtwtwqwswowswmwmwswowswnwlwkwqwqxuwu" +"xqwrwnyowqwpwiwhwpwuwuwowrwpwuwuwdwkwuwlwlwswo{owkxuwawtxtwszmwtwiwdwuwtwuwXwJwswmwuwKzmwtwlwtxowrwpwtxrxl{o{o{o{o{o{o{owkwkwkwkwkwkwkwkwkwrwpwtwuwpwq" +"wqwqwqwqwqwqwqwqwowtwpwuwswqwrwpwrwpwrwpwrwnwmznwswowswowswowswowswowswowswowswowkwkwkwkwkwkwkwkwkwswowswowswowswowswowswowswcwuwuwowswowswowswowswowt" +"wnwswowtwTymymymymy=wmw^wuwuwmxlxmyowrwowtwnwtwmxmw bwswIwuwmwuwmwuwtwrxswdwjw]wJwkxuxmwlwlwswlwjwowswmwmwswlwSycyawlwswowrwowswpwswowkwjwrwqwrwpwkwkw" +"swowkwqwqwsxowswpwjwswpwswowrwnwmxtxnwlwswpwswmwlwlwjwkwHwswowswowkwswowswowkwswowswowkwkwtwnwkwswswswswowswowswowswowkwswowkwswnxlwswpwtwmxmwjwlwiwTx" +"uxpwtxowswowtwnwswowkwswnynwtwnwswowtwtwqxuwuxqwtwnwtwtwqwswowswmwlwuwnwswowkwjwswo{pwrwmwmwswnwjwiwnymwtwnycwkwuwlwl{mwmwiw_wrwdwtwVwrw*wswmwuw?wtwlw" +"tzqwrwpwtzswkwswowswowswowswowswowswowswnwswpwkwkwkwkwkwkwkwkwswowsxowswowswowswowswowswowrwpwswpxtxpxtxpxtxpxtxnwmwkwswowswowswowswowswowswowswowtxow" +"kwswowswowswowswowkwkwkwkwswowswowswowswowswowswowswlwnxtwowswowswowswowswnxmwswnx >wlw\\wkx`wnwrwoznwtwmxl| gybw^wtwozmwsxpzuxfxlx]wnw_wlxjyn{o{nykwnz" +"mymwkynymwkwewewjwjwrwswqwp{myozn{owizpwrwpwkwkwrwp{owqwqwsxnyowiyowrwozmwlzmwlwswqxsxnwm}qwjxlwGzozmymznynwjzowswowkwkwswowkwswswswswnynzmzowjymxlznx" +"lwswqwrwnwm{mwlwiwHxuxpzmxlymynwswmwnwrwozmxuxo{pwtxn{pzmykwmyo}p{owkyuynwnwrwmwly`w_w_wbwjzo{pwqwnwmwhw_z>zY}M|nwuw2wqwqwryrwqwqyowqwqwqwqwqwqwqwqwqw" +"qwqwqwr{qyo{o{o{o{owkwkwkwkznwsxnymymymymycwuynznznznzmwmwkwuynznznznznznznyuzrymymymymynwkwkwkwjynwswnymymymymybzmznznznznwlzmw hwHwlwSwTw {+qnrmqapmp Kpepgpiuhpephscqfqhqfqhqfqhqfqhqfqhqfqhqixgudxdxdxdxdq]q]q]q]wcqjr" +"bt`t`t`t`taphpgplt`s_s_s_s_q`q]qmsctnqctnqctnqctnqctnqctnqbsktgs_uauauaucq]q]q]q[saqjqbs_s_s_s_sNpms_snqbsnqbsnqbsnqaq`qns_q !p Zp jp#q\\q6q7q l" +"q [sjq Qq -q OqZq]q Cq;q HqWq $rIq`qZq _q iqbqKqFqIq`q hp$q]u JqYpmpLp .p jp ]p Xr`q[r !p Tp\"p\\p6q6q mq Yx Qr -r Ps\\q_s" +" Ipkq:q HqWq $qHq`qZq _q iqbqKqFqIq`q hp$q]t IqYpmpLq /q kq Fq_q[q #s Tp\"q^q6p 1p Vu Rs YsJsMy &v])]2_4^U^ 6^T\\5])]1_2]T\\8^U^ K])]2`4^V^3] " +" U]*\\2a4`V\\8^U^5a F]*\\1\\X\\4^U^=]*\\" +"2a5^U^ 7aV\\4]*\\1a4`V\\8^U^ J]*\\1\\X\\4^V^3\\ " +" S],\\1\\W\\5g8^U^6c F],\\1\\V\\5^U^<],\\2]W]6^U^ 8h3],\\0\\W\\5g8^U^ I],\\1\\V\\5^V" +"^4\\ ;] " +" :\\-]2\\U\\6\\V`7^U^7]U] F\\-]2\\T\\6^U^;\\-]3]U]7^U^ 8\\Va1\\-]1\\U\\6\\V`7^U^ H\\-]2\\T\\6^V^5] =a " +" J] " +" N\\/]2\\S\\7\\T]6^U^7\\S\\ E\\/]2\\R\\7^U^:\\/]3]S]8^U^ 8\\T^/\\/]1\\S\\7\\T]6^U^ G\\/]2\\R\\7^V^6] =c L^ " +" *^ U` O^ )\\S\\ " +" !^$^3\\ E]U\\ K^$^4^ G^$^4] J^$^3\\ #^$^3\\ 4^ B[ " +"&^ Xe S^ (\\S\\ )Z Q^&^3^2]S\\ A\\S\\ K^&^3^ F^&^4_ >]S" +"\\9^&^3^2]S\\ W^&^3^ 6^ Q] M[ ?` ![1^H]?` =]4](\\ %` >b4c Bb ?`2a .a Ib Pb Aa `0`*^ $^.` <^F]F^F]G`G] F\\S\\ ;b %a2a2a2a2a a:]" +".a !^T_ Bg ` Dd2_8n?m7g3]:rD]P]P]@g <] 8] 8] B] 3e J^K^ If7^U^+b@d Fb@f5a Ad4e-] :f Ra0d AaF\\HaF\\HeJ\\?]._0_0_0_0_2\\U\\0tHh@n?n?n?n?].].].]" +"-h:_J]w " +"P[ 9[/a:aQa7[ Wl \"h E]1]T]+\\R\\;[4dL]Ag=])]2])\\ U^1f8c8k;j1`;k7h?n;h9g 5i*b:_8k6kBl=n?l7mD]H]C].].]L_A].`I`H`K]>kAj6kAj9kBuB]H]F]E]E^L_L^" +"R^L^D^I^BrBb7^+b(a D] ;] '] Gd A].].].].] ;] (b:].b #^Q] Dj !a Ff3_8n?m8i4]:rD]P]P]Bk ?_ 9] 9_ C]&[0f I]K]=]0g7^U^-fC\\S] IfBf6c B[" +"S]5[S].] `K]>k]*]3]W]6^U^._V_;]Wa5]*]2\\V\\6]Wa7^V^ I]*]2\\V\\5^V^2]7]+^V^ @]W\\=v P[ 9\\1c_8m:`R`Cn?n?l9`QaE]H]C].].]M_@].aKaH`K]?`S`Bk8`S`Bk;_R_BuB]H]F]E]D]MaM]P]L]B^K^ArB]1]&])c D] <] '] G] :].].].].] " +";] (^6]*^ #]P^ E^P\\ V^ H^T^4_8n?m:`S`6]:rD]P]P]C`S` Aa :] :a D]&[1^S\\ I^M^=]0^R[7^U^/^R^EZO\\ L^R^ N]U] :],\\0] \\H]B\\H]=\\M]>" +"]._0_0_0_0_0_/uK`R`Cn?n?n?n?].].].]-n@`K]?`S`>`S`>`S`>`S`>`S` H`ScE]H]C]H]C]H]C]H]E^K^@],^T^5],]1\\V\\6\\U`7^V^6]U\\ F],]2\\T\\6^U^=],]2\\U\\6^U^-e9\\U`4],]1\\" +"V\\6\\U`7^V^ H],]1\\V\\5^V^3]6]+^V^ B`1`1`1`1`6]W]>u P[ 9]2e>eUf;^ %q $^O\\ F]1]T],]S];[5]T]N\\@]P[=]*]0]2ZR\\RZ $]2]P]<_W]8]N]\\H\\A\\H\\<\\M\\=]/a2a2a" +"2a2a1_/]V];_M]C].].].].].].].]-]ObBaL]@^M^@^M^@^M^@^M^@^M^ J^N`D]H]C]H]C]H]C]H]E^K^@]-^Q]5].]1\\T\\7\\S]6^V^5c E].]2]S\\7^U^<].]2\\S\\7^U^,a6\\S]2].]1\\T\\7\\S" +"]6^V^ G].]1\\T\\6^V^4]5]+^V^ De6e6e6e6e9\\U\\>u P[ :_3f@gVf<_ &r $]M[ F]1]T],\\R]>d<^T^P]A^OZ=]+].]4]T\\T] &^3^P^=[S]8[K].]4\\X];],]!]<]N]>^O^ " +" 8ZM^3`P`Ba9]M^=^J\\C]K_B].],^H\\E]H]C].].]O_>].aKaHaL]A^K^D]N^<^K^D]N^>]JZ6]6]H]E]G]C]MaM]O^P^@^M^-^A]1]&]+_W_ D] >] '] H] 9] B].] ;] )]4](]" +" %]N]:c6] G] J^P^7a8_1],^K^;c=]H]D]P]P]E^K^ Ee <] \\I]A\\I]<\\N]=]/a2a2a2a2a2a1]U]<" +"^J\\C].].].].].].].]-]K_CaL]A^K^B^K^B^K^B^K^B^K^ K]K^D]H]C]H]C]H]C]H]D^M^?]-]P]4]0]1\\R\\ Ha C]0]2]R] E]0]2\\Q\\ 9c 9]0]1\\R\\ !]0]1\\R\\ ?]4] Di:i:i:i:i" +";\\6]G] P\\ :`5g@gWh>a (_ J]KZ F]1]T],\\R\\?h>]R]P\\@]1]+].]3^V\\V^.] T]2]N]5]8ZJ]-]6]X];]-]!^=]L]?]M] *]5_J_Ec:]L^>]H[C]I^C].],]F[E]H]C].].]" +"P_=].]X]M]X]HbM]A]I]D]M]<]I]D]M]?]%]6]H]E]G]C^NaN^N]Q^>^O^-^@]0]'],_U_ &] '] H] 9] B].] ;] )]4](] %]N]:d7] F] K]N]8c8^1],]I]>i@]H" +"]D]P]P]E]I] Fg =] =g G]&[2] <]O];]1] 1\\F\\=\\ Q\\F\\ S\\Q\\+]3\\.] IeU\\ M\\3\\N\\ ?\\I\\@\\I\\=]M\\<]0c4c4c4c4c3a1]U]<]H[C].].].].].].].]-]J_DbM]A]I]B]I]B]I]B]I]" +"B]I] L]J_E]H]C]H]C]H]C]H]C^O^>].]N] .] '`X_ I] FbWa=bWa=bWa=bWa=bWa<\\6^I^ ?Z2[ :a5gAiXh?c *^ H] 7]1]T]-]S]Aj>]R]Q]@]1]," +"],\\1^X\\X^,] T]3]L]6]'].]7]W];]-]!]<]L]?]M^ +]6^F^F]W]:]K]?]FZC]H^D].]-]DZE]H]C].].]Q_<].]X]M]X]H]X]M]B]G]E]M^>]G]E]M^@]%]6]H]E^I^B]O^X]O]M^R^=]O^" +"-^@]0]']-_S_ '] '] H] 9] B].] ;] )]4](] %]N]:e8_ H] L]M]8]W]7^2]-]G]AmB]H]D]P]P]F]G] Hi >] >i J[3] ;^Q^;]1] 2\\RbT\\Ge R\\VdR\\ T\\" +"Q\\+]4\\2a IfU\\ M\\3\\N\\ ?\\J\\?\\J\\AaM\\ G]W]4]W]4]W]4]W]4]W]4c3^U]=]FZC].].].].].].].]-]H]D]X]M]B]G]D]G]D]G]D]G]D]G]A[H[B]J`E]H]C]H]C]H]C]H]B]O^>g8]N] " +" 1]T_ 3[ 9] G_O^?_O^?_O^?_O^?_O^=\\5]I^ @\\3[ ;c6gAy?d7`8]L]7^7]L]>^ H] 6]1]T]-]S]B_W[U]>]R]R]?]1],],]0d*] T]3]L]6]'].]7\\V];]" +".] ]<]L]@]K] 7Z PZ X]7^D^G]W]:]K]?]/]G]D].]-]/]H]C].].]R_;].]X^O^X]H]X^N]B]G]E]L]>]G]E]L]@]%]6]H]D]I]A]O]W]O]L^T^<^Q^-^?]0]'].^O^ Sb7]U`2b4`U]8a8])`" +"7]T_ M].]%_O_@_2`0`3`/_3c9] )]4](] N_6]N]3^7a/c0_ <^ D[U^ Ga N]L]9]W]6^3]-]G]B`W]W`C]H]D]P]P]F]G] I_X]X_ ?] ?_X]X_ Nb7]2ZFZ=]Q]:]0] 3[SfU[I" +"g R[UfS[ T\\Q\\+]5]2a IfU\\ M\\3\\N\\ ?\\K]?\\K]AaN] G]W]4]W]4]W]4]W]4]W]4]W]3]T]=]/].].].].].].].]-]G]E]X^N]B]G]D]G]D]G]D]G]D]G]B]J]C]KbF]H]C]H]C]H]C]H]B" +"^Q^=j;]P_9b3b3b3b3b3b3bN`Bb3a2a2a2a V_2_2`1`1`1`1` ;aU] :]U` S^T]U^A^L^A^L^A^L^A^L^?]5]I] @^5\\ ]R]R\\>]1],],].`(] U^3]L]6]'].]8]V];].]!^<]L]@]K] :] P]#^8^A]I^W^;]K]@].]G^E].].].]H]C].].]S_:].]W]O]W]H]W]N]C]E]F]L]?]E]F]L]@]%]6]H]D]J^A]O]W]O]" +"L^U^:^S^-^>]0^(]/^M^ Wh:]Wd6f8dW]:e>h2dW]?]Vd<].].]O_>].]WdScK]Vd8f;]Wd7dW]?]Wa6h>h6]L]B]I]A]P`P]K^L^B^K^@l4]4](] PdU]A]N]2^8e5g;]Vd?^J^8]6]L] E]V`" +">pA]S]S]:e6kDo>]L]:^W^6^4].]E]D_U]U_D]H]D]P]P]G]E] K_W]W_ @] @_W]W_ Qf9]3\\H\\>^S^:]0_ 6[ThT[K]Q\\ S[T\\R]S[ U]S]+]6],] ?]L]@fU\\ M\\3\\N\\ ?\\K\\>\\K\\;]O\\ G" +"^W^6^W^6^W^6^W^6^W^5]W]4^T]>].].].].].].].].]-]G^F]W]N]C]E]F]E]F]E]F]E]F]E]D_L_E]K]W]F]H]C]H]C]H]C]H]A^S^^K^ O]S]S]B]I]B]I]B]I]B]I]@]5^K^ @]4[ ;f8gAyAg] F] 6]1]T]-\\R\\B]T[6]R]S]>^2]-]*\\.`(] U" +"]2]L]6]'].]9]U];].]!];]L]@]K] =` P`'^7]?\\I]U];]K]@].]F]E].].].]H]C].].]T_9].]W]O]W]H]W^O]C]E]F]L]?]E]F]L]@]%]6]H]C]K]@^P]W]P^K^V^9]S]-^=]/](]0^K^ Xi" +";]Xf9h9fX]h6]L]A]K]@^Q`Q^J^N^@]K]?l4]4](] QfW^A]O^1]6f9h;]Xg@_K]7]6]L]=]G]C^Wc@pA]S]S]]L]:]U" +"]5^5].]E]E^S]S^E]H]D]P]P]G]E]@Z+]V]V^-Z4]5ZKZ:]V]V^ Sh9]4^J^>]S]9]._ 8[U_Q[T[L]P\\ S[T\\Q]T[ T]U]*]7]*] @]L]@fU\\ M\\3\\N\\ ?\\L]>\\L]:]Q]:]1]U]6]U]6]U]6]" +"U]6]U]6^W^5]S]>].].].].].].].].]-]F]F]W^O]C]E]F]E]F]E]F]E]F]E]C_N_D]L^W]F]H]C]H]C]H]C]H]@]S];]P_=]S^8i:i:i:i:i:i:iVgIh9h9h9h9h<].].].]'d<]Xg:h9h9h9h9h" +"0^8k?]L]?]L]?]L]?]L]A]K]>]Xf>]K] O]R]R]D]G]D]VZOZV]D]KZV]D]G]A]4]K] @]3[ j=]L]8`7]N]?] F^ 6]1]T]5uI]T[6]R]S\\<^3]-]*]1d*] U]3]J]7]']" +".]9\\T];].\\Ua-^;]L]@]K^?].] Uc Pc+_8]>]J]U];]K]@].]F]E].].].]H]C].].]U_8].]W^Q^W]H]V]O]C]E]F]L]?]E]F]L]@^&]6]H]C]K]?]Q^V]Q]I^X^8^U^.^<]/](]1^I^ ]R_h6]L]A]K]?]Q`Q]H^P^?]K]?l4]4](] R^U^W]@]O]0^7g;_S];bT^@`L]8_7]L]>]E]E^W]V]@pA]S]S]" +"=_T_].].].].].].].].]-]F]F]V]O]C]E]F]E]F]E]F]E]F]E]B_P_C]L]V^G]H]C]H]C]H]C]H]@^U^;]N^>]T]6]R_;]R_;]R_;]R_;]R_;]R_;]R" +"_X_T^K_R\\:_S^;_S^;_S^;_S^=].].].]*h=bT^;_T_;_T_;_T_;_T_;_T_1^9_T`>]L]?]L]?]L]?]L]A]K]>aT_?]K] P]Q]R]E]F]E]V\\Q\\W]E]K\\W]E]F]A]4^L] A^@ZN\\ =i8e@yCk?^R^" +"=]L]9b8]O^?] Im B]1]T]5uI]T[6]S^T]<^3]-]*]3^X\\X^,] V^3]J]7](^/]9]T];e7]We/]9]N]?]K^?].] Wd Nd._8]O`U\\T\\K]S]<]L^A]-]F^F].]/]-]H]C].].]V_7].]V]Q" +"]V]H]V^P]D]C]G]L]@]C]G]L]?^']6]H]C^M^?]Q]U]Q]Ic6^W^._<]/^)]2^G^ !ZM^=`Q^=^NZ;^Q`>^P^=].^Q`?`Q^>].].]R_;].`R^X\\R^M`Q^=^P^>`Q^=^Q`?`1]MZ;].]L]A^M^?]Q`Q]" +"G^R^>^M^1^4]4](] D]P^A]R^X]@]P^/]9^Vb=^NZ;`Q^AaN^8_7]L]>]E]F^V]U]>]P]>]S]S]>^P^>`T`7]6]J]<]S]5^6]/]C]G]Q]Q]F]H]D]P]P]H]C]C^&]TZ,^7]7^N^6]TZ H]/^U[TZ9" +"]2n;]U]8]0d <[U]F[M\\P]2[R[ M[S\\P\\S[ Tb(]9]'\\ @]L]@fU\\ M\\3]P]9[R[1\\M\\<\\M\\7\\R\\8]2]S]8]S]8]S]8]S]8]S]7]U]6]R]?]-].].].].].].].]-]F]F]V^P]D]C]H]C]H]C]H]" +"C]H]C]B_R_C]L]T]G]H]C]H]C]H]C]H]?^W^:]M]>]U^6ZM^].].].]+i=`Q^=^P^=^P^=^P^=^P^=^P^2^:^P^>]L]?]L]?]L]?]L]" +"A^M^>`Q^@^M^ P]Q]Q]F]E]F]W^S^W]F]L^W]F]E]B]3]M^ B^B^O[ =k8d?xClA^P^>]L]9]X]8^P]>\\ Hl A] 9uI]T[5]T]T]:^ =]*]5^V\\V^.] V]2]J]7](]/^:]S];h:]Xg0]" +"9^P^?]K^?].]!e Je2_7\\PdW\\S\\L]S]<]M^@]-]E]F].]/]-]H]C].].]X_5].]V]Q]V]H]U^Q]D]C]G]L]@]C]G]M^?`)]6]H]B]M]>]Q]U]Q]Hb5c-^;].])] B]=_O]=].]O_>]N^>].]O_?_" +"O]>].].]S_:]._P`P]M_O]=]N]>_O]=]O_?_1]-].]L]@]M]>]RbR]G^R^=]M]1^3]4](] FaSaD^Qa?]R_.]9]R`>]._O]>^N]8`7]L]>]E]G^U]U^?]P]>]S]S]>]N]>^P^7]6]J]<]S]4^7]/]" +"C]G]Q]Q]F]H]D]P]P]H]C]D_&]&_8]8_N_7] B]/]T[3]1l:^W^8]1]W` >\\U\\E\\N\\P]3\\S\\ N\\S\\P\\S\\ S_']:]&\\ @]L]@fU\\ M\\2\\P\\8\\S\\2\\N]<\\N]7\\S]8]2]S]8]S]8]S]8]S]8]S]8]S]" +"7]R]?]-].].].].].].].]-]E]G]U^Q]D]C]H]C]H]C]H]C]H]C]A_T_B]M]S]G]H]C]H]C]H]C]H]>c9]M^?]U]'].].].].].].`O^N].]N^>]N^>]N^>]N^?].].].],_R^>_O]=]N]=]N]=]N]" +"=]N]=]N]2^:]O_?]L]?]L]?]L]?]L]@]M]=_O]?]M] O\\P]Q]F\\D]F\\U^U^V]F\\L^V]F\\D]B]3]M] RuJ`O[ >m9c>wCmA]N]>]L]9]X]7]P]?] Im A] 2\\R\\A]T[5^V^T\\:` ?](\\6]T" +"\\T]/] V]2]J]7])^1_9]S];i;bS^2^8^S_>]K^?].]$e@u@e6_7]QfX\\S\\M^S^=]N^?]-]E]F].]/]-]H]C].].c4].]U]S]U]H]T]Q]D]C]G]M^@]C]G]M]=c-]6]H]B]M]>^R]U]R^G`4c.^:]" +".])] B]=^M]?^/]M^?]L]>]/]M^?^N^?].].]T_9].^O_O^N^N^?]M^?^M]?]M^?^0]-].]L]@]M]>^S]X]S^F^T^<^O^2_3]4](] GcUcE]Pa?]Vb-]:]O_?].^N^>]O^8a8]L]?]C]H]T]T]?" +"]P]>]S]S]?]L]@^N^8]6]J]=^S^4^8]/]C]H^Q]Q^G]H]D]P]P]H]C]E_%]%_9]9_L_8] B]0^T[3]0_T_>cWc=]1]U_ ?[U\\C[N]R^4]T] N[R\\Q]R[ 'uG]&] @]L]?eU\\ M\\2]R]8]T]3\\N\\;" +"\\N\\7]S\\7]3^S^:^S^:^S^:^S^:^S^9]S]8^R]?]-].].].].].].].]-]E]G]T]Q]D]C]H]C]H]C]H]C]H]C]@_V_A]N]R]G]H]C]H]C]H]C]H]>c9]L]?]U]'].].].].].]._M]O^/]L]?]L]?]L" +"]?]L]?].].].]-^O]>^N^?]M^?]M^?]M^?]M^?]M^ I]O`?]L]?]L]?]L]?]L]@^O^=^M]@^O^ P]P]P\\G]C\\G]T^W^T\\G]M^T\\G]C\\B]3^O^ RuJ[X]P[ >o=\\XaX]BwDoC]L\\>]L]:^X^8]P]?" +"] E] 5] 3]S]A^U[4dT];b @](]6ZR\\RZ.] V]2]J]7]*^7d8]R];]R_]-]E]Fm>k=]-rC].].b3].]U]S]U]H]T^R]D]C]G]M]?]C]" +"G]N^^M]?].]M^?]L]>]/]M^?^M]?].].]U_8].^N^N]N^M]?]L]?^M]?]M^?^0]-].]L]@^O^=]S]X]S]D^V^:]O]2_2]4](] H\\U^W]U\\E]Pa?" +"]Vb-];]M^?].^M]>^P]7a8]L]?]C]H]T]T]?]P]>]S]S]?]L]@]L]8]6p=]Q]3^9]/]C]H]P]P]G]H]C]Q]Q]G]ViV]F_$]$_:]:_J_9] B]0]S[3]0]P]>o=]2]S_ @[U\\C[M]T_5^U^;u O[R\\R]" +"Q[ 'uH]/ZQ] ?]L]?eU\\ M\\1]T]7^U^4\\O]O]I\\O]T`MZQ]S]O]E]3]Q]:]Q]:]Q]:]Q]:]Q]:^S^9]QmO]-m>m>m>m>].].].]1hL]G]T^R]D]C]H]C]H]C]H]C]H]C]?_X_@]O]Q]G]H]C]H]C]" +"H]C]H]=a8]L]?]U]&].].].].].].^M]O].]L]?]L]?]L]?]L]?].].].].^M]?^M]?]L]?]L]?]L]?]L]?]L] I]Pa?]L]?]L]?]L]?]L]?]O]<^M]?]O] O]P]P\\G]C\\G]ScS\\G]N^S\\G]P]P\\B" +"]2]O] QuF]Q[ >oAqDuDqD]L]?]L]:^X^8^R^?\\ D] 5] 3]S]@`X[3bS\\R^G]W^N] P](].\\&] W]1]J]7]*^7c8]Q];ZM^=`O^4]4d:]M_?].])d:u:d=_5\\R]O^R\\N]Q]=j<]-]E]F" +"m>k=]-rC].].a2].]U^U^U]H]S]R]D]C]G]N^?]C]G]P_:g3]6]H]A]O]<]S]S]S]E^1_.^8]-]*] A]>^M]?]/^M^?]K]?]0^M^?]L]?].].]V_7].]M]M]N]L]@^L]?^M]@^M^?]/]-].]L]?]" +"O]<]S]X]S]C^X^9]O]2^1]4](]0_IZ O[R\\X]S\\G^O_>]Vd9_U];]L]?].]L]=]P]8]X^9]L]?]C]I^T]S]@]P]>]S]S]?]L]@]L^9]6p=]Q]3^9]/]C]H]P]P]G]H]C]Q]Q]G]ViV]G_#]#_;];_H" +"_:] B]0]S[3]0\\N\\>o=]2]Q^ A[U\\C[LcX\\6]T]9u O[RfP[ 'uIf7e >]L]>dU\\<] :f5d4]T]:fT\\O^NfT\\UdOeR\\O^F^3]Q]:]Q]:]Q]:]Q]:]Q]:]Q]:^QmO]-m>m>m>m>].].].]1hL]G]S]R" +"]D]C]H]C]H]C]H]C]H]C]>d?]P^Q]G]H]C]H]C]H]C]H]<_7]L]?]U^'].].].].].].^L]P].]K]@]K]@]K]@]K]@].].].].]L]?]L]@^L]@^L]@^L]@^L]@^L] I]Q]X^@]L]?]L]?]L]?]L]?]" +"O]<^M]?]O] O\\WmX]H\\WmX]H\\QaR]H\\N^R]H\\O]P]C]2]O] QuF]R\\ ?qCsDtDrE]L]?]L]:]V]7]R]>x '] 5] 3\\R\\?e3^R\\SbJ^V^O] P](].\\&] W]1]J]7]+^6e:]Q]-^>_M]5^6" +"h<^O` Qe8u8e@^5]R\\M]R\\O^Q^>m?]-]E]Fm>k=]KdFrC].].b3].]T]U]T]H]S^S]D]C]G]P_>]C]Gk6f5]6]H]A^Q^<]S]S]S]F_1_/_8]-]*] A]>]K]A].]K]@]J]?]0]K]?]L]?].].]W_" +"6].]M]M]N]L]@]J]@]K]A]K]?]/^.].]L]?]O]<]T^W]T]C^X^9^Q^3^1]3]']3dN\\ P\\R`Q[G]N_>]Q`;bW];\\K^?]/]L]=]Q^8]W]9]L]?]C]I]S]S]@]P]>]S]S]@]J]B^L^9]6p>^Q^4^9]/]C" +"]H]P]P]G]H]C]Q]Q]G]ViV]H_\"]\"_<]<_F_;] B]1]R[3]1]N]8a6]2]P^ B[U\\C[K`V\\7]T]8u O[RdN[ 'uIf5a <]L]=cU\\<] :f3`1]T];fU\\N^NfU\\T[S]NaQ\\N^G^3^Q^<^Q^<^Q^<^Q^<^Q" +"^;]Q]:]PmO]-m>m>m>m>].].].]1hL]G]S^S]D]C]H]C]H]C]H]C]H]C]=b>]P]P]G]H]C]H]C]H]C]H]<_7]L]?]U_(].].].].].].]K]Q].]J]A]J]A]J]A]J]@].].].].]L]?]L]@]J]A]J]A" +"]J]A]J]A]J] K]P\\V]@]L]?]L]?]L]?]L]?^Q^<]K]@^Q^ O\\WmX]H\\WmX]H\\P_Q]H\\O^Q]H\\O]P]C]2^Q^ D^<]R[ >qDuEsCqD]L]?]L]:]V]7]R]>x '] 5] 3\\R\\=f+]TdL^T^P] P]" +"(].\\2u *]1]J]7],^-_=]P],]>_M]5]7_R^<^Qa Sd .dC^4\\R]M]R\\O]O]>]N_@]-]E]F].]/]KdF]H]C].].]X^4].]T]U]T]H]R]S]D]C]Gk=]C]Gj1c6]6]H]@]Q];^T]S]T^Ga1].^7]-]*" +"] Lh>]K]A].]K]@]J]?]0]K]?]L]?].].]X_5].]M]M]N]L]@]J]@]K]A]K]?]._0].]L]>]Q];^U]V]U^Bb7]Q]3^1^3]'^6iS^ P[P^P[G]N_>]N^=dX]<]J]>^1]L]=^R]8^W]9]L]@]A]J]S" +"]S]@]P]>]S]S]@]J]B]J]9]6]J]>]O]5^8]/]C]H]P]P]G]H]B]R]R]F]C]Iz<]]K]@]" +"O[X\\I`3]O]<]O]<]O]<]O]<]O]<]O];]P]?]-].].].].].].].]-]E]G]R]S]D]C]H]C]H]C]H]C]H]C]<`=]Q]O]G]H]C]H]C]H]C]H];]6]L]?]T_4h9h9h9h9h9h9hK]Q].]J]A]J]A]J]A]J]" +"@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]Q\\U]@]L]?]L]?]L]?]L]>]Q];]K]?]Q] N\\WmX]H\\WmX]H\\P_Q]H\\P^P]H\\O]P]C]1]Q] C]:]S[ ?sEvEqAoC]L]?]L];^V^8^T^>x " +" '] 5] 4]S]]K]A].]K]@p?]0]K]?]L]?].].b3].]M]M]N]L]@]J]@]K]A]K]?].c4].]L]>]Q]:]U]V]U]@`6^S^4^5b2]&b^Ua<]J]=" +"c7]L]<]S^8]V^:]L]@]A]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]?^O^7^7]/]C]H]P]P]G]H]B]R]R]F]C]Iz<]\\I\\@\\O\\X\\J`3^O^>^O^>^O^>^O^>^O^=]O]<^P]?]-].].].].].].].]-]E]G]R^T]D]C]H]C]H]C]H]C]H]C];^<]R]N]G]H]C]H]C]H]C]H];]6]L]?]S`8j;j;j;j;j" +";j;|Q].pApApAp@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]R]U]@]L]?]L]?]L]?]L]>^S^;]K]?^S^ N\\WmX]H\\WmX]H\\QaR]H\\Q^O]H\\O]P]C]1^S^ D]9]T\\ ?sFwDo?nC]L]?]L];" +"]T]7]T]=] Hj ?] 4]S]8d/]T]T]N^R_R\\ O](] =u Se =]0]J]7].^(]?]O]+]?^K]7]7]L]]K]A].]K]@p?]0]K]?]L]?].].a2].]M]M]N]L]@]J]@]K]A]K]?]-f8].]L]>^S^:]U]V]U]?^4]S]4^4`0]$`<^Si O[O" +"\\O\\H]N^=]M^@^S`<]J]=c7]L]<]S]8^U]:]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]?]M]7]6]/^E^H]P]P]G]H]A]S]S]E]C]Iz<]]M]>]M]>]M]>]M]>^O^=]O]?]-].].].].].].].]-]E]G]Q]T]D]C]H]C]H]C]H]C]H]C]<`=]S]M]G]H]C]H]C]H]" +"C]H];]6]M^?]R`;l=l=l=l=l=l=~Q].pApApAp@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]S]T]@]L]?]L]?]L]?]L]=]S]:]K]>]S] M]P]P\\G]C\\G]ScS\\G]S^N\\G]P]P\\B]0]S] D]" +"7\\T[ >sFwCn?mB]L]?]L];]T]7]T]=] Hi >] 4]S]7[Xa1]T^T^O]P_T] O](] =u Se =]0]J]7]/^'^A]N]+]?^K]7]8^L^]K]A].]K]@p?]0]K]?]L]?].].b3].]M]M]N]L]@]J]@]K]A]K]?]+e9].]L]=]S]9]V]T]" +"V]@_4]S]5_4b2]&b<\\Nd M[O]P\\H]N^=]L]@]Q_<]J]?e7]L];]T]8]T]:]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]?]M]8^6].]E]G]P]Q^G]H]A^T]T^E]C]Iz<]]M]>]M]>]M]>]M]>]M]>^O]?]-].].].].].].].]-]E]G]Q^U]D]C]H]C]H]C]H]C]" +"H]C]=b>]T]L]G]H]C]H]C]H]C]H];]6]M]>]Qa>`P]>`P]>`P]>`P]>`P]>`P]>`PoQ].pApApAp@].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J]?tG]T]S]@]L]?]L]?]L]?]L]=]S]:]K]>]S] " +"L\\P]P\\F\\C\\F\\T^W^T\\F\\T^M\\F\\C\\B]0]S] E^7]U[ >sFwBl=kA]L]?]L]<^T^8^V^=] Ij >] ]K]A].]K]@],]0]K]?]L]?].].c4].]M]M]N]" +"L]@]J]@]K]A]K]?](d;].]L]=]S]9^W]T]W^@`5^U^5^/_3]'_8ZJ` K[O]P\\H]N^=]L]@]P];]J]@_0]L];]U^9^T^;]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]6]J]@^M^:^5].]E]F]Q]Q]F" +"]H]@^U]U^C]E]G_\"]\"_BZT]TZB_F_;] B]1]R[3]1\\L\\?o I_S] A[U]F[ V]T] W] N[S\\R]R[ S] ]L]6\\U\\ ']T]/\\O\\V\\@\\H\\A\\O\\V\\M_0o@o@o@o@o?m>l>].].].].].].].].]-]F^" +"G]P]U]C]E]F]E]F]E]F]E]F]E]=d?^V]L]F]H]C]H]C]H]C]H];]6]N^>]O`?]M]>]M]>]M]>]M]>]M]>]M]>]M]?].].].].]-].].].]/]J]@]L]@]J]A]J]A]J]A]J]A]J] K]U]R]@]L]?]L]?" +"]L]?]L]=^U^:]K]>^U^ L\\P]Q]F\\D]F\\U^U^V]F\\U^M]F\\D]B\\/^U^ OuD]V[ =sFwBk;i@]L]?]L]<]R]7]V];] F^ Nu=[T^3]S]R]O]N_V\\ N](] 1] ].]L]6]1_%]Aq0]>]K]" +"8]7]J]/] Md:u:d>]3\\R\\K\\S\\Po@]J]A].]F]E].].]E]F]H]C].].]S^9].]RaR]H]P^V]C]E]F].]E]F]M],]8]6]H]>]U^8]W^Q^W]H^U^4]2^3]+],] R^M]>]K]A].]K]@],]0]K]?]L]?" +"].].]X_5].]M]M]N]L]@]J]@]K]A]K]?]$`;].]L]=^U^8]W]T]W]@b5]U]5^,]3]'] J\\Q_Q[G]N^=]L]A]O];]J]@].]L];]U]8]R];]L]@]O]O]J]S]S]@]P]>]S]S]@]J]B]J]9]5]L]?]K];" +"^4].^G^F]Q]Q]F]H]?_W]W_B]E]F_#]#_B\\U]U\\B_H_A\\U]U[ H]1]R[3]1]N]?o H`V] @[T]G[ U]T] X] N[S\\Q]S[ S] ]L]6\\U\\ (]T]/]P\\U\\A]I]B]P\\U\\M^/o@o@o@o@o@o@m>].]" +".].].].].].].]-]F]F]P^V]C]E]F]E]F]E]F]E]F]E]>_X_?]W^L]F]H]C]H]C]H]C]H];]6]P_=]M^@^M]?^M]?^M]?^M]?^M]?^M]?^M]?].].].].]-].].].]/]J]@]L]@]J]A]J]A]J]A]J]" +"A]J] K]U\\Q]@]L]?]L]?]L]?]L]<]U]9]K]=]U] K]Q]Q]F]E]F]W^S^W]F]W^L]F]E]B\\.]U] NuC\\V[ =eXZXdFgXhAi9h@]L]?]L]<]R]7]V];] E] Nu=[S]3\\R]R]O]M_X\\ M](" +"] 1] ].]L]6]2_$]Aq0]>]K]8]7]J]/] Ke=u=e<]3\\R\\K\\S\\Po@]J]A].]F]E].].]E]F]H]C].].]R^:].]RaR]H]O^W]C]E]F].]E]F]M^-]8]6]H]>]U]7]W]O]W]I^S^5]3^2]+],] R" +"]L]>]K]A].]K]@],]0]K]?]L]?].].]W_6].]M]M]N]L]@]J]@]K]A]K]?]\"_<].]L]<]U]7]W]T]W]Ac5^W^6^+^4](] H[R\\X]S\\G]N^=]L]A]O];]J]A^.]L]:]W^9^R];]L]@]O]O]J]S]S]@" +"]P]>]S]S]@]J]B]J]9]5]L]?]K];^4]-]G]D]R]R]E]H]>kA]E]E_$]$_B^V]V^B_J_A^V]V] I]1]R[3]0\\N\\>o G`X] ?\\U_Q[T\\ T]T] ] N\\T\\Q]T\\ S] ]L]6\\U\\ )]T].\\P\\T\\A\\I]A" +"\\P\\T\\N^.o@o@o@o@o@o@m>].].].].].].].].]-]F]F]O^W]C]E]F]E]F]E]F]E]F]E]?_V_@]W]K]F]H]C]H]C]H]C]H];]6k<]L^A]L]?]L]?]L]?]L]?]L]?]L]?]L]?].].].].]-].].].]/" +"]J]@]L]@]J]A]J]A]J]A]J]A]J] K]V\\P]@]L]?]L]?]L]?]L]<^W^9]K]=^W^ J]R]R]D]G]D]W\\Q\\W]D]W\\L]D]G]A\\.^V] NuC]W[ ]K]9]6]J]/] He@u@e H\\R]M]T]Q^J]A]J]@]/]G^E].]-]F]F]H]C].].]Q^;].]Q_Q]H]N]W]B]G]E]-]G^F]L]-]8]6]I^>^W^7]" +"W]O]W]I^R^6]4^1]+],] R]M^>^M^@]/^M^?]-]0^M^?]L]?].].]V_7].]M]M]N]L]@^L]?^M^A^M^?] ]<].]L]<]U]7]X]R]X]B^W^5]W]6^)]4](] H\\T]W]U\\F]O_=]L]A]P^;^L^A]-]L" +"]:]W]8]P]<]L]@]O]O]J^T]T]?]P]>]S]S]@^L]A^L]8]5]L]@^J]=^3]-^I^D^S]S^E]H]]G]C_%]%_A_W]W_A_L_@_W]W_ J]0]S[3]0]P]5]4],b =[ThT[ R]T]!] M[T\\P]U[ R] ]L" +"]6\\U\\ *]T].]P[S\\B]J]A]P[S\\N].^J]B^J]B^J]B^J]B^J]B^K^A]M]=]/].].].].].].].]-]G^F]N]W]B]G]D]G]D]G]D]G]D]G]?_T_AbK]E]I^C]I^C]I^C]I^;]6j;]K]A]M^?]M^?]M^" +"?]M^?]M^?]M^?]M_?].].].].].].].].]/]J]@]L]@^L]@^L]@^L]@^L]@^L] J^X]Q]?]L]?]L]?]L]?]L];]W]8^M^<]W] I]R]S]C]H]C]VZOZW]C]VZL]C]H]@\\-]W] MuC]X[ ;cWZWbDe" +"WZXe>e6e>]L]?]L]=]P]8^X^:] F^ H\\R\\5[S]5]Q]R]O^L` K]*] 0] !^.]L]6]4_\"]2],^>^M]8]6]J]0] DeCuCe E]R\\M]T\\P]I]A]J]@]/]G]D].]-]F]F]H]C].].]P^<].]Q" +"_Q]H]N^X]B]G]E]-]G]E]L^.]8]5]J]<]W]6^X]O]X^J^Q^6]5^0]+^-] R]M^>^M]?].]M^?]-]/]M^?]L]?].].]U_8].]M]M]N]L]?]L]?^M]?]M^?] ]<].]M^<^W^6aRbB^V^6]W]7^(]4]" +"(] GcUcE]P_=]L]A]P]9]L]@]-]L]:^X]9^P]<]M^@]P^O]I]T]T]?]P]>]S]S]@^L]@]L]8]5]M]?]I]>^2],]I]B_U]U_D]H]:c<]G]B_&]&_?_X]X_?_N_>_X]X_ I]0]S[3]0_T_5]4]+` ;[" +"SfU[ P^U^#] L[U\\P]V[ Q] ]M^6\\U\\ ,^U^-\\P\\S\\B\\J]@\\P\\S\\N].]I]B]I]B]I]B]I]B]I]B]I]B^M]=]/].].].].].].].]-]G]E]N^X]B]G]D]G]D]G]D]G]D]G]@_R_A`J]D]J]A]J" +"]A]J]A]J]:]6g8]K]A]M^?]M^?]M^?]M^?]M^?]M^?]M_?].].].].].].].].].]L]?]L]?]L]?]L]?]L]?]L]?]L]3^;aP]?]M^?]M^?]M^?]M^;]W]8^M];]W] H]S]T^B]J^B]J^B]J^B]J^@" +"\\-]W] G^1_ :aW[V`BcW[Wc]N]<]P]7]X]8] F]KZ X]S]5[S]5\\P]R]N]K_ K]*] 0] !],]N]5]5_\"]1],]<]M]9^6^L^0] Ad Nd A\\R]O^U\\P^I^B]K^?]H[C]H^D]" +".],]G]F]H]C].].]O^=].]P^Q]H]M]X]A]I]D],]I^E]K]AZH^8]5]J]<]W]5bObJ^O^7]6_0]*]-] R]M^>^M]?^/]M^?^.]/]M^?]L]?].].]T_9].]M]M]N]L]?]L]?^M]?]M^?] ]<].]M^;" +"]W]5aRaB^U^6c8_(]4](] FaSaD]P_=]M]@]P]9]L]@]-]L]9b9]O^=^N^?\\P_Q]H]T]T]?]P]=]T]T]?^L]@]L]8]4]N]@^I^?]1],^K^A`W]W`C]H]7]8]I]@^&]&^=i=^N^^P^=^P]7]X]8_ H^M[ F] 6]S]>ZQ[T^6]P]S^N^K^ K]*] 0]:] 8]0],]O^5]6_2ZI]1]-^<^O^9]4]L]0]<].] Uc Pc1]2\\Q^S`W^P]G]B]K]" +">^J\\C]I^C].],^H]F]H]C].].]N^>].]C]H]MbA^K^D],^K^D]K^B[I]7]5^L^_O]=].]O_>].].]O_?]L]?].].]S_:].]M]M]N]L]>]N]>_O]=]O_?] ]<]-" +"]O_;]X^5aRaC^S^6a8_']4](] D]P^B^Ra>^N]@]Q]7]N]?^.]L]9a8]N]=^N^?]Q_Q]G]U]U]>]P]=]T]T]?_N]>]N]7]4^P^@]G]@^1]+^M^?mB]H]7]8^K^?\\%]%\\;g;\\L\\:g G]/]T[3]2n7]" +"4]'^ <\\F\\ M\\S\\ J\\F\\ L^N^6\\U\\ ,\\S\\-]OhG]K]@]OhQ]LZ=]G]D]G]D]G]D]G]D]G]D]G]D^L]<^J\\C].].].].].].].]-]J_D]MbA^K^B^K^B^K^B^K^B^K^A_N_B^K]B^L^A^L^A^" +"L^A^L^:]6].]K]A^O_?^O_?^O_?^O_?^O_?^O_?^Oa?].].].].]/].].].]-]N]>]L]>]N]=]N]=]N]=]N]=]N]2^;_O]=]O_>]O_>]O_>]O_:a7_O]9a E^P_>^P_>^P_>^P_>^P_>\\,a H^.]" +" /[5]T[S\\8a1`<]L]=^R^<]O^8b7_ H^O\\ F] 6\\R\\=[R[U^5\\N]T]L^M` L]*] 0]:] 8]1^+]P]4]7_1[L_1]ZM];].] R` P`.]2]QfXaN]G]B]L^=^L]C]K_B].]+" +"_J]F]H]C].].]M^?].]C]H]La@^M^C]+^M^C]J]B]L^7]4^N^:a4aMaK^M^8]7^.]*^.] Q]P`>`Q^=^NZ;^Q`>_LZ>].^Q`?]L]?].].]Q^;].]M]M]N]L]>^P^>`Q^=^Q`?]/ZL];]-^Q`:a4`" +"P`D^Q^7a8^&]4](] S]Sb>_P^@]R^7^P^>^MZ<]L]9a9]M]=_P`XZB]Q_Q]G^V]V^>]P]=^U]U^?`P^>^P^6]4]Q^?]G]A^0]*^O^]P`>]P`>]P`>]P`>]P`>]P]X^LZN^NZ;_LZ>_LZ>_LZ>_LZ?].].].]-^P^>]L]>^P^=^P^=^P^=^P^=^P^2^:^P^=^Q`>^Q`>^Q`>^Q`:a7`Q^9a Dk],a " +"H]-] /[,[._0_;]L]=j<]N]7`5a J_S^ F] 6\\R\\=^U[W_5]N^V^K_Rd L],] /]:] 8]1])^T^3]8_0^Q`0]<]Q_8^S^8^3_R_=]R^:].] O] P]+]1\\PdW`N^G^C]N_;`R`C]NaA].]*`O" +"`F]H]C].].]L^@].]C]H]La?`S`B]*`S`B]J]B`Q_6]3_R_9a4aMaL^K^9]8^-])].] Q_Tb>aS^;_R\\:^Sa=`Q]>]-^Sa?]L]?].].]P^<].]M]M]N]L]=_T_=aS^;^Sa?]/^R_:]-^Sa:a3_P_" +"C^P^7_8^%]4](] S_V^X^?aS^>]T^5_T_=`R]<]L]8_8]M^>`SdA]SaS]E^W]W^=]P^=_W]W_>]X]T_<_T_5^4^T^?^G^C^/])^Q^8c=]H]7]6`S` ?] ;c >c E]._W[V\\9]4^J^9]4]%] ;]L]" +" IZQZ H]L] !u ,`Sd9\\U\\ ,ZQZ,]E\\E]L]?]E\\M_S^>^G^F^G^F^G^F^G^F^G^F^G^F^K]:`R`C].].].].].].].]-]ObB]La?`S`>`S`>`S`>`S`>`S`?]J]CcS`?_R_=_R_=_R_=_R_8]6" +"].]V[R^?_Tb>_Tb>_Tb>_Tb>_Tb>_Tb>_T^V_Q]M_R\\:`Q]=`Q]=`Q]=`Q]?].].].],_T_=]L]=_T_;_T_;_T_;_T_;_T_1^:`T_;^Sa=^Sa=^Sa=^Sa9_6aS^7_ Bi:i:i:i:i=]+` I],] /[" +",[-].]:]L]]C]H]K`>kA])kA]J^Cm5" +"]2j7_2`M`K^J]9]8tC])].] PgX]>]Xf9h9fX]],fX]?]L]?].].]O^=].]M]M]N]L]qA^U]W]U^D" +"i<]O`?k=]Xg:h3a7f>uCn?]/eSe;]:]H]7]5k >] :a n?\\H\\8]4]%] 9^R^ *^R^ Xu ,q9\\U\\ /]D\\F]LfH]D\\Li>]E]F]E]F]E]F]E]F]E]F]E]F]JnIkBn?n?n?n?].].]." +"]-n@]K`>ki-]]C]H]K`]Wd6f8dW]:i>]+dW]?]L]?].].]N^>].]M]M]N]L];f;]Wd7dW]?]/i7c3dV]9_2_P_E^M^8_8m4]4](] QdV`B]Xe;d1f8h<]L]8_9]K]>]XdW_@eWeBg;]O" +"`=g;]Vd8f1`6d=uCn?]/eSe;]:]H]7]3g <] 9_ :_ C]+f>n>ZFZ7]4]%] 7f &f Vu ,]XdW_9\\U\\ /\\C\\F\\KfH\\C\\Kg=]E]F]E]F]E]F]E]F]E]F]E]F]JnHh@n?n?n?n?].].].]-l>" +"]K`]C]H]J_9a<]$d?]I^?c0].b3_2" +"_K_M^G^;]8tC](]/] M`T]>]U`2b4`U]7c;])`U]?]L]?].].]M^?].]M]M]N]L]8`8]U`3`U]?],c2a0_T]9_2^N^F^K^8]7m4]4](] O`R^B]Va8b-`3d:]L]7]9^J]?]V`T]>cUc?c9]N_:" +"a8]T`3`-_4`X IX *W FW " +" " +" " +" HX W 4Z 3VCT X W 4Z " +" HX W 4Z 'VCT ;X W 3Y 2UCT KX W 3Y 0W " +" " +" " +" @W !W 4\\ 5YET ?XHX 8] >W !W 4\\ 7XGX KW !W 4\\ 7XHX +YET :W !W 3[ 5ZFT ?XGX EW !W 3[ 7XGX 5W " +" " +" " +" >W \"V 3\\ 7]HU ?XHX 9` ?W \"" +"V 3\\ 7XGX JW \"V 3\\ 7XHX -]HU 9W \"V 3] 7]HT ?XGX DW \"V 3] 8XGX 5V " +" " +" " +" W $V 3VNV 8XGX IW $V 3VNV 8XHX -_KV 8W $V 2] 7_KU ?XGX CW $V " +"2] 8XGX 6V " +" " +" :W &W " +"4VLV :j >XHX :VJV >W &W 4VLV 9XGX HW &W 4VLV 9XHX .j 6W &W 3VMV 9i >XGX BW &W 3VMV 9XGX 7W MW " +" " +" " +" CV 'W 4VJV ;j >XHX ;UGV >V 'W 4VJV :XGX GV 'W 4VJV :XHX .j" +" 5V 'W 3VKV :i >XGX AV 'W 3VKV :XGX 8W N[ " +" " +" " +" DV )W 4VHU TEY ;XHX V ,V 2UEU TCU :XGX =U -V 2UCU =XGX ;V NV" +"IV \"W " +" " +" JU /V 3VBV ETBT :U /" +"V 3VBV FU /V 3VBV (U /V 2UAU DU /V 2UAU @V NVGV " +" $X " +" *X " +" JX GTBT MX GX 7V :UEU DX GX 7V " +" JX GX 7W 4X GX 6V GX GX 5V (X &X " +" )X 8V " +" ;X FTBT " +" LX IX 7X W E\\ AW ,W ,W ,W ,W " +" HY GV +Y 4Z NX @X %W " +" DUDU =Y 7W KW 6Z 4XDT BTAT BW KW 6Z IW KW 6[ ,Y )XDT AW KW 5Z 4XDT " +" KW KW 4Z ,W BW 8V (S W H_ AW ,W ,W ,W ,W L] GV +] ;a " +" #[ F^ 8XGX +W BTEU " +" *R 9a :W MW 6\\ 6ZET ?XHX W Ja AW ,W ,W ,W ,W N_ GV +_ " +"?e 8] J] Jb 8[ <[ $Y FY 7XGX =Z Di 5W 8Z .Y !W FW *Y 4W)V*W)V-Y(V " +" W $a MY " +" EW 5W >W Kb AW ,W ,W ,W ,W !a GV +a Ch =f ^ Mf 2Z @x Mx a 5a &W 0g #\\ -_ <\\*V.\\*V0a-V\"X )Z /Z /Z /Z /Z 4WJV 1~U+d Kx Mx Mx Mx MX -X -X -X ,j" +" @[3X Dc 8c 8c 8c 8c W \"W 4VNV 8]HU ?XHX " +"BW \"W 3VNV 8XHX 2W ?W &XHX ^ K~\\ >S 3Q +[ @[;[ ;Q ;e HX 2VFV #VBV FS 6`1V#g GV !V 3V !T 7W 0d" +" :` ;j ?k -[ Dq :g Ky Df ;d $f 1Z @o 5j Np Ex Mt :m\"X/X'X -X -X3Z%X -]0]0\\4X Gi Lm 4i Ln ;m#~W$X/X-X(X-X4Y4XCY1Y-Y.Y&~S%a >W $a N[ EV " +"5W >W Lc AW ,W ,W ,W ,W \"b GV +a Dk Aj \"_ h 3Z @x Mx ?i 6X C~Q)X?X?X Ni 6V /V /" +"V DX &f #W0W e >XGX %c#e +b\"i 9_ Be 9d 'V 3k %^ /c @^*V0^*V2d.V\"X )Z /Z /Z /Z /Z 3b 1~U.j Nx Mx Mx Mx MX -X -X -X ,p F\\4X Gi >i " +">i >i >i BiEV.X/X'X/X'X/X'X/X.Y.Y#X 'j ;V \"V 5VLV :_IT >XHX V \"V 5VLV 9XGX IV \"V 4VMV 9XGX ,ZHY A_IT XHX AV \"V 3VLV 9" +"XHX 2V >W &XHX !_ K~[ >T 4R -_ D_?_ >S =t Fh IX 2VFV #VBV FS 7c4V#i HV \"W 3V !T 7V 0f @e >o Co 0" +"\\ Dq W M" +"d AW ,W ,W ,W ,W HW 1b GV +b Fm Dm #` \"j 4Z @x Mx Am 8X C~Q)X?X?X!m 9X 0V 0X EX 'h" +" $W0W \"h ?XGX 'g%g 0h%i :a Cf :f *V 4m %^ 0e A^+V/^+V1f1V!X )Z /Z /Z /Z /Z 2` 1~V0o\"x Mx Mx Mx MX -X -X -X ,t J\\4X Im Bm Bm Bm Bm F" +"mHV-X/X'X/X'X/X'X/X-X.X\"X (l ;V $V 4UJU :ULXLU >XHX XHX @V $V 2UJU 9XHX 3V" +" =W &XHX !` K~Z >T 4S /a FaAa @T @w Hl KX 2VFV $WCV ES 8e5V$j HV \"V 1V \"T 7V 2j Eh ?q Dp 1\\ Dq >" +"l Ly Hn Bj +l %e E\\ At >s$v Kx Mt >u&X/X'X -X -X5Z#X -^2^0]5X Jo q ;o r Br%~W$X/X-X(X,X6[6XAY3Y+Y0Y%~S%W 3V IW !_ FW 7W >W Md AW " +",W ,W ,W ,W HW 2[ ?V #[ Hn En #` #l 6\\ Ax Mx Cp 9X C~Q)X?X?X\"o ;Z 1V 1Z FX KS 0i #W2" +"W LV ,i ?XGX *l'h 3l'i ;c Dg ;g ,W 6o %^ 1g B^,V.^,V0g3V X *\\ 1\\ 1\\ 1\\ 1\\ 2^ 0~V2s$x Mx Mx Mx MX -X -X -X ,v L]5X Jo Do Do Do Do HpKW" +"-X/X'X/X'X/X'X/X-Y0Y\"X )n XHX ;UEU XHX @W &W 3VJV :XHX 4W =W &XHX " +" 1\\ 1\\ 1\\ 1\\ 1\\ =XMV K~Y =S 4U 1c IdCc AU Dz In LX 2VFV $VBV ES 9g7V$k HV #W 1W #T 8W 3l Fh ?r Eq 3] Dq ?m L" +"y Ip Em -n )k H\\ Au Av%x Mx Mt ?x(X/X'X -X -X6Z\"X -^2^0]5X Ls\"s ?s\"s Et%~W$X/X,X*X+X6[6X@Y5Y)Y2Y$~S%W 3W JW \"a FW 8W >W NZ 6W ,W " +",W ,W ,W HW 2X \\ 2V 2\\ GX KS 1j #" +"W2W LV -j ?XGX +ZEZ)VGY 5ZDZ)i T 5V 2e KfEe CW G| Jp MX 2VFV $VBV ES 9XIX8V$l HV #V /V #T " +" 8V 3n Gh ?s Fr 5^ Dq @n Lx Ir Go .o -q L^ Bv Cx&z x Mt A{)X/X'X -X -X7Z!X -^2^0^6X Mu#t Au#t Gu%~W$X/X,X*X+X6[6X?X5X'X2X#~S%W 2V JW #c FW" +" 9W >W NX 4W ,W ,W ,W ,W HW 2W ;V NW IZCY Hp JY &ZDZ 9^ Bx Mx Eu W *W 2UFU ;XHX 6W ;W &XHX 7h =h =h =h =h DWJV K~X >T 5W 4g MgFg EY J~ K]FZ MX 2VFV $VBV " +"ES :XGX9V%\\GX HV $W /W 3PATAP GV 3[H[ Gh ?]F] GZE^ 6^ Dq A]FX Lx I\\F\\ G\\G[ /[H] 0u N^ Bw E_D^&{!x Mt B`C_)X/X'X -X -X8Z X -_4_0_7X N^" +"E^$u C^E^$u H^E\\%~W$X/X,Y,Y*W7]8X>Y7Y'Y4Y#~S%W 2V JW $e FV 9W >W NW 3W ,W ,W ,W ,W HW 2W ;V NW IY@X >X " +"4[AV IX &X@X 9^ Bx Mx F^E^ =X C~Q)X?X?X&^E^ B` 4V 4` IX KS 3\\GW \"W4W KV .YBT ?XGX .V7V,P=W :W8W /VEV 3V +V /V " +" 7eGU KU 3WCW ;U-V$U-V LV5V NX +^ 3^ 3^ 3^ 3^ 3^ 1~W6_D^&x Mx Mx Mx MX -X -X -X ,{\"_7X N^E^ L^E^ L^E^ L^E^ L^E^ !^Ed*X/X'X/X'X/X'X/X+Y4Y X +Y?" +"X ;V *V 4UDU >TEZ TEZ T 5Y 5g MhHi G[ M~Q L\\AW MX 2VFV $VCV DS :WEW:V%ZAU HV $V -V 3RCTCR HW 4ZDZ H\\LX ?Y?[ HV>\\ 8_ DX )[?T -Y J[B" +"[ I[CZ 0WAZ 2x ^ BX>^ G]=Z&X=b#X -X '];[)X/X'X -X -X:[ NX -_4_0_7X \\?\\%X@^ E\\?\\%X?] J[=X =X W X 3W 4W ,W HW 3X ;V NX KY?X Ca 9Y:R HX (X>X :VNV BZ /X '\\?\\ A^ FX0X)X?X?X'\\?\\ " +" Db 5V 5b JX KS 3ZBT !W6W JV .X?R 4V4U HV ;V4V 1VCV 4V *U 0V 7fGU KU 4WAW TDX ;a 6V ,V 4UBU GV ,V 3UCU 0` 6TDX 4V ,V" +" 2UDU >TDX >V ,V 1UDU :V 9W (o Do Do Do Do GWIU J~V >T 6Z 6i jIj I\\ N~R M[=U MX 2VFV %VBV H] AWCW;V%Y=R" +" HV %W -V 4UETEU IV 4ZBZ IWGX ?V;[ IS9Z 9VNX DX *Z;R -X JZ>Y JZ?Y 1U>Z 5`C_#` CX;[ H[7W&X9_$X -X (\\6X)X/X'X -X -X;[ MX -_4_0`8X![;[&X" +"=[ F[;[&X<[ LZ8U =X W W 2W 4W ,W HW 3W :V MW KX=W Cc " +";X7P HX (WR !X8X JV /X

f6d-qO6qN+ox!4lM%p#z8GJNJu%T)-TrIAaF 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

qVs~|xBAA%S6b8NYNZKrRbQ1(oH!9QYi@2X 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%0D3* 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 z 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 z

bgvG~%>m5$YEMns>P>dt@N70aqi*-#W9!80}0B#`h#v`jEgIJK#92{*}^oy6jp4N1SPwWK~f9l3Bn7wXtjk$#xpo0*bu11!X+80%z0J_ zbY8YixupS@X|>{uRAq3)h&PadWgQ}1I!c%nEE}2QU*ACJGQsKaC z1_j!r_?vR%HMeAWp)gN~>FS!z#{dY~cCNR6S$P@q=4l0XY%oI~ve`apat!TaCJD$V zjNG6GHQ;ayDAoJW{I)#*V;Mlg&e9*1$O!MyTCG-ceOj!PK9sbyEVvk7(a)1tNSj7O zc*{~jL3opRZ~$}P4Yt+Tv`2GEn(V@2C|WKJ`e-F?8I>m9Z)3`SO^!-h3J%v1;KPzs zJHc*<#~ccf$x0bjl^0mbGv#@p=xE!h-h#hE!pn;5h26DE#< ze#i+CgN+9qW{2}-#NichaSpRhRE(Swa-(8*R>?FO4GVj8j|ZZR+=U#Q06Of}%UQAS zn|V54+uoa+GLBRoQoXZ1`cwgyi{?t%dMHCyKs}XVAtwn8ETxY;W%@{{Ek#Il!Vc`K}>VOVRM6B5rvl8x|Erdrhb;^AOp3?o3p@c@lVkp89sznlbW8tiIuc2fx7y-3s@lq7*l-XH*h{Q1}?08Qk zWXjqgd3LxWNlr|fMfUcTHhg5g7g_;{6)LJY5)oPxkxMvRU?V&N_Ff}6D}Q5=M&GI; z1N%6Sj||MOj^5<7xyBBdvG-WzGe(fB_PL{&vr^^?%a=Hio#BlKAmJ(iK7vd=EzwrZ z9c@|$(pTw+oJfPkLyyE6GAXLh=^p_+v;5O=30iFHTn18KKsH5WxFvWW&LLULMcva* z0Y(ydBin-fM$Y-ez;a{F9~kPKQO(Hs#yu4&em=Liwi`pf$Jy_X=yj&5>A_&Edc~FU zkFcL%;4_S1TeH;37TE~`PWyjOb))3VYfe)01+J4*!5Ds+M&~BLdLlYYvQ2Un#l+W= ztG@_1CNewih-9oy3H8OUARx zaW}h)Y1y~C#w5o%Ynhx88}#ysQ#`BtmutSJRCNTmoTW$N5Qxo@xenO%P7qE>8WKJi zZke<@*e@FCP061SD}w#ZEia}2&a~v16 z8R#l&R_O={Vy6c#h<#AFD28jVan|HTWH481hB+VQn|VQ_JfeXQ3dSepJ8Wedo^yqF z%Ngt;FD$@k!j?4+V?bdnndkqc*Z}2WIz=%$&3@n_pAtz7^n~P$%wEX87)|$y1{P{= z#p0^4>ckWoEUv{um}WcKaZyd$&RJ$9!;NZ&J|F(fCF;?nOkUn27(s`)N7piBK3amn z0ATB(LFn2xF2CCp4AG<~?UM1aYQ2=1<%5XJ6*Wz5usKLJZOR8BjnVSM6sucNRV zaJI6j!vd_k?TevacM1}9;MXbT4GN{tZ_DK z5y7GRMG7y>miKJ$r~O0kVE@_K(a`~JTW|O1@WuX5TbVwV+-|zIxiUpkWw?8X&u4); zdoO4x+4kNu8Jh1Ko*(E;h27tV(bK0ChXa40u;nRTB=2YKE4Pi>u&4_N;%6x--YPvI z46~I0{^<*!dfaf=)sV~vXo0p`@M>?^!_v3mR&ux9DwY27=YR6Q(MumDtWn#nt+DOE z@G7Z~u19s==Cx#e@x^U4;J@|tRsOrSV*PD28_niw`!CJrT61;1v9i9>_)DX?0&oA~ z{YOn?ga1>1|3m(J@{LEv2FW!XkX;kCv27ba!Y+t`^+J;x893|-5GK3P=z)XVF78&m z=H_N=8UJn5zbo|bD*d}g|E|-&8}#qyGC^p;R4wDbP5QS*|F-Gh75aCT{#~Pg*XiF4 zs`w%X2JSSvOz-fDe}URU>guw$KkNd6RS6`w7qCvX(X2MtgzjIMC?M8fL|?iX(^ZZ7 zL50Lhc*{iI&cT6)W)O*Jq9$kyvaZLQnH-r1e)pRE_J-Q>0VeC}3T<)tvN}C_wP!)X zD+Cz)Yqq3@+YSxLe%U{JdGz|s+d2Hz`(@|kWaseg*QZLvfQGPaPCp=XBQzq2fzUzs zMF8+>?_~ES)Yy5pf3Sb{E0R+$_RkLYPEWlTM;;L7}@m`cgy^`wJr(Y3F;1#d0joa{5ZRva{Oi6j)=BBKplrfMEDdG z5JM^;*CV(;-_;oNNxmE%MXAm5SCXf{ieR;*rJr01Xkg%v)TE*jNi-IACo~#H0L0oM zw;*n7D|W2r|FH+TZ>$!F!vhS&9IRUB?APPH>Z_f@*DrQ<&t9MGom7vG_fB@s_78vR zoc?-xw)YBJA}=#o8w}=wYe|X!&{7=D2H}pY5_Xyl_V0TqhkFMu=xkSc7mFwX#8^?7 z9lB0_NAhBFqsxL2NklQhytL^f6=`}uVdGihL?a}es z{?Xw(+_BYHFL1Qb51IPGEUmr4R6&MTf+%~*Mh^NLKZz|4IKHEmMTrCBNIsZ_KS`(&ugM3|%tX+QZL zh!{68IyNs&7-z(EP!Eqvl7f0lc!dZotoJ#j6wE0LH%lllMge0W_RfN)pA17(tN>T5 zA18LWjS@$LA(`a-6R&!edJRuViCMPMly)7~R{JP^q9aK))hS=Z=~8Qof_S=?galph zH>h`;t0z9@YtgB|Mz5*G>s(Dbx8-a#uOib)k(&UMRzMJ-IW|fu1&rhxXtt;9s;Vk` zmANP0YotWd9!90Y3wbnF@uD-OmvTKC1Y4dK2vf`R&3P$<*0KGXDx3ULAH_R5oef&r z#uTA5K`IL9k*jNF2}leiaXDR^HLLacrqzUMKzGvUJ?S)9c+X4zgqFNfF-I~8X~q<# z!UOTX|65B-{F?}_N!BDv+Qqdo7RCU3E~_U+^*Nj&hBBmFT>;$FLJUeb@0BlOWg#-& zJ$iMF+zamJqft|?{OEy`5WI?0Zr;3y)a1o z;YC-yfcp}D>jL90e#YOZfWTk&Tlq#ny+N#Xk@S|-i(!zOzcW7(C@?JXpxV9mqXb_? zNvj$RsKaqOxTy}KTVHHZn3Jj+9=*Bnld#(n8}m^U*2D=@cEh59Y2dj2d|lRsC4cM9 zTeVOr2vy#dq|b}zT*=x}wO*BAP}7UWo=VM@-j`3Fcn3kckQlp22uwtK2_g!PpGvvA z`I<*_7~w&dLDz!>PZXh5IB3;sI#r1*QwFut(eTivd-^agqu_1%&N4W+1sMvC+U z@u#&fU6b3je?zNFnU!mO3A}OdhTwfR066NhKk(S9eNk_KsJVA^2VSGaRyD*Rl2@@m zx;9$>vhMdEhWZTS55g4mX_VeS8n(F1j0OPd^`g53?um)#LKVX&3&6<4W}`&+Z-6X3 z-K4|xZ9|>_ySIb2jT^Wu{Wuf=urLFV1o-oSgor{CCvu9$C^)uAZ<|&Y>Trty3q^)Y zNwAQqFqY5~K&5oRI|tbW7Lq`1Q?F^>iziEfFVHVii&SQ{V(=t7RBXqLI=`f3Aj z#np`lUS%IWzqNTIp5R8rPxLoHY_ai9|6E}ihw&JO$3?O`= zLE$e8*xE`4+@Rg=v}&@iFv-Jn0W{Q7zWXe1Wyx`~YQ**R&w=(f$<0EEO?+W$Ugqd058JT#>e2q@6Fa+OUe? z&s>pByU3y z^z@_pG;B6nJbZX+tG$+rzsU$Dm7j+pVQc&&4%iU30k%3!+AXo?B6a#ky-^e4;$Q6l z=r{UDv^$D`1{mRf7Ed%u>X~-7_{Gno?uFQXqlefZ07peX657iAh$MP)jm*T#JAQ1f zyz|9Vn{Wv{!AIKK$+h@%!5{j8QC<9K2Ym&cI*5PNs}UnC`paMW=|Vr=%Eyhhd->Q8 zQuT=XR}JiTLw>m3)K3@s@m3ZdS0ZBmEtldey5!4CoAWcr0tlZPf1#RO13SN>z;CV%_d z7bNhUH^b;|DDH1STC_Xh?{!x`HCyUUiz&-jf{XRmHeT*FoAqX^HhVjG;}6M&jhozn zCI!N5&~mT66F=KOh?d)gjt8rJG;Rr1->t2BYKR0VX*y_))E=S8$%^;)`%!m6cssM7 z^LtTp0Sn1nez930amhlWgn>XIpky1flmT(Di~>NcvDm6`?w%;_d1V2s?4=Yb0yDox z!%KvyUF1-xNI9dIc$GKSI%_NBMKWM(4EGC5h_ethI$0eELGwE zaEgf7+aJ0#g6Hq&o97E#O1uldt;Ww6NV=mWKs~RCQq(z4#VR@8Stzb7xdk**bxBi6 z>KO@@>QaVMGGDB&nZJm@u_~{v=1mf$U zubzSn`EfFZs66q!R5-BEndyydBAzy0&O}E{k?{B-mrSCTR8PE*>T~!aO;$iJx zfe_3Ky^j5d;VnNt^kQF@L6VH#B2mTN7QF3r6&4~-Vz0;UIS^yZxtb@egXk!J|i)we$!er#Rg}JUL#4z51aDAECz%fzx>^t zVkGY9HPUtJftHZJ6P3pw5N$OC-jZ+HYx?nrmV8v3nsFY#-q_#{AbH3Sc!#QzKp^m2 zA_mo?*h5SZs>i-nueoOa630LihW011`!sQAeMEDWRxEjUah=8Cnm#oDf7 ztBp)CCKhwWHnYVxv&D!GRAmIwm@5!xip2Rs#vBUbF;~Eb!USZl5YUWvDIy~C#gJ;u z6l6luEQ<7_D#XO3`aB5LiG`bR$)qCXFC-wTI#H79EvzrU9dTEQxD-$AmfFd3XJ{Ie z$`F;wPrr#jyh}&Cjfj?1)tIo5Trsng7`Qujq*jT&Q zKY(ntfFbQ_y|~@bg>N^_=L_?PfG>$x{&mZ1m)!p#K@vGjFNvU4uS0nS5q&G4R*lD1 z^|+>1HlK zl(V{#A7}$fI+_WmS!tWBG-;VBo~wRz0eC*`UIV=&ntLRHo^4&4TuFM3qca#*Y{Jwm zNd=Y4o=~#8!b(y0mF(`KK|mH1Y$F2n!#oJL=JS6@lj0LsG!|;C8b&3re3_(G6%pPwOT?lE(>+mvPkcdow&=Z{= z_d=n1f&b?G3%@%~9F^#OW=;HFbP=q%crENQU_>gQ<>O=3w?3>9$xD$W%2y{sNfc65 zQeyk*Z@aO!Q6yf)@3PJShFUNIf)TTq4Q7S-kW2+}*pU6u#i~n%1%*)A7RYLCJS*Yr zTB;22{Of)m9C8NyP0ry%a;xfuS0qNozttjPb7sA;EYBi7^`c~IHEdN>GlAe%Wia=>}9<~)q~n#Q7z?+Yu8`f?LMDN+8y@B71Ukgvn{zfdZOYP|=T z30bl4cW;1m$=4))#-0%}7|B$0EhANZ%!bMW?`}E{7`!AUvcv(Xf0ql)y6bpQrlIlJ-ynBtJ=!cY8$R<8->+inqaPfb4}xKlctflOGi`8b>^xK zMyg_S%~h?Ly>5d3rK&>43FBemiN+GDaG2bZBw0KW5fG%Ye}9>{^nIcfS|J!9M15Vk zpsHQ(-c{(na9};3v>y1U5Xa$1SzMX$V5N*b4_vvxYKlKhM-M_#P!teV94DCAQTS{$ zL}ofoG9-bY@Q|;?d;wR(fu#{rXjvF738OVDjFyJcPw^IL3k8G_Pgb+Px!k!7%)k|t zO%AmV1=NdznUtHq3r*-n6n1ZraU)`hugfs<+>^ ziW|(%%I3{lrnR+4_jer%ubUvu7ZY}^1!KdgzM*QWh;ea1+8QZ6rn)nL-9YJnlb{-p z@VDEJ;M9VHox3#f1Pg895>r*>tf8-o64i0sCnCXD7l={8OF1hx{eDg=4wDGO&g)*hBTMOKQ0u>CAh*9Z+~GReCuLi;a@&Q zoX{$Bz6f;cWFI>+8NLWSLK(Hz53H)Yb>ZOx6D-@hOQ9c$UkTjG(iehTF`<1SECW;$ z^}lGKK=lCDRYQe~3SksnVfaImJp3ptRc{j_?(ok{@+T}P>obLpe^z=0O!p^Sdly`;^ih`fuZH6RtIOJrf(gfe91{@4eV5RHNvCld+&JoBnv>~N zktk+Ya)~xj0B%pTDy%Dqm$5$x3U5kFH&8yi^utmWhiiOAx0_ zFS9AIkTxCpyorQ*^+8%SCh<0zcmYw%x3b+~HwH4%#aXOCSK+Gz$+OcG3}q%<$fb2v zH0cdu=gz-f=~v_6BIrA?fN&wfKkLL@;nRkC+H{S9)))O_R9Eh_p)mevHVUdW+Kq`7 z$%O@VdtuV0uSJ->5JvZQ-O)6>go52Xo)KO+gC+LIDHtn$bKfMAI9l@T>jXH$7VSHc z7}=nsTKRh?U#RW6fQHxYM&Wu`oKW{(FYxu-mDP9ddK;7K!G3z!Tyt$TVo0vfGqYDaJab~b;l&rYcN@7QiY^b29L?RJ3z$Kwb z;rWAWtWX#dB}J+(OPfT+L=|8a1l#_3QV4X$y^4kf0vL0jjoG(ppB565B+X?lJwI61BV77Vf{6>i1pL!K8d&aq2ucJngddZ8fNj_ z(vP9}zC9x>hu$Szca&ox`zrmp5r5d^fG2}39dJ6F)4%%p(+~5;jdOEr(rkh!ty(l` zpV?X%a${n4%^#utt^Ku|cB-LiF&+)jfo4WS>yjWOTXA7tEoGP+jk=Yoq^l?hoi8Z* z=-x~Fd|@aRrm3{oubLmK{H5>$=?D2_-=;~7}1SaVj) z-#wD~iwAGfn6^lMkc7b?P`Z>jCBGH?|(%vLvqxPm#>`(9Q()XhHeNp*) zvx48+Y`HpKWNkE;Tr}OoREDDV79va0$u)w0woWf7tN|1Re9mc{lOQab{Xj{tf>04R z!W^VvXJ}&)D(jE|Cf9|Uo#cAeHDY+3J6~vI=_;8+9@=E`E+(JXaF9gOsoz1N$)Y)z ze+HJU&!$CfsT$+h)zUc5_A_l2^Kuq5lB6-lU@xGN#aD+oAsG)_g-if^G>Sz@drC38Ejq`M;UI5=Q1UPs1Zn&*6+vXJ$jv-FTk73T$M=z6Hg_bN5aP8>(4k%5#6ycbW2}Nb{hTIMLJXR*|HE zWTRAJbUFE6rY1&muHfdK#e79y&=lFGU1UD{FjhEqAidviH<~OM?c$R|%m{A{IiukV zdF$Uh^mk|k-*bs2Z(U{*cIjJnjoyw%OCN9V;eRe1a@lS)tC!>7!ZeY4LtJvja=N1X zQ2Z)1ZJkoDczKE{-mR^=EWy`St9L!eEZ=Qx-b@nKiI6}pf!+N@bU#Ttkk>ZdlPf>F zBseUk*;U~hI`?oF5Uqff9tIA(Fmy;LLSN*eKqw(!?~lA0ayZZuRhNY?I{z55JUw?t zI6DM%hpV+>b{shTW{pfyIOmJudF zsqt#gvX)9>J55T<1=kwgSqdV1F_q~Uxb4HyIg4UhNmyjKS7^|u;oZ7y;q*q-n0;-sQ2gpd9g=$o7tpz91Hi~e11%-%G5LCzS{eKd-q z1nAfRRu}+s(Q+}~z(hF6d~arV{^?W`ImkL}cgb%S|BVJpPL7^&E?GWW;;JZUX5nUI zwK&XBwg!AhjnwFlTt~ZAc$#9~PwU3jMujz`e8{Y{BxhAP|NA!q+s;t<=d^oGLBu(k zVAYII-m~12WVF41i3_?6BqXtw6*gVsB{RH`6~wSOme5kQ7hVCQ+JBt7cp<5adbOoG zoDVIhL99I(L_G{K_*jstCIIbT3=E(ZXE-Huj8z$)+8Jai7lyG$*~8v?_vQI0p=5XW z<+As#M5)6}ji;9hAIlqrP`wdoUBy_}#W@iNgr>T$>mW>!U38k@>ohMhGvf{rC-+Si`>2R~-9Nb+eitXe@LSAHDdkuZY0y**PS|L; zK@bELqCoe4KMi6GzI7XTuU?;?Q6{PVLvP1hS~gHaCZM-iHyGrSynC#uT45?$6Y1Rj zOH4q5<>Qqa&jy8^#K5r}EV6qoVt2w!(i7QWFUhEs;*pHGOw<4B641sR+OivQpwC2> zO*kB=AF9}wG}-)s*V2*+2u*moxgp2mL^UM+?T?4P2$Cs^s11wH4+FbL!ozGyJ@>>9 zvQ<&BJjEjufLu7b%s|2q<_l83Q`y^lApgV@5z#z$G}q@~pkh`Aw;2!=2M-@mL#q2Q z>W>pS!~77ZyhQiB4%SqKVjkF?bcw@xau{G<#8^Jcw`O%zlFRQflVLAcBDlGU6kr*D z7=M`0H~=vgj;?3JKz9ihe3i{MaQOG4>wYvAfnoc+%8`E&+7K{GAIDF<dAPb0&5uNM zTUi4rY<^(gM=WYE$jp;qbVT=zz|Yle_~@z~DcTz7{pgktbRb(F1@idzZtTJoYf*lb zy&s4z9AEn|0MuU@iO zQx*8?Ob-%u4+*jLu9K5j+HI8TrW&AFo@6_ z_*}6khdsPs<3H;h1)29=kIXMF`wy8pxOotrxc0*vUirAECj>f{i25)QOBMEB9|WA& zA((WBOu0e$V*Fi1$tTA;Svi>M7{ZS7co)uwyj0pu}k?q>XG?c{$$;wsY z7x-z)hQLA}vCG!cH>cMi|J5c)M|!=qthx%+Ybp%yvz}{JyrZ2TkWzNC8t|d*uJKS* zN2K1O)D>NdhD+plRny}{$yaoz%q^)FTp&HimwV|iNp66F*85c5X7g2PH(#~w<}=3e zRX;YjXRJ5pjc7%rig9xITu8xJ`5em+_x2ECXu-~p||6}$VaBK zrQ8N^NyT1w9LK>h?LT0Sn-Q?!WB%NW;G^KogD^HSgTea|<$vQ;T6g}#a!%&!MTtxs z(Nj=V3QrvCVU)`Bla!@!A;$b=A!qAKImJEG7G*2tSD9JS#RQrKFlD>~$`z4<3Udfj zv}c47h~zCqdZ4d7TBM}jc!YW@AHxt(KF??*lgOFP0N;y&+5NnjrRJF_^Ed?dMRbe# zA1RAw5?&4czRtu49p%gx(_27!JGDXaD(!^XLCP5)F)1ZX6Y%&&@-K<75{^+<$=Z#m z@1wEf>)aAtC{a9A2%Pw^W=-N~KOQWx3qr+VKTBVeU=Zs2NJi3;%^D%7R!GeyKV&tg zIlOieTyp%(z*|BAw#>~qCt{jaT)IjT<*brdF)<7gze;{*X~c>e?qF?WNknUrMVKcv zo!?*!RxD$JTEhe&j3_EuD+Mt?Oxc3zjW8Ro$fYNdOCS?pE>k|%JCU~q6Qp8wfgEb| zBWKD$U8js1#fvcrMy@?TIacht*^iD|WCE}AXXuq&Lc?fGmPKoMp;nSb|FnvTRRHtR zHplp^l($b|X6q`{aoLs}GvBN=RjU{3uDH;o&k~c_D*XojP@lq!ftoCN&C%XmVl9xm z#sulDD&7T(NVb%bOPS;)*{{(}Sn%a~RLQ%aFPTRA(gNH##ofA1^Tm%ei29^=^_G`R7Rfs{L0X;!gN3efE7R01l^Bx$F)gl?kFz-C+qw`>ZpqL z4>snT+#_8ypaU-xMRXY!&_i_R-Cc_hsPSUGbi!ArnKqVjro@*|EX@ih%Nm8<8>-Te zu0l?jXA~(hg|sczmBs2NL-l4mmd!~qCJ8a-1VFl9=>-Wg1Q%g%1Fkr2!>mlFC~6fO}3uV%buMrsq)q9 zGDxN_iXa2%dtF_YlOS9E%udc4HG+S$bX*5?F z>+QdI|4|dkgK4P0{~`bB)b_C8XnT=Rl3h6Xm{XV}9ldcEaMZ;Eh3SQoF$MJn+=|B9 zBIh%+bfh)$!ya&NKuKNUxA4;7_y+zBMhC`xx+y#YpTEzXUpEf?R5qf3ap++9UV@7e zuNVDdn=*_LA!~xsESOWBOekz$*?oE8oQMrd?aFtyEi$mD**uxlywVBv9ah zBn#rjExdTr^iE$L1L@ZD{>vYFt+v-(+ge%KYHfP2&vw05quDN%>f?ST@kd}SuRZHOU0K4VGSwUPT|%G&9GbHZj4Y7nm|r_v03qN^(YGuF{3x$I zvkN&0QNjs2oe;*u5QXG{3qt95=j`Q{M}Yd_#o9{!_q5uswXtIUTel0H39R>cjb;lQ zKeJ${c#?T*{=SX|K|Q#^^shl&ujSy|-wQuHhr#tDzn9eg5%#$Xlz0MLJoc;2TC3Kg zn)aqv+j^J8N^p%Qxs5HhwmKJEt=49H%Yz2GH+Xc>AnPg)Ml9cBMkN7$0zUOQ+3yh5 z4km#1Y7@hXCF6dor>~Ac>{4r)W`b;ymF7kPAg{V-6>Md@>=Q{veeOkpkSYPH>S99e zXq=A5sRdwT-O&<&Fbl1 zH#QK2kyrlvzpa+w#o|x9yA^K*a8L^oN2}RvYR$T@R+pU%8w!jMmizTAiQ-TV9&A099M@^8 z>-`jc`+PJ=D4qG34t2|Ol!o;X-DSPPmRB=xt!i}?2bbYJwG6-Tk_%(*M{*780N8a1 z?-BWCJ`g^xRuO0wF6MFE-@Z=M(N?_^kww;FLKEA5VbgUXp~epHu{|5w%h4zugY%^txGF ztu?Aw-QW1B)~NqR`%8`d0>2FaLxn^c+U=r-00~8yg#l`aM1uiT`OUYs9Tu+#XhEI? z_`L?-?WJLW*buKJK?1&AK6d+2bR~bJW8k8R5)8ZY9nveEc8gqK;2o{jw(D%2(f;(X z$G{iUE-k^SRT}qc$Wq|c$6%VD1v=hhZP^ykDTcz-B2y#UnBGG5=LM>8>8HTZi)zD& z)5Q~+o|O1TU|Kf~;sGY04SF?q&sLm0``x}T9@9Zt^`F_#^`?0b-dzVGM_ypwhwOl5 z)>>)O=ui&_Z;|Gy!7m!3S!&g_XzNJ%$Xod#umNwb6<^CriA{tBb5clz+W?F!->*eB z0kY9p$$(GBmw@L{fsdEVm~5e~9&I#vsMSafb;__en$BTwv<>3N`mpL+f;;x(>Bdo# zh$%qTu32ww{joh;Z#sLn4s*uWA6B$JZM2*QQS_&!}|1XH7&BdMlv=Q4sVjmZ05SH(7#fRMtcuuo(hR0j)NQqi&ESk-2*9Rzs}b zp4qQliF}`0&9$P6{J6Ebg?rIL$$qzk-A4s{FidMeQXWRI_kqVJLAU-s|D9pyWQH%U01_Q?e<1tZA-dhVDT}AUZq5A31UZ*-b8@4uBe0sVnf}12JSTO z^j0m(qSE$;>mqEoH$MZ^rW4f4Y9Wo*ULm@}nld(51im8n;|FV#>sm-jNQh9<{$?%$ ziLnLAmyAc~p$3z9VpdpfY~)BEc>`HvKT$FwZz2J%Xzr7RTs!|ipFsE@T3MjqF)+)E z6?ponk z<+uLoYO8STuWp)KpEzLCt)V!6ggfxe=PhtkAZJ92i*<=#`a6f?hM(o|MF5 zg}~R>9|wGWqme-e$1jgPmY><>TDI`l{&O>aB65~*(>S8uxSyGg z&6acC;Oglkinw16A5?4AuBD z<%ZF@6?f-;&s-ayr-u1wcJ&dWYU8rBK%f+wMr%u}N23hq!zCSSSuC$!X*uQ9*qT#d zz0yWGwCId2vCem=?UY%sw2NidD{aesBP$VxW(#D(D=R1~qJHh!oyrx;cL<1@33cU< zf4*RlJMyPsaGGFnWyRDj@WNT2*H&lP3u~*+y?`6=f5cu`-~4kg%&-?$SF#cY!7&Y$ zUKzzjb`?Xh$b1i!*7k^2*&N@ub9lP%?FtS&r}JD{Yp$9Ik|bFF zx%2a0=lJE$>C1_Tea)!}Um@EF8oEP@_n$Zi_9WzH!6~ih*G{c_VU5kr!V7V|*~$y$ z>m2LtI#=+2`M#qu=I4)IKWhHa-T%+&`@HE(d(e|VC+{;SFNViIC-1W+Zx9TCcKUPj zzF_D5d1rjy?1jVh&nx$f?hFh`^XKG!&g6}U!1wh2oV-~kuVwOr#0LU9JWl+Jupg!m zxuXBuXAsBen8DV{BWG}g@%1orp>qQF{_|(%wc?cVnP z2j{=-KL733=S-t>3#(cD-?oLnbn3_l)R?|mp={)Zao3#`Ms+Pja@9Va46DxC=Kn6K zQO-t{CbjqhkGSf8x2$MgjOwi^NZC+tMR`bjqn(Aa|f>t zB~)bE;jFed*77>2QH+6a1Q%tNUTGR8Jyhz_`rKamBH!xOmCcQ*zSXO%&8+p*WyTwP zb#=Yi8~lY?aIKm32JiPgO5=f%CAwD8jfMkezh{@pn3+*PEwVrG7L7U;w5dTgs9k-% zQHX6;*PGe7eRlf1ikg;Jr;bC{AruCb2sq_+mOAost}d!vakWf=4oX9^PW-emX3^VWYsfw zFU+1d9N3>-cJTcn#^1;~53X*u8ih+mE?(CB4gC9XFdlgQV0e{YQ>rmjOYg^5V~odY zLRo8=*6YpH_14DPiuHZHQQ-8LTw}Ob(|VuM*}OU3$0dMcJ?>_j+9(_hd|R2hnew;W zWvlLHG2CV=t7|gOhvB&u2N=ns$m?#cXx9u3{|% zp}4-UH5{sZX_Vphf)U&a7;%@~3qpGkD{ICeMt+iX{JyD}TU%}A2o`Iot7s#V8AYaq zsRpz^t+m!2@-u6AYb)&>{CuHRgXYhDUC-OR`a|2;cx`ZVd~n3WhpF=DPD?bD4Ru5(u+5a2IO!^yVL-;-f(D0C*VOS@6wvV#n8&3M~xl5 za}m;g$Wh(v|EMj!_1>K?zTJ7Y`~0Wzo6S}tQ?D6^pO4ptO`jMoAoMX>=!|A!Z-ZYV~MbE6a z9y#AF_k3@zX3s>gf7u;c%mEjAL|at8pe;9++-T-_3`9O*Y?WCxj&==Bg9Ty5Iu7Wj z(ls1ZE{9PyPScQ|w7sPTVP(T`+hw}Bs9w%>whK7;&W|zd*H(dPnuN80L=gv+7v|LU zql@3r4ob!@Wmo#Q!q^^3G-37d?qArDF)^#I-MK-=Hcs39jg^hnNnXk#cA9s*ziZZ7 zUpKaU^%A}UN02SE(aJ3|7QF2HS7x0YC9|>7Xylhym*;;AJ)$=#8bN*%Hk!qodSj)T z-;ycNuU*ky@gv{WwaucL-LS}%>^3J~E2JH2R;A6xYHsKe;`F-dY*;+@&4!Cr1@gJj z<`2GYenvk{cOe_#W}`6n1weMN9vFZw=wEi&;YZO)NK1Q%hw7u?o|W1xMxq}_qFhPz|yD+OD(*=SpPqW1vZ3)R|n zVIY1N(}*Q-ChUn{m%g&DD^^Qp=&^noMH9km2w?f1Hyh?<3p{I`A`t@TT1%{9G@BM3 zDQIBmeUI`&NWWU_5JrS%bcc3*i4Dbcn+gYmpcndSU=>-j{Ke#cBZ_krQm{F(g*{3T zktCtb2qJ_+?9^=9(m^<)056TA{%l7Ds;^9f?Q(m9xe#uc69KPoOaQ#roCugPY60NF z3k$wk{(rOEC^wrMCOeR`TZQlID^m?uMJdOw+)(Cs6HQlJ?SHoIs_4r92ga-N!|B=c z-OkIso#)UX3|W65A?4|>r=7E3kM~YHFWnzc&vwq7-_D*N>_2mV!OpwByxMzpbnpVYje55+h4_@pZW`G@>b&j6> z*Yo`ouS`^Y{VP}u1E-XWooProZJ)+wtJ!KhWt=wAU{}fV7X>2EEZyM}fC4nr*gb>e zTCGNr#0wF@*P?aW&0?Jod|Z2!ToWs_T?nk*UU4|8PUQuf?X|V_Y0Ll=TFBj zo*4pNK>C_t(07jxU+n+Xc>$N%DTmJ1FC_(Fy*$`I{Cln>T!*iA4xgX$%lYh#d8HCG zFQcTFtZ!SJDA`tXExui63N;(Z4sz^6!2l4!E{5b@6B+Ls9shMIjG}d*6@Z(zd)u)* zR`XFsxDfm!yc;|4avM*B_;7z;^eGtLc6N7nJ4ujkXI@d}Li=UDn4{E-gB>7(vL*R# zzVz|2yS#kws^KW?DEH=#t0=#9m3H?-zIWAd6wa4BcGZqXK)~|XUNAyFutPKroU!ye>TN6aFqc7kphIcU5y|eI<^XThI8AT*Jc9Oh&gs9EUwXWAS*1Z!}EAa9924!tcZ5 z;3De7fJd;>h7$RFLFkd^rYVx40RI21s$>AXP}q$$g2hAee8=zgfC^6>ecJM%rGH?9 z6>q-oc^}Tp=gsr-vbT5}g*|Vn;x#@kb3;ZgtJeku^+ce`=PeV^`QOf464oO+&Dfqp z|NQg&4~@+@gvU<@!2aAB=>^@sWAtZU4cn_x6UfBGL*&N1^X6jZ>6C8fYa-(aRiEZN zH1O{cBX;`1a9dhWjjl&Tf_FPTxP42-i0EJr2F2Hy}9!^KKZ)`cypYu%;idoS=;7R2+@UthgG+dsf&@hX0{e~6EJyDyJA zyXpzvRfppFjNTSeGkb6L_TEsDLSn}8exU>x&ZIj<5cLQb=m8)bsViR733 zYa+@Ph$>^!kqARND4HJReapX%jYnAsV_3-#C;iMZJ`ht&f6ahaIf8r0~7k-p|Byk#ijk=Cnb$DH${~#6( zf!v0&7*&8*#)xq%^HXJk($7sAwq`D;ma-;;-el&2-sPs^Ivw=0y%j2p%p{1n_?g4t zW#<9k18NU1T+2*bR0Q=a_>RA!44TvjF8KUKlt4l(+rwML;Uainwlch4C`B+-V{E30 z|3YchyUb36Trn(&zeo<*!60)9rW7P%0*=G-J^UYhPqOusf<2$mre`6oYal>w!smyC z)JgWIAcZ*+T+4(lVM-V9z=+@0CK2y4+eEz0Z4`GJI#c20PD7W|q!#H>CumV8=unF_ zs1x<41=`aB-RT6)X|dk4NNZZ8GcD4X7V1ljwWUS6(jrZ%Q%^cUOIn~KouDB#HST;x z{h2oS-ueMkI(rm5)S>Hgd59a?}S#AEA|My?<-;-}V zLFbj8cspqt3`P`In%3R(y{l1oPBa;#HrG^?#P z-c6p?y5++tV_0n%uLrknh_vg)IE7*TngE+60pfFU;-Qn{iTQGzZ&G8E=d zq@?S6$K#8B*!2#=ZZJ#&&riG&zDcf0eTS*ip+eC>o_aw@T3s00o*FG3B#UQ`HD4)UQxW9~+)Bxp| z{j--xug|=l!(TCEIdB$dzdof%$wW}yoG-G6dil|ngI--(%s?+p{$<5r>Myv zM(MJ57l*J(;K1Zo6KZES=CZfighKuhGy8g{DHKn=s`nzi1o$udQ4}wG&w%{K@~?IP zKm%jpR-0`+Ag@n%cw9SpE-_$sh(>TyTq*ldJe*|_Ivzk6`#V(!0(Yn%r#LUZ+AFjn zbZYR@6P2Kw)yzp3c)ZlJG}BTmy-X)+;6KQu3AnT9E}QHG_|$do@gZ>>U9X3Wt8b|3J%;!Zw6n9K#uS7NytFG4H!k5dV0=KQO}f_lUuc zIUaU`23aFN?Oq27PU3ewz^ZulBT&1wD8Bk0H{1;Z<-DU3tMUjUSA&DCW&)jGIhFxn2?u!oH6-plS_j$@l`5{+Bqf$++7M zfK6D&ALPrM@EjX3aJ|wVoYiIQGQdF+E8*?k07yrOa_&OfDyjLgDSIAxqds8BP^=Mc z9z>adD!QEA!A#*UMwu8JFB&eSymU0(s~KgN+-BvHJU~d+@3(tDTi{a zRc^3!83MhFnITxF+gyN7w7ljj?vvf!4(zdlZSMu9bf;0n4lB}`Oy;S|C8^=Ot;xU+vBhj4M@eGm6sL?(OW^i94D z0h@wh@nLTn>qrtDPvu3>kM8Iu3YqdilMOQOg1Wr`?nkLskaypyy~TQJ`c_Cl(w`l(^D@VK-2uy{7~`!_BY-+=kpR?8Bv93i(}{CxjpyABmT!7J|rPRjQC#qq#TZoJ0&I(BDpgPX&v_F&(0 zg?jhu4gFWHnC-mB((D#BMC62MNxkXGH&4A!-p7yBmMRLY%JZXFTpBu{o0*@lijVj$ z+b|324aplEYZ$={FeAaG0)TT zyf`Dv@R}}~<>iXTp-8dZKZX8ys)eVeIl61Hzum5fnLxT5n_hQwldr8g4^P|Td{-Dr zXM5DGc&6*#_kY6y5)PdstZViT2G%XBYXJ*fhWHmTG5(df_`Ylns_boh_Xbo8v%OckdXlNG>x+_hb*X$+ z^>2%smnCI=n0~x*w}4JWVG>@%;nk2Bfgy?oh;6}>b^*jDQSeCE62*BB>~sRFh^e=* zM0x&$HASDcr7($-;+!amtr+FGiVfOO)Y-s12g=~YCg#zab1 z7Vn5I_D9IZ;jLEzk_DIx506$9V|^lF1+$fop&+nQ-cog`It)?(8T2ogmW|&&@TW`5 zSkWlcjV>>jh?~(bmw+mNfx-dNBcfbT$TLj)4_H3|`k;Hwhh*>Ih1tlGcSqe%fQ#s)S(atU}PTl;PM851N~u`3^*7I zwJ0J96*LI1Y2s;ji0Q|8TgW@3h$ifg`#wq z&x?A-_Q&0S&KQ}~QcWmFSB26x$ZlQT$n{1C01=9tNkEX$moc3XjTQ{7v@;-BBT+paZZ``W}zCskXwj$ z4~h9;ZLfixmL~vV@F7qK1O><}<`q}N0<&rwEOYazX#+o7XaJj&1dg2_yB#R_3m__Q=Ja*g7Y@BvIiK@+#s-v=H@Cfn-0OXBjET)sbRHLCs=eK#7cT&rX}nUwnec0Ph!!;ps?-#)6HX`0 z-{=sta31l`{+k~}xhUD@5;*LB5@cTko`Y9NA-$zm~ zX;+Zje%AFwlf}cwshbm%f+lWgl3-7)`pP22>;?Ey2@~sYtDSeXrTTfTzVJRX`==pp zq}}7!q{^?p+BtmvVrTd4^~v5z_3wKphkFOrqvO4koio(V^If~eSAvk31D}V2C|C+> zx;Wq(AZbj)1Fxx)yO}I}BovT&g{cyp!3VMapQ`g8qU6*32Ql(bfUZq3%F-6#kfFZX zU8o$fypXiQ%!u-}I?aqVk4~gjji3VT;p}8*`w`sSM7kd?xEdsuodM)&)DL^J!c4I6 zRG=`eqfvM3RTyXBj^LEUqpkus2;&)gn1@r?zgYnK{n53*b#(foDL^t;W>uj>v$Rrc z;CaZ9%lbY}!ap#;%Pp+Ce|O_8d|(mteEX9+4@;{x6IneP)XJya(c0;Df$$|lDDrlZ zg!+BiAQDDNOi5Gm8oLO9i%~g*fwaW>F!FknsI9YjytX1FQi=4m2HK9!E=rnFNuu?e zd_ED20col-nv>jr$ldAr50dC3XH&GMXKe}`QNp4R{34FVSJxz$LSm^&Xz&g@*nbeB zF{XNfUG) z%5G1i((>NVE8b$O*;retl=T*od{&tnD=X3ki`P~kQ{iBDM>Mcj$A33wY=##bY$sI}JQaoH`caZ9Z!<66tKQ`^{mChF}@ zthbS^w{sxsJ$qce-8Z7%^GDU&+!594@N0AO7&ooDG%xMRb7{}YdTmqGnb^*{Xh$I` z?|4`nYO)7)w5&kuX(J0N_j9hCxQVj`&x#9Ph5_)UByh3oyvf!XQleNXB0}26N zr?IzyE*^U?etNn8Uw=P%b$E3Ae@;%%UjO{dn_vHX!CUYzy1n4?>N@=Grau@)qu=8s z9pB#FKm0)ihH<^^;9{J^wfRd3OzmCLIXsgB2_RCDGzCP9w3yHUn{%zsC2P_f? zL-3izl-Y`pk52dB02O+{*!~A1?pTBYaJrm5M&h%e(X>4x{lTeXn!py~t3Gpurv zDb$?+6(w5|GB$T~x|IPbr;rQVKu%9uKQx+KFZZjj-_&0nA7foOrKcww4H&caT7tYD zjr?YagRo*x5w_oC+Q+yoWkp`?u(KqFG`aQ|ShrUmxp_ltEF zN3%%V7QLeU-cM5{l@`Q1cfKnB;)!UNB+KqBLR>j=?&c(5S7=mQJ(&1=#T#V7-^Q8q z_Wb1Zhc#RP==D7v)iu3WQFu}fyZ!3$eyyMyA9XzBt);DXoNM(dOu|IImmI-+<=i8% z{^-3T0I9i(muq@m>)+>CAHjV{#>17DTc_h8>_gxPwle*`_WQ_M`LGvT)4A?{)ZQ%# z#?lxjHnC(jf!B)P8%6zKskmjR^~EiR8*9Mr*)7An`(Ws57iC|F(ZA++*W?+ocq47> zwaohZka-cdH}mfN2P!44#()E(%MBr7OqiE`+|%Y|!M)$bsGWBxEax)H*s~wr1Z?UF z_32i{H~j~pCMP*QzVS|Z%zVodkd<1|a}NB%GX*atubjQy)Xl37ZiW?NhFB)ng#HEZqae;q71#y%cK$<%>Y z>mApq+xDpS9j+ixzB-@?VkJNWByLcG9<3jTh%vmz&G& z%BKYztCr>%_2w=xM7QO8(y`kOw)N7-o5GthfE23%{eb~YzEu$=3{s_u&{dveBq?RGHuLTF9`u8~T zaDh}r=S-u~7)j%VW8#-_SkMOa#Ve!19sL$SgaL9N2`5@_d1}f7*i~h35xa)gck~mR zdcjtNvVNxF^4Za8+3N)`%79Fs`I{O&ATpjNJq_3$fcp$6b-4gQQx8#5=NU;=pr-(v zq%~{+MUx|7pg|A?6N8ciHWCx_`8EJ*7U2pK$9#=ra=bp1JIkUiX_r&6D%P7q31YdW ze8WrA8=ae}HP19)lXUT=--jJ*H>+P74eOU*VXSE4oM}|PGMkj|CbURJW*_gh--CO@ zYFNH98!R`=jeByt3EII{qwL$wsy7?>!7wOKI>Z zG1wxBo70G7*-Lfc!O*k;Q>iWDlOJDompOjN59qug7Hm@-yizco5!Vnf3?$!yNNp z6J!9-hh^^8+vdB9V15=G6`&fNeNo_lK3SOx9vHyS1P}DvO1px#5#p2iWm>y%Xl7_u z{1upDvD(D1pGvS_N^=>FyfnSjHhh2k8`h*>(2DZa$kByLl>uAweDSRaBZMkf)LFb2 za9F*`VIaA42s-nOW4Z0f}%|^p}hv&GsL=#Gs=ClDTgZpr{bMn*PS?AgQ;m*mg z=)J#p@?vLq@6$cjgIT~42K~!>27j(pwA1R|V{2H@6phie_O7Z3G=E}cb~B9Xig!{zfVt%kj; z@HQZ|*oJovj5}%WQR5!!0ebd-PqfR+mbg_Gq?9Omzfcw+7qCwYEF)anSi>P~WhH^4 zPZ^1#zqVqOrXyXwH!>3@q@{zit3=fM&tAct{%oKaQRuxAQOhD(6RDc>FcoNCM1SW$ z2xvKL73_A4)KD0-9IfsyqNLqg^{j-qf>_KNf@_I;k^P?{P~8;j+?+v>J|uPC)ZNP~ z%!dG9k(yjY`On-3{0D8+zv*=7y6TL&ixv7rBU&ViW^QgYPLsv5snvnuw_(?$d7Hs~mWRAk2b-wA5jS!61 zgy*Lz0N8^~^g%a?8fco51@HLim%WpP!trArGHl}^T4#vfiw(g8{Xl|WOJHpA!km2b%9`J zYf(nOevh47iZFK;kH_TmyrtTq=22$A6ZY)r)HP!luwSZhtTJ=<{P<11^+Thv^{jSO zJFVqpB~;CENpAwo`rG!(JGkbcZ5ZlSvzD!VJ<4CX*CV*N)gqA;!2zpP04uj*vhLdY z23CK0TzxG^|MK|t8{WP%X=Q3}8_%R}#_edL<@nTUyZM7>?TVMje9l7azD*=ZC4*vJ8B zx&Snb0JK|`qO)iKXchLr8n!W?lZK7|VY^nxTeZfpEO);9KTLU&t#ijVUbsgV7V@9V zjB=iMba=dGqt+@OiK!uXeUoPYv}0k!qA^yOl{5RbkYb{}C#WX74JQSa>5YuJ)*%dV zdi45acQ0GS6an_b3naCQN^sbGBF5|@TGUs`eEE@?+;N0RLn5nGRlIr@0E|jk2o@CsYxMe6v+1)cEB7 zK%#1rd4E$hD=7AMOw5ceJ2#`V{}Z>xC&#ALf?fN)WMlAoad-FV`0R9hIzy9<79eq> z!P$`DhfKO zk6o7&U_`}m<2(`)D^bcZmc$z*!EH~7N4cVn{!>psA((B$@>>&BgS1f@v566 z)Q7eo?2S$V%;IF(y9m1eSX?Iir$9b*UhS@J{GGC|4ufc%^dF=!T?n7kc+7E>?3)kH zgMcC4DH(h>iZOVFsLsjSpyg}!MdS>bA{;~p0$szxFX@AneOp&F3y1`@Ir%EKY+mnz zmVtxa5OVkNBO$aheP~VXgX^}KSVc(T=?`6S#w4nxG-pu&X7(}%Sb-76qzytrNv&_3 zU8Cp}rjhb*ZYIrNL6;mH^15cN4W4`BhqvpS@5~Q5(`W|=FRGdV?P?8YwWZA;epuRi zb-Y&(rTM^88$g-w9B>AsAS>s&9^r7LHz1m?jKoOPJI6Sp}>QQ@TdY7<_9%XxF>M+|IGXUMNfNo3$IzvaTeopV^$Aqusom6YeWXj*K2R;3z^-6(BJM<|N9-guS{@(nbg{O zY0hjAq1G@j69Yc4p#8*xR{BDzhkCL5RlV5xs%`<9VQgoo_OQ~;##fuSv-X}1T>5UB zEevkHsEyN~n|2$?ZS!jkfE=-Qk521@k!Ah`kcYQc|3{zO#EW+0ZKL@vEi1 z4>3MKFJ8R_a)f#tBFB{R%HmP}n z;@Ro*dK>-{_it7Y+ddXw2(nI)Eur;2v^GOTltqk)0;{THC=GgR z+T$XVQRWNaE-9FW^YfX|^Zp(oP!YfW^vnL?l#SATxVj5-exVLYOvyt!+}!N}>lny>z)&ZJ9QKOMeSp4KuQ1TVN~ z^u2QuHR$EH)jD9&c?_?w`gJuNPwUchT~u=PsII-gBifuY|#H>=#r>h1}vL) zXWHEnQ7%>Bs^x#Y{YU*B

aj4)IJt)4auewhQkcahFhj=RAe-Dn#$?>DNJaLu25) ztpkjAHbwla1@1d1uR41>&-P~wlZUMc`>5*gR&`6oGI4r!X6u>dFRDu5UxaxB4YVk9IwtfVC%Qt4R(;IrI|H+YD9R|e*oY*Dm#)b zZ)@uc9!5g=zwo{+oVM?Q>xE*U%9wND9;NL{rcUqkD{sozjpfho>94v0)>bk<|LL1R zH1RLk1~j(+B^x1%T?iH5PQxG=RxwvG8&$Emt_!1z+O9OGuDFS2eGZc%XR-bdRF+cs zraEk0AlO8>JrQB=JFkwW&2=b+;&~ZNW$)+JigFc_A;qNRQt&5GX01|GW=#}2-rd1c zjzScN&M37$wbb6vYlWRM%B&Z4YHeK?+E}U-6xuM2-GE2Yb#4`;_R_xO>+GeXd@C7+5^NlUxNm`^=FwUbXzX~Ao$-L zjH2|=nc8VEO#H7j*Th2ECkt&)p1pXEv7m2&Ma1d}hbclnR#-kbqUC#Gf{{EB#AO&` zsFNTNA7&;{YxMZQ2c{py0g8*vz@d3 zpZB)QF7{ayA1d+>#c8Md{8b72CIi5T?qyq8h@szAM`i$l69Rc64FTmVA_e%pAfk&3C?eZI;iF^pK}V!7KgrPf$3N|7-kiQZJU%(< z>=wMQ`-9ssAACVgO)m^m>@rRURgo{gDtmyCXWieQ9{= zusgX9<7=MNpzGrKuZR0@>ZA02Yen7}@WWfFHTVQc$6aYph&e6@hpUPLM^lyy*b{!- z4|SqsPOpPF8Rly|;?$WUvC0s*0U^Ss>@Sqj;2~jGH7F;)*G!k-B=~&{cZw^h0gcCq z5fKq?;`|stC4H^me^85c1;+TD*Fu`IdQU?30Yvg zI-X~ZjC9yOjBb(kv>djPCdm408+jB>w{6El!m(t}Q==cBY+vr8<6_syO6SF7tZtE` zrB+enDfk7^(0c8D8B-7q5o;07!yl(XjG+M6YAV*O5ftT(qHvnQL8fIk`;hHEbxZKHS&7Ln>>5Qsr2E?-j zTfZgkIaLNd+zgyWHmP?nYB*JD*^S+%118m$eiqiVbrL_hAiSTn`oO~LtRNzwfW1y8 zy1V&~2@>ux!fBkfPEYr#@jJgYoG!cb>rl6>$l%~!ACPElii@wCu6F+XGR-l*t(|JJB{~M z($?-O6f&TnA6*jTk+oc?`hCG+O_ zY0G}`@~6y;_0>kxXb47sbV^sm!h$go7-1Td2Zuexb}%2JP|djD-u}aTx8(7^B03=b zqay^O&P79lOT~)4mSK14+*y|k8%5~Fz?-Ey?8btPXwQG(UVSnc&q*zCv_MZa4iX=kC|@#Hqz1$NW9z{L(8 z`s@_J?^|7To9oWf9gYa&1SW#TJO&yCS3KU$PG9D=$r)un+00Q+Gde>TPG7x!w)gH- zNf~k>a(jUji)W(jz5*l%ht40S2&n1^3paGG4puzfe^ixhg;3fJX0~`Sg_=txJ<5iz zFQAjm9vSo$Wi?eF^HsNd}1rY!o6BPE|?*dI69|O}MrA5HOGZaliIc4E_Gm0W-g81pM24;-W`_&dxy&A|lJBt)2SoHwA&a z{qdAo(!<~`S=u_>`{lH%6O9;0G8#Tqu}qX?($1XVErh6XN$wYEPJ6PV{a$`Ol`cpp zOJX0{fSaa+Nd@jOE$`H}6F^MKE^nH95Jd5tPo&`FhC_byGnZRx1 z$s-Bu!0!<|@+?^Pj*oXKyJIbbnJ)tPUv|}=1;BqyYy-Zdx&{Aq`_XVh1H8paxcH`SG`)7Qs)CsljPCHE`5LgP^oPup_Z72n6+l^g z6qNM>DC>`cvQYqK<8e?WD2Z!W>|3H zMZ?oH8fA_dT^ocCf3FUsA*xogc16!lTX>I=(~L#IUL^RTnuNgss4#~>;rVHO$?1dZ zK290Aa&_8>j{E*_QxO+sDUvITd_d^RlVI+jVM;PJ4Bax{9gQh%gK)s9d9;g2o5ivb zvi9Hw77{=Kr2Al+!Q68-OgqM8o=^#z8Tn*mw3pk)UUtausT=xQ&!l5jkS4`3mY4qs zrzJaAu!BykO)G)qs5feAUJe#MX*P1z_73;nOsEtLgUoLE`zf?St+g5gG5q}?_X;yN zteEd?_-MI>9cpDd^ycpe)usc~YB8w$o4ym&QgIb?O7hkA&rXZ0glU$1*xM(P9sa(4 zlg(X20~I3;rv`ogwAGR)V9l9fCLS-Fb+N_rtsj4!lLyYo>qQ@%)g zWz#FO%p7332DD{B6dsipx#KQmp5)##AL)IsN2VZn_-bg&!2uHOoHWE)axNMx1r1w9 z*-_q61vB8VqZ$Zh1k~*5UlYt~Bc~A=+N0AILyl5jDa*7&XrNchhF#2bf zemt;q4Z$l+;G2Dk2~sL%pR=ic^J90kM?s(o^f$)4u?^V>`#clS!{E&sZ-#G-4r6@0 z{js&tDwr1oQZ7Q%~U_NC2StK+iNeM_Q%Gc z2o7VD$w*P(c`Fs+Ju8O(SCkFhr}Pi(*wJ4(y-~K$%d%G#4U;y46Aa3;W(PBQmS4R- zINN`<^Tsp@^cIKBwahtu4P}0|){`ZSKxaiUi(`w9i2-Hz)$3vysMvJFD5_Dsl_sAK zxI>A_Wb_XLMA!=f8EqmpkTd?_B6>odnYhcE-Iro@H z>3u8PPY&!i8G6%#j_Ci*n>R@J|J;;jl0Q&*#lmKr#myGh$yRaCC6F%_yyZ;X#0mHC zwdcMW*hW~Dr@S^#cnUD&KMZuGEs(wHo}`mFjbLuMWqi>mo&~45x!Gu}O@7T4nm&R3nV=lwqEf9zWiCG7SQMUlHGI_daJWQu87I4Wf6 zF%gL;Mu?meAQFbTGm85CC{c#JB3Y8)j_Fk}yba@M2;6;IE0tK2EkxHo)izY9^B?w4 zk5PVv?}2p}>G?icZE}b@ZDvg7uA?~U`Dq~OSAR&Hx{mq>^HVBWu@pI=UEK%__^w2p zweq}pZwC#;WCA#__cEe>w^`UcU;{TH@dO!=Zm&yBdybQGA6j?}Cf^52I}v z5E{0vzkShbwU+(QZFJXv|uLe39Unsz(eIAS)8%|R^21aKd zZZMpoehl2ogE0-u-iYiEO9`MDs(XpY@eb!2zWW@tdx!?x>@g<6qFvgJH^7{Tz}%Ez zfna^miV6UK$6c$A*dF~yF{&Z0)u^C3P57Y+H|yo*DA?y{r?Pb>i9TBxaptwmP?Fo!cpOO1Yeg zR6F-JBUrHwRq;QnWxmbSC@EgV{txTPPwqxS+;f3l!}^r1Ci{-sZLfM`R?B>HHAtUw zT~wcn8k0Gx9F2)juA2GVL)FZE%1)>q;%Pf4rYTuc5~F~U>X~8{&nO@SEhS5;VtiND z)kG%{CU4@EdJw^FQ!CHPQ7k-u&|RR7v&4e*~{rVyYXC_z>C;IZ_V|A7BSFa6}Y z+Nf>T)^H2;0BHiXeLbqb@^1p1yc&DlCSTA7@L-L#wH5lip7{&^HCv6;fh^#5a3y&Q5kZ@;x@ueSFuE$&e%WO7n~Gu^(Ra!nh*J^!+Wbrk-6R72aP! zWg7)O6I7{GGoZ~cCf7jj^*Z7_b?6h0==kN%>C4XP%bkR9=)_t4B`*Mu2=PMqp(+%q*oP~l*=Hlj_?yS zKJFtufe!B0I8{3e`ix_Rq3t{e{=M{Zu>TFMTIgUw@#Scu;hhY?lSsHwyf?23w^z z4AOcp?a3{Jp+h-PHkIE>{p4msE&5z-+I8-eP}R7*yQ|%`iKlDfjW3vVmVE z96am>qGl3qCG-Kw!<4!`wb9bl61DrJSDInSvy?$tWy+cN9WpQ9)9L%JPS5xf^=reR z|NSWF_9cw(>hdksOU8qNA3w;d@+W=k1`K~UW zsYBd8br{(9?^}&#yV_W(w%X8Fe1TuY#uJcY_AvY&@l@-(y8J1c8HMr#K2j4#_3vPh zuq#^z*hP@~E?E3tfikMoaHqF->&dblv#<$77#e1AtlaN?*RY%lbp?gAHB*n4xl zce4Kq!zmmr)Tb2Qg?o7a?9^Q@iB&lvvKXvPEy)y5FB#1W^RC^R5hxID(@S2DnA)ga z8)fzMp*%M!YqNP141UvaI=yb%LGeyRyBh$f8sgN7;Q)^OV=Jb?efros{ZNIrg7*XM>2;s}`XVAu_VM4kTM z$05+B3JgFsdNc@!->(3oZhTkAN7a^5>N~{nGWbKBsoShUZNHhVov(qINB0D=wAodB zC8UcMj7Rr zgAu%=GBVBu%QRKgtRKo=oqL{XxAdL7@xK3)u>a4c|7+dbB)l3%aqv}0 zBKp6zvcA%60O1exf3w;6lm7o#{I^u=N2Mi{ant|hx4YUvR$%wQ!AYF!_w^pY@ZfRHSA#c$ zFhO-)X>cQo0X|GhEE`EmN!K5C24X%sP{Y5wfywP9cku71e+B;nB8Gp5-HVclnj!x} zaiFGy((~YAe5GEVof?nNFU${C1uRHMd8w9O{ZaY~=Rd#l|1AEWj*F82HrG-9yW09w z{`)^e{{NMxrg;6EYwJx@{=W+A-(Fo?{d4{Q75@R{hRo6StTJ>)+mEY~Mx)N7+rdho z(bnEiCws?OUg|_S55`{Ubnm(OIthBE-J`=7`#+(%C(6-x4za+3OpOgU#ez}d==f~^ z=Vk!|K-2;4xe}S-kf#NGzeb(0d#&x(e9;_ zz1A+gCFN%0X=&$|zr(L9yg3}ga`;sJrN7Kl_+=Um-LG}Hs=Vq!_C=p5_-a2%d);rp z{U<h~XD0(e zjc4}lTbGmsJPUe6)HlNi;XdERJ=5)$Shs_Vc;!`(S|w8hMEw@ZpVIE}G1b7c0MDx0 z^Ork6;{m{p-g#Ntee(vlAFQlYu^F%}WgJ77dbpBW-_G;>6WL=J|JsT*FkGX(H+#FU z&vu?2?3pK$POqs)f&~}9_n+a9{lndZ*UxFQRQIzJ;&@dj2MNdfv(uATuJ`|q_Ct>M za8?Umlf04-#=dbO{DooZgzW?+wrLOcI;bRunGDngr#AAUMGdbV@WIePYA z3c~5m@jkzpt~^%LVylTw6>l00MnyVa;}Kgv!TD6bCU#9jgOiQFNqqIP^X&EE^Mk$5P{KRrG}H1H zT%p^wDA$3^d$px!o?5hF=6RboD?q@=yEJ!9<`*-!Y^9{xXMYr8g(HB3=;CbW#ip;Zru=JDa!67p0%=1Q5jf`#5H8ufHej*iYM^NVzq0;Yh%(jWO7G>5eJ z#)QEl3eJ;p6_I}g<29mpbcjZv4HOc4^#4yW7b698RDnLfyv^GDd}y>gho||lLrePQ zfWN|waHlTfz`qecE<=9kMZDh)R3IUcuZYj4pX z&TYn|s;4OLWJ_$biID1u!s7v&z>6-`QCyZoFUCkKy5!V;mNHc6mbrP$y0*CED`nSS z6kfQw!tafpx&3~^^-c&MCLOlMd$F4MD%md2&(lMG92SKN2zNd#XO`cwXaX3o>0EAw zcn(;5x~0uxr?p*{03S6WdXDoviZ#u1b1-Kz{xh7Nk4UNQJ+Gj9b2)i}WS|p9{mGN7 zvYbwGjL^{Na9gLw3=&+nmuh|@0SB z&e6aUXIovWT|c6YIR!Y|&(8;)vv~)WE>H`b!-mBDob8>Sbx!xr&h`(Px$1cf=#1K- z+__=Ay}+-?gB|*cfz{w}Y&ZD*AQ(jPL#H1O!gRaZTrglVYoRtE0{7ly(`v8Z+f*mz zVJP1_aZ09SS)ZJmN0T}MozPLK4l(?H89S{|F6{eWAC-{h+*R?^)lo?gPw%KI`9&So z;SR$L*?yxdhWej+FoEsw=K`d{A(8V^oPWd znrp8R!exAM@A_;k)BfRp=f(a3I_hPM(RS{I3C4Wx1aTb2$##;$1rRSF0ky!9My^Ml za2R&b2P)`w@M>7BJY9fu=NZo9)Re~P^RiV7Yr)-%!a->F8hux|KNA+JVnOo0&tZ>r zFsh>I5A=_FpwSrheTEtm`(rbwyE})6&=2IJK4ZG(=Y0|*j{2}W7R$@z)}F@UU{TH? zs;7ox5|hPB1^qMmQuE(7-pw?rW*@D|bq!z!awA(!UYDP}R#pdrQiE}O-#=m@2$R|~ zznxzStK{j)E_7$x8ZVXD-39sy`NXmuRBlO!Xudw7b7JJyosqrm;n-Kntf@wFu&E$T zgxtXkrwGYejb|?x>;--~6}$kD$kQfS9S|R%`b(t}nqu)p zdh|y&B{hDYsgw7##@(~D>|R#y@8vbdo{(I6D9=NgX-DevJ@%NorUkD1BW!9C8!EgH zXm1T}YV0Gau>{|y3$-OfKD&@PCQ7ZN33!T8@_oI&@X=hQQtkNV(c!Oj8S)G%@u!+P z+N!16;nCike;ZL%%q* z2>FU|R%84*<}Al)q{3jdYmKIi^MTzJek99Azdmx*5U9_ZtR9DM#T1R6^yd;WZm1#Q zn6gaqF`$fR!SZkYu+Je;u3>7fuBqZ(6!&}8yRa8j?}7_YBxly~HpX#(D?48wJ;RYJ z<0?~ccN)!FdY{g?Cq7~ZM~vOk3wtuUV}QvjeV|T94~`k)=pS)l1b9)fqKgz2&0#uW zj54~2N6|%mY*YZT`z4zDQ4CPzv%oW` ze$u`6z0>aXcmN!i_gz9SeoVxRTKE3@f7QMRX!HBMEl=Gpa2{8h8=H76*Q$*s{LgE) zwpN>4?Un!bl3_RsVsD=6y~d2$Tl7d=q+wfTS&WHyX!Y_I{;2{tbo!3=J@Q@&Ow2h) z-SRwaAGJHGGv9lrGe)UY`cRtF?QG9C`KN4ad%jhgli%8ak%)3J^tQd# zr(WoNx9uIifQN6tr8sXWSy`lPr;GF9vRD2`_3h68WA95F+BmYcKTE%&rqPTfEQ!TS z51=!rM_yUfdi->5X26`;16}4m_w)5NHvs6`A^&+(ZJDGXonINgV_T|*6vplE% zf2WQFYb$Ey8hpbN;XmQP|4Kea)h!mf{>8dqho%%{MX@?arXhQK;@2Vh={n{u76t)J zfY$f7>lA;O3ZRCr$U;<-SaTV{rs60arz4CiPOB)S<(8utjz5@q)VcyIhu6)t7=3th zUXiopEIBX&D6XQERh?&boj+xAr`4!*KEb`CTEYx)>4@??&qxy*iB=Jdjzz~6qJ@*t z>r#We9vXJg?-TEon++p=qlZ1#cog`qFT3O7~C()9t#WX_Dq0(bxp>WU5HCaojaX61zK{y^&N{?%+ zwH2!0VLciRLFw@+K3Y*tqAb{FvrdT_SmCjyQIf+foHa)#qJdf|n&}ME>#J3nS+@mOCO!I$6N6Eu=|8hoE0l+-5Ke30;4b+r{_;S&AO9}}IF0_3 zFU0?^EI(U*_VjU_|6h6hm;Luw;{T&57InlbltMBkxi!sb?sO}wD{!4Fw;nT$H$vNB!pgMUC!6h-oXW2N~q1W-DW!_E48!Cjt>CLV&Kri38 z^q7qGV7t*^yXZE2Idc2hE}$MGcXUfP(&7T&N&ViK!7j~ds8QK{_g3TmMuqD^E@D8u zz85ut+D-$nfHDa_Rne*u@~1Q3wzhsQh3H@h2$;`N)u*9S*ia7#S$JUI|kmKb)w zA7J=i5ALc-rSU754Xg)&?sIz*j}5qu7JVlR>>NHPPhg*!SB zrkbn)^5d?8VN_tIP&tB=nsNb!8Y-{R;nL->*SH$@d$`P@1iq^C#zAC1Tt;&BW)c=6 zBRFYKS0Ir)K)r@I8bfku+qQoJz1i*s7<~E#9B!ClZ$m7vuB%Q#`H0K~P%3 zkNQeY!55rx4g>?JAkSR`c3M8ZaK~;BN{ThKw1SKG3QiG>Djf=iXP~l1|DHXro>otz zs!FTyvq~dK=hLgL=8ug2yt#8Ya|C@}un3#g?E@U#)_S3bWB{?;X8t!`|PIhNT;LDgqNwkZTVp z2W^;Z415_5-45M2saUuwt5_y-804a=oJc>j(~N}#HE(WhzuBjG#T?jPcqmul$!g>2 zx2IJ&<;7c~TG&+O41qZ}-s~P@A&~gZ&f!)C^Ge^JjW_SmtU{%tQZVU@Euc$~vb2m0 z1XR1b0lY-!TOf?D-(=_B+~sD|dzc8hXi}$w(iE{XirJ(=MvsdQUZ`Piy_+G%0_)-c z!YR@j1tC%hxscbehM@}_#AtwFSZ(450DszE$!1sCEXB}%tcWqq^e+pwhp#G z!N=w<+vM~2-HreIxqWch-amMY4=DJ9G?c5#^03X)^IbQ2h$e!)F(1?+u-i5G6;3YQ z5q-x)bF9wn{u3$!I7p-f*Phy2Ks|(70?=vd@R~KByT@_`MY~nn{X;@s`Lhtsti z>L{Xwh_%L>Q`4lBs%2qDn!U6%`X~U3v2nD8J_e|oPbGqM7`VO81o>Ri>5$AgRsctissO(@_pHFAe=0}JWsMG6tt*-^6*KMA7Bk*rc6yiOavB*@Nmg>6fV5^cW} zy<-G=X|e$a#mPylwRCzKJ?XG5jq!>fR248i8J2X61p2{nGQvAY^hQ3=SzGl*{T;rs z(3pbO;Q4~$v7#|X>u05{=BopY)5pzs&>RMxqn+^Yjm4$E{~frxzyDIg>psvz-wo@3 z|GRTmH0B7+A>SPD?CJyMD1DlErWn^gcn=)@n8Ojm;T=krQO51!sd2+_(x=zA%&DGJ z1Zi(f?AIXl&tZ?a7kIZhi_@88n@+3c`240Mf@xk8Kzv@WJDs7ZUpSwO_!?vQa1{Kh?)F$`*icv~BT5^D&(mnXM%5^wAu?C&%;cH6HGj*gR5*GfXiWHJp? z-7UC9Y(YJn?f-pqfJA!Z@F*)SY(`uXu=blj9_?-%y)r2E=2mmJa)O&QS`he)2=1{h z7UFElT%11RWjhFs_sKLwPE+b-a-Ll=z0a(fOHEWA8*3VxW;5;dBXhfU+W4z?`+L*N zMQ1Kf!P*qGv&Ls6gvT%IPH!OUp%ZI5<%7=^{PXt8BPqc(#~&bB1~KJ8s|8v(h3Snz zVz;;1-rIQB-rd@dj}TfL-O#kTop$tt#{Pgc)3kfT$pyN*R|W`<-h<8Q1Wq+=xV;rBR^jm;=W6_dtNq;2(VW|CQr?X3+A>y?!fhT?E*_h4glT1k5wFL!|N--5gU zW_CFTyPF(I?5C~lMAF0a=;yr`2fIhcc9Tqy;z*c70z!hq4Fn(chAzE-~blf3aWU%T+QM&~Vgwra0 z{J*1Dirsqz6@GSv4DO1dusmdK#r^^Hju{>dwE_o+S<2lCDMr(9@Zx{)l9(9R_n-2dVqe^^0Ux>j!LPHIA;He8^NKM0z2a_-w0E0wBX-J@<zN>D4jEP)CZtTr# zwBZI`31~>=1P^=~S(J0Mm3Sn2B2OLjxg^^XMd(Pgi1K@?nZVehR~SZ>it(Kpd?7HR3*rS_@xq=P zUg6~eCeMuoW?T!NJWz2DZ-$8FOmq^acLD01z%HqiD_R$0BBBzxQG~{_ds>^Cyj~8M zT9uO%=d9Ffou0O;ORZLGW$Cg^8xdu8K!n}%-~+5nl(Iu_P?|<1=&dNolG=kCGE~6z zrq_{DMPlp%SSdYM-n&&GEq5T#KuCRsLOfkH5@y|7v(~ciHM9v!)c$-%tD=9UCG~md zhCx-(AZmiDlApx~queT&@sF&UerDH7X6rD$9lr}_6&wNRgLsbQ8TyU^cF27mHI3vy zUmOH&OkwnL5&O1?RWJpL$$*lJ9iHryMcozI5>iC^E-CRk2$tIw=K-9?q%Am$fVr6G zIkOy6%1{&>K3vkZmVU3@0wuLn*&_BROU14?0UHr{V2oqav|%E@pwrW>}VorPCqP( zY2?oMCl(ek?MA0F=}SQmt_zaM0MAAGA3c4XHg~zW`UAaASmR5D5}742t#wF9)g)Hw zcDp|A78lj%WA`$w(d0+1)~4tM)b%hMj~m{>QZUL3Nt86_P; z=Jr9or6mbHINaOd7H{nzb6?=g?3UwYsoND82m`k=Ud{1x*mp-jH>6sdg3=)o@i2Zm zT9xvt=Zf*j_0dHSN58=|Ra$R2qQm%>x0AyG)_yT6@dR5 zFqEt*o<`s${omesx3{$>w$SQofV3ExTSDQSemu~LASaYXRy_Bt22h3Im)$q;ak9B} z)I8iF)f27RqdHt0UT$svaQ6k9RBz}O;M`GoQDl(OvP>K8Fq4pat3lf-)p?n}LXZ$# z3@OEA#>gwy%nCgvn;f7{%QZoI{#E9ENX(x>@Il^1;#__=+CYPO9X*3#lYO~qawCd=jQ7Z}F8I8Xm@v#QnZh$-nP{adczCinn#rTnB5XR4jJwzf3cXT-+=l?YUsrd|GWkrtk z@ZXBc!<$pCY&CF+Rc$PS)0&7=23geOd5fa;lu_7>a%d(`PVrI|TZDWy|3b?!eIeRa zrY=QIqE@VBsC)H=TbYO>MWz+vctIb=n=PRBjz)??=cVEud@Fs=RQQmeEF! zI$E(z@0bmOlkBuwt;Np_TAlbIHx!RlC5`aFi0JI$u;-7l8dk9Z{~lE?3G7i7%>sdI z!;wrQ2kD(t4O3eT*n@M*XKttVDLEe{$TA{_enqluR!3`Ujyd2-sAy7CEbudX{Pozw zd$VMes*WqLO5vZT4QYcMZz4SZci;~oYb|?e(~YlCD5Rfu)Qy^mwZfoJ<{jyHCErMf zA#^=LPF4!aLb9xk#DlQ$HAI(1QGv){NEe%LBI1&NQU4bIVqC(!HU5a z^Ztcuc$?WI!Q9c3mSEN?Rcuvcan;kRWhbqK5lF35mIW&O2sBb(|8bytzVwA~FA-Q^ zh#KI?|3qrR?0%c|C_zbF)Nw5Dq}ug`iIJ^yOH_#122>*-f*NB0NmjV-sH4bmMbF{p;CKLaSL-IumM(pw=KKP^spbP0b>b7Bdd$54` ziW(sAtFx2XZ|7;}Y1CPZy=$YW;RHov!(f;) z%=YcVTmzDtOjj$zo7bbDJL!1F>NQSV+R=kxP?tM8>qJ5I*2I@)TnNTGKsMLVw5!M# z+$z`+wBZ!JFjW^)^d!Xb^eRP#oU4?c->!hHL_5+8ZbY^<*h!*1F{(x*)X1QE#vo>r zd3&KxyWS6itgC7AFo=`6*~b92vVyc}8V$@M8LEIePBZI*k+%cVHb2%4s2wV|X?ad& zGetfG#l&Pw!J!1;Nl{xm9^+8|TxRStCExNLk9I8sms1>E5ZnrRZGnWK=#r zjdb?RROzsB?N2+KTkW0gt=%Iwb(JnjaIm2(!p?;yF_*>wNSUaSsEQ}U^I^~Ju$)}Y z^zN}N0x=6cw~M5#JAtcphxO6uDhwkSeDFrXy(Cw)L4uX$5@^t`%{z?^u8C-tXfjLPk7c1)YjVWqQN*rm(XuzjWV&ka2 z^={|5vQowUq+hL`Euc)i95021sm9{E_oiOuF5G;`o zB-$K|y9^=VUx?-=n$OYV@Wzc|WimiZReoBHhq53P7$ZS3X~|WJJt?Q!VwF-%r7{ep zN@T9qzK(rKx6My+D|GrAz-H^<=z ztrBFT?@sGX`8AQ>5&b*E=aB65RQkcnJ~~h}WnJfV4yV->IJ#{3j>uc^6Yt{kO>8Yi z`Ke{HBJJQbt727ATJFdr3Jog_t3_qPc<;gQ{^yK--BT}<+Z0nq?~@Z`W=`3-UuOz4 z>~##w!)9Rh^@o0L>3a@>F+Cw&qv+B z>v&;EP#8fG-36ovoaGeI^I*M1LK$@6ho@XTGie-BjsPIYWyaGkGz_;OyTjm-L&BY? zAwS}W@?M5`59B(>g`6$?tqfi`_c*? zI~zxEz99Ezr&%d3{7o>IXDn=5fF(C<_kmj}t#Z7{^;XO`o3ni`N@o%-ge&5jx$0JS z-Ov$s%R1VCLD>1fEzGWZPJvg2(bw%w46h|CAkTr4RiIcG%M{M;svmU4qZ?6Li3C+r zfRZ+JRb`->GBFa8fvJn-$SK{+d4ZC963nc5;E(c#RS|E zOg}0Zdu6!>}HMF3Oom3elI2?GL4Gn89mZuBn(ND8Pdq8 z1n94_VMn+x#zYmRljT!!q7g(+i_qWtRSgy|If&3db!C9L!iP1!h$0>hCjJQ%D|i=` zSp6PM`sa8FwQ~H5Ie>b34B#t$HaH`B%%ORFA5Xwb553&#UCcm1h-3zY#vl(w>~tSU z3Z9h&K3XgudPHI%FAPV{n$D2VfrMqNKc#G3l?AR0W)+ zuk_?so!KHqR0bEaSXJ;q6yK(DG8q6h3@!)$Zzw(_Wy%^2QSlg7I#3kcw%o^Z1mWcm zkXuq@Q5QeGbY)9*r}8ClEd-efNFE#5rjprH?Ua{tN^2%UM#8>4m5> zA@eXJr&W27WmHpCLapVhs!X#HW_3mKpH>taHk$!K79BL~w-)V9LWJ^B3Vh9=f+N;X zpl1;C$0YAv$<(9vl(sqY;LOM0_YWeD4iWzJtL7k-q2#0u%j;3?}%Vz@%Uk zE7DU`6W+yzM}B<3x^#L$$oAxBOGw(N_<5zr7nPA$#Ts$Bp={jX^K~1b^9^-YPda!3 zT3;(lr%zr-=S@0oVlQ0=_^j1rkSHT#`#a6h&n6^D)a=#v^wK2R_x4_G2PNRLrotN%l9}2j$D3P% zs32?;*29b54N5A{$r$QZs6db?L+N$Z)e}n%en8F?X~fbm<_>2~m{Q^x(oWRfEd5#* z8qm*PiK0cr58JoG(GR0nirQ7JDS3Ca!&0m5{iC963((@Zno}zc@7*ARB{TCyH1rdd zptH-zC>k54W`H;Gs&ES%955#=GAL?-w9B^y@b?Dq6XVH%!rGYTqPRdyE7boQ+CISQ zl4q-OOH}&(BCFOTt2$BfJt?(z#X_}_O69O1rcvlTl1kOoVO~ukZzRh8o{Tq~`VZF#2k+5n4e>XTn#izB;?JnA60P8d8fl8Z+Xpt`b@BzJgZ zlrM8t@K0jQ(3F&;Nohu0Hb$AIv8QGa&ie_4-6BA2<#;P(Lt>&^!qsIXmZ_+^kvA3_ zAtHxbC=_&0D^2OC)O_>^-xx36y_2v0$Nk{i?_M_lN4|q&7N%z)zWK&ZvHi_Ac8b_* zRqb0iXizME=y6yxNEW3!RH-7>i=Ls=(#lD62hipjl&`d+OiN;ZWRpR(7S(vK0dZP! zSjNw$l6pcTD>^m1cr0h2EyoN5<@{u|++1GN#U!>6UNiJ9!}Q8ms}Crpks`5%6ZOcn zIzeeg-86B)bm!Y?y^kXqWm}9U$03$C!}dyJD875AMboqB^(f-$tN49ClW;$ zcI_!rK#9H7^WQ5d9n_TuLxti?Wgr4I-`&x=0gqa=B0~fl^uM0cE3C!pRzxh)a#^jD zn>LX%J+I=nqMYe@EdpXUvye8{^eQ&k_^fIdt{keBzZVxD>yKT5{Zdt7Jy?O5{j-Zd&0eS~<6&%}9;Pf*Gi|KiLvx`XHkHG8HgQ4c6a?(YC~J&%LzvYOaJ0Un z((aG8`lClx#;r~!ISs*++;4)|tdXwt#mHELk-4BavNGBj9d`rieffZRlBL z21r@-w-uhKW|U7{^nkC8az|(fRF5t`s#7y|6jJBH@1(Rrm%><;oepMw$wd-dw-ZV! zs%(Xd!lEAhAp5_-@l=eCl3Yqwjn`+qV>O!%wudZz#E&{bReny*P2Gh%+Q>^3LZj4( zY$>TQ`dZh(nV%)rXK)RbN{_%O_zwxgSRk!D`x}uNCL&`hGGQ&5NKVcV+Aj|9t&Eh5?B?*7OzyDRt|fdV z6TkA(FQujKbFuV`SbVh9EgOY-qfxQV{@QF6YmC|Y8D93yq-RBx_Npg~#$_{Qwjw{3 z{U38qq&1BU9y|XeV!rGNOt$9Xrw?0@ckVFleI|}aDbKXkM=3LxGC6YEBq82xZ*CmE z-Pvc@<)a+_MUz1rLs#%Xrk8SBJ4u%x3o*KKhhfmYMKycZ9bNl_DA*1oKQltt=F!i4 zs0kuOoba|k8T&o_zIK|Le1C6i6AkUe$pE7+kEbNv-Fbb$E{VfnO0okLwjy9(g6RpL zJ<&<|t4eGmq?^5p@Y_y~QMN!}kpq9o0D}@kxhpo`ZX9m24TFGjILBCxXf`7#NM1)A z9Eo?SbwxvxQd5U?6a@U~(gQYc;tFP$t;TSAAK>~f0s@kkksr8Evy0bbZi^76ay;^J#qY9i< z)5F5N^%c;(E@zc+@K`5`@`u8cW#ol0xa*}KiUqxPQbrNg2lVo9usp0|N53gW#i5n1 zT54?Zk-lsZO1|Ks9Y%pwiB`d><8Y+^x1E|NZ@Or|qVH#0PW8H)bIabXE!9U+r=TR6LS=NK)q?9Fwa%KEU-?zLml5(s*|7_`YwS8i2BiB2)g>?nNOj5vw z%~1^Um088eHfUoTePZbjivm3eAueeNxV(qV;n+6Cg&&a_`LM;aO<_XKcezt7aesJq;14o zvJ|H&pmQMCDWHhDKFMNaAM>TJSM#JdGmnhiU0}~mQk3%sv(h*@SzcK^)dF8aif~69 zWU`I%jZxCtT`!kDUiUuN^#eh_QL%*v^kp3-PL{fuvpgV$W5NvK@T2oovRD-h@~e2- zxIs);u99p?49hp*aGz4}N_J7__#4Asa7)~ta!i)tRdg8=BmsD2Y2#62tYUHV?K3u{ zL(Vx~T$J4|7K_954Y5i71Q-vxhaLs~_yug5a`N2@d14mkomI)Awb9CJGNfV0+T=>f zRpQ+9iWNLiTjkDVQ*mJ#j+?PvGC4f7{B>Z9JC?zsYL>wXmP;1%S}qzJJYG*0b1}U# z&Vm`j^|BnrbVjMf0w@&xV3dQ>M<69Q{-5hISp)LHS8gPcttnOgUg9e_lGeN>3wrZ8 zV-%G5fQ-_dHAfR^V}K$GOQSLfQU*oJQ?QAuNKryw|I;V2mfks)#cWu#C=3mO6a-1Z zlZwbTEBp0~T2-ZnT_V;}T(`Ai~pd>~vDvi%$Q=tJCcS`;0XD@MyWG$4leEn18N z@49WIUWb>lM{@re{EW7^3P`&|vVax>_!;Xncc02Cpp=n=B)RD7FN0cT zOi7H2Qqi2$DP>Sv$BZAVqOvL$0%i{85YAqe8AGi_LDn?=O;1rmyIGSUN9!P&I&B$9 zS_DV(c@Ro*Hmve>Yv|*HYi~rL>Vk#27~?+P67diZYovlkl$B5{O~Mh1VAk-D@@bIRdV8;TG}9W&U~zJ z$HI+3^Y_WXmk+V&n4RX#CD&byMn*1|L4)l(u082Vk4_$ly+YTB@O9Tzo7RmVQ~LPm-9!58#PfmBwPLT3TwYEb;SUvGAFSf@_me$NE`!(jSWY zD=pt)?L5Y)j=69#P|^TT5~8xPmO5va;esokJ*lHckae5VIjQS+6EkB(R;CcIQLz!B zPHXYIXHOoY(HA~%$r+8Xn&4Q=8&c3d&EBPY2NTi@A%|=nX1O24jq#&Q3P;CBC!;p{ zAXQHGo*ccZ^Gh9{EM8f$Xoa7&1Kdv~A=@}nR|u-eAe$Eyi*La4VClHYHn!y7jduM6 z&^#P@V>0TaD5|tE2MFZ^7rIFg?`dQdwV`|yItUp0cr#^) z@Fe1Ko1~*DX>EC_Nna#3#Zt(1P!t2#iHgj?okT)`F(~bBR#Ssd+GB|mgiqGXt*`U1 zT%_vAfi&&UjMtn-p$5LrQ=a04HrXFD2 z^fJzx=|OnL1>pH#$GvIn*fYF|y@O|PO(q|(v@Gl{8_(suqvsLL;E6CYmWy65-iizH z_wWt{Vz$-*3k*5*`I}HW3uy>Niejp;5M|Wh-nDxhQalB6WKM@m6yjr1L&Bv%CMFRR zfvD@|CCe;R(D;Rz%)lL8HX6J!KLoI;c?>ji8-fDV1c_AZp*M6TypCOl#C8-yIWR9e z0^u9!O7HOK@ok<5EduN~+&X%*dt5o;=L&O!eq|(rDOAalDPWNJB|DEAPAMDcB!7$^ zr$=vIzT7&JU}kC0$xVKWTY2f@i;aY*Il3s)5PaorudB@7*0YmD>F}glUt)8UZR5vt z<+n?asq}_jX4I`~I z_Xb`-KGm?ib>M^FORtinHjKb)iIY@0sn@%Hi0pbjkrq;O*lK)&LsIDzp3?cqbKm3n zi|}eaBG28B2b*W+ro@g^8eAU>pbPWOAV6ZA@|q-oMH$P1FHI-_R)Jhc!O*>=<5?cx zT238_uaQx_3CR_UlW#MRk%DK;|#YHl>*V>nZNxRpTh&PrTW}ZPVEIwYv z%LS|Pb~h2aV|TOO>wXsXzSp~Wym}t?{h@){{t4ThgkUvb2gf-#%;O_Ir=8YUg2hu@2MtNj-(t1Do>G zaM)RlegxNW2{0bOVGut4ZaI1&e~pJ1@Es^ql=jcHy#sSsN7H0eCm7b$F{<+2JGO>k znOwB}$B^Ly5;~j)Cod{Rjl|UKR!$gxb251R^Az=X6|zzyt2~^an;Z?nbaqCZ%zPEM zDXo#4mZU)(qs4sh@#ggR7;#P*AM@-bpIy|mCy+5Q*r{7%S|J%jpQ{1WM}GEcL&r_n z2_83AKRlH?_Fy26ng`-w=nam%5yB)qrQjUI6x7erWE?mFG*zKM-BMfK)wbfer5VOS zSwA+l-DB(#7l$w6c96gklEpP4;6yA3M~I+Y3{Vc|QKv%+>#&VaBQIPQ$-OyxRcT7g zqM25pC#R=1{8QDYmR8wp{F(ZO>^*fQROrELdZbRz8+CkI8JRVUD>EYTD}u}b!*(k! zI~}pw__ncJ6W(Pf6e|r9v_-D@KA#MOpnkQxgt5!rvIoYH8;ojj*) z-1n*blkdT7j{&SYf(WKD`1)>R-e0u$;ofHZV0RO4C(TzoKW$AFR%*{cJCD5I7>+<2 zhc$unKY|yOw-1uIZXA+r#Kz&eJF*_PdHwNA{;}Q}O=7n@j(9|OJ46SNdaP067O0Bg z)a({+G!O4suWKao8rH;`*+6F;J~iB8r5h3zMWKx3T{BrJoAcJh$Q_Wf z#HyBGQoZ~&Q87O@9d%Bc3Q~_?uYl@GWfsabgI>2Dj&FN5UQhcHkL!e1Sq+ zjPfAv!&fkdQeZBmmXEu0&Q$k=N!tv=YC=^Z@`lyZwpp4#)8S6)HnoY=SJlWpZ*?n`kb=P>_>Hf$j zZ^f8Skw}LSu2`~d06C@favng_nc7r~^^1aRqtvXlDxFxA!3erC!u#oN%%^sW(i3LS za`~pGu`|N-Dn}U^Z05(bjpjG3q|N(4n&2JzQon-5U6vt#$l~J9?$TKLY3f}f#OGK6pGM0RMc@aD1?!C z;f>I&u`53Kt{G1o?w-6IMYFG;OzvJi7qwD;l_> zjVYAgjo+X2Mb8^t0&w#egiWp1osAdGO(#N^r|Yb~(f7k{5O)84IULHHI*Hy1@4UtWVD{w2SS5%{ zHW{K3)_8miQ-(0(-HFG>T@q;?<9Yh$9a&Tbse%g2Eqesl+K%TD*2wDe^0GL;MJRN# z`wGe0>*4~B4un3LC`oj8LhcQSox`Bk=-66q2(g8y4eSCm7(*&1QO`N97dcRqeV-qy z@DO}p(Om(f0-(36WXqrkd5Jjpm|&%j^!m!`>bKuM=i*jYf5a<=drlE1&^kg1VBqs| zFwtZBX3&Lt5QFa3WYjfBRzh{lGp(yl;8ciQS-=31N&5a+2SJ~)Y#K73jP_P=|pBV?L$h^_AyF?>e`aC<+29+=r>T#xEW3vePk_(OZA;-OUp6CsBXT zDXnS_e2+|o(QH)dt*UoQOzFQR)U>Np~msWpV zdiT0IZ3AFxb0zf2&MunuJ%9h0CmgB9n2dZyFF?d148VtLl_C*LXmj?xelWV7r#`pu zU%EkPR=I(X4vyqRbl+plm}tq-suD0&BUol|tYFNOXsG}%bnQh$OYLK!oH@3}3}Jib zY45-rqrez8h|(^@S0zS{Fxl|i$i0N4zjv$qMv)#cl*hS;R^uZKG$&W}<8Pn6INGdH zI1|qeF~IAt{~p)0jC>f2ZgV4+LR4@;b30?3XG!nJnVBBtZ zvQ23x(3p`@_QhU`){=N~cIV8C;_;cWR)|9TH+ufxdgA>6?WbYu!X*L@+tp{QD^H%# zDph_oY%Wa%#psWy5T+XRzB=tR`|jDZwK=eCQ7@wAA^&tuddl;*QrFrZK6bxYx!P%p>{We;hQ+yj&#=J2X&r}BB z+2e1Ya4Fe4jC!7Cl4hsCxQDZZc{FEPVo7a~WnGckvE|h#%gaWl z+YoYKyroX?^usgy29KUJRwvi1vZVLCQ`gTfVMz$IJq3PREP3M&g~eU!Tr|2%sF?9A zllWxdEm@G0hiuSQT;zv($3(^)naQxhLT<25CX;Q8e_3#lk4V<1y@ubN>=KWvLw?uQ=^<#l*)~f=pyM z#LAD-)gxl6?TtqMH!25`Y9H?o7zORIcmizSGx3f1Rv<)y-T=m>rWAcQzN+Y>ikb_K zp}k)ECccB%bKL9%gG?5pxe+BFEs0jX!JE<2s@QvBOujcjR$0%Go>X70Q(rt1D`)qaY-9y7 zZWi6~*vE@jpkm!7;}E0Xsq>(bWA|92;fOWiG!_|KShdt>r*6gu^A`T)01?bxbbI1+ z`2uDe(Kh8BuleYa;k(M*GBn*lgzCFth^k<>51b#yJG~&BPL%Gsz38^5_T>#BAlccAjKWYI~84FaK7*+tC%QaHX8RLPpfB{$TbFi%*e0FqwSoNo?6SZ z?8F0D8YIdxTb*7)OphOvtQdNG-o@zx99P}Ne>l~_N=;eRY}pyPdqQf=MKUQ7mr^~1 z=q#lcL*ejhYh!cku)Vpv-Q1rYZ@^4#8EEkf=w7#X(HS(ZRCF&HCwynWx%*~wOH23d zh&omqbRdMopW(^D>#hCv(bn#^s7O7=&UXFy@Xc0D*uU#<>u-*l2Zvj!Y7w@QROz=j zc8{zAnuiBRM|IZB?CigM5X*;Hpa#1)X(|wFY-xNVF9?kD5lTHFktV|jLadRp}-9P0D`o6e;A#yK@#;b7L^#go``JpUv zc)Ytwp;g~Oj$gX~MU(r&-pf75KYNefx2=-*;}T|DN8^3mSTKJ>RO zzQ-3;a#hudzsE;Kx@=zz&}^tu745b=2DS+JSg+l#RG@?MV5&Isj_p*d)#rLF?A#v( z8FsHfSp~LJ!^$cjVM@D5Hbv{A+oLe;mF1eb`#!~|srsD7D?$d{UKbWoW9iFpl z|N9t$xK_G7L<*#rHHTUWt(TJ?D^Szb=O)&wS|J3ip-Zd?F0maI880oO$ojNHpjd0zZ{Y5@2qZR(M+ zOxI$6)N1U{=9R;^`c@iCDmBMqeJ-kLc0Oiybvd_ejaa;LQ_{~P$;nM@UaA;1Rf|h* z65|Z-R}=5$GWm3~2(KT271|I#|~=ynehI*Lm4h?n0Hj zj0!ZhN=u!VR*;;9*<~2k*@Ptw@4G!bNu*J<*VP_W7=8q8QQS)xUjiRt$60}^0&?!8 zR;J1jZ(ae;#~PN>D5u`*_8g8$ljzQEuY1QiknT;~+jtNgSo_V&NqE&$i1Y;wN3W_@ zFP#XlKHg&r{%IGIT})Qbse-~utZC6eT3Gq9(Uc8;=$Vimv5O5qaDR=0vznD&G#20( zJxU!-_@FaFmY-5XSH^709?q(&LVe>;{Hr0rqty|`eK%;DS-1itFis+yrtyl?$E5vI zfvFX3FEGi7u%iTh=LV74PV@C^?R6->ItKW~4Ve>vXkTGCoKc%@JnbuG&x40+N&%w2 zY2KKeVo^-DZ4=i$y2_Einzk{$?lC%y%7b>o+V)MN&?&fTjquvCYTJ21Rlx_>BOfH@ zQ^+)_Q74ocVHEKWC1Pq+$%LGjT7p1Gj_4zcnUB zlLp?i!rV*N=9G(fO28Dku=T2Uk|ZZd5~y8F7oc0820=BAQ%cFA0E)8ts$5meA(_>_u`c)6ed@J53-Sn0^?%4GXs>uyVC4mR>r z*XIQ!CUDrf5=#U6n4xm~dftEE^`o~Wpz2ybIYGcm&O189rF+D|U_h};k>7kYDu21k z&2W|b%gZh4ou`CJL)?0!taD0?tbW45k{We9iT|xx` z=N@}~js#6YA~d7M+16;O^{$nXVv#`;til%Y>8LL$x_+*ji_h#N@<3=bQjU^TCqc`D z-yBVHx=$Zyg<(-R*+gO*ot&vmgu!V@-s1<;>E2)glDrNc@q~7Al$+(r=6ob810EmFiH!CKzssB=``?nQL&7sB zngAMaI$5K6plhVjQQpPzE!i80wBU{B7MM8n&nSqPs&O#sTp3xX7xj;)NUq{#+_ml) z1a2vMZ{bHd#tWV(gZ#-d-fkSiZQ-ocY?dQ7M(wgQVpq$=kev0=*s%WZGU>z5VNwQY zCMECc2HX&yBrI{00y*OywBEX5Qap0~S|jM}p?UwcCvi4t1Ci}^H4KNy^7MuGF@{=*pBOGhZCeMGwWY zmef#^tap>~2$)*7cT7Gg~kD7)9Mj&PylolStfNHE79R~wp>&)e6 zF0q(9_^XY>&E~=87GB8_M|s|Z$2xqZ9|75~DxG~8zXfMhELU?X;=A@wFoR>DHfpS~ zlEdh5w<#luHbhfeYE*RjqgePcgwu}Lm{``)WMGAPvl2V+O0%QLG1N3-<|$jn zqIB56(?fTi0i zsVkSq)l?+u1)|3lt+=A;;s~wR$wfqK2wMtG2=mqM_xoNK*m=)7J5>vmOpGds;@ZGL zMAi(l3DR6$CR2@I-pgLhvsz=uQH0jS8IBp*O=ov!R$|2MgBpaP&%Lrv zqzKEAzl!=#>>cq*hV6FH@0$vB(gX()Jfqn@D$r`Mql&N7qk7jnpIkat0aoVBjFSQ1 z9GxWNe@j6Mq~+uG&bz%WQOC800#mwtjy$)=J`XjaO>aVUPQf>b5gP>E$k}5ShG5!2 zS`w9HCvKF2GktK54E<-aXEA%cSQ-tWo8k?Yl{7=srC+-b_)Moi&sh7jJrJ~%vvsorLg0Ca#KiC(t>mo#845Q7kiB~boO zm=d_mt}`c$#71-25nnY+k9($l**p1+l z#RAQzafH2WHsdEw%3d*I#$&j#>-Xpyy6!CfqSwsYQf+DXa7kkcPfO`o$e^j!#jza7 z&eD_1xb6MA?u51VR^{YmqyB$x{kPN8wN|y(TB%*e8j#2X&D4ox11K3{UA8%Z8Zhqb zXB35z0=v}tCEldqfE3Ur66DLS>1b@8a6+q>(9Jq)!OcdTndyqEv~>*V#nHZ+H!iGF}w~ zj-k;%xHcIa4LDy6e#Rb0gJ49_7@;7#8C#7dNDa)we7S1Yd-qnk7Z5qW4o0XCBFQ~w zgLg3K^0F2xm6U{d!3&V~j!v0BDd$gl8HxDArRPgx>9Ty5=5u?uGGP&vC_>)R*6WSK zjpKtutid@;0OBr)1Gwo7I0_wKfaFBigpN&xVnPa671k6d3^%wTBps2r9GOcl5U-9n z0t6z0F+ox0L4sMyh)Ma#xIb*C^^D(AZrFo(IUb?IvdTSI8XBP}y7m10dycrIu4j*7{6DW+EuKc`b$=5SoM!b3E{iH?2g zP&#WRW|ZnkQdKU#*m}9MFFqa~tvj%*#5Q~`eQFJy=by>50P)dR4k6penFLFEJJ|bD;WX!>L*x4E$yt->IUHw(MQTIoo%3pc$(5}c#gw$K5D1Jph-enTS_~O%V!qJ!$l6%=?;_?p6~Cj z9=$$O(u2&R9E@G60CYf$zXSEkFKA-4B=N+7A(FR63W6L;3Mhj*^RF^uyW`Jtks~9^ zMB&xQyBSOTa^OmxVgez(m+BTOV0C*lhRcz`6(B7vwhRA8SE_I2c)4bi=s|!SKS|sWs0tBG zD7S1Mu28g$B;`toVN6XQLH0Wb)@rQMBcdIJTVp<^=Ut4oTq=UFGi%U|OCrR({>@`L z$*sYn2r@|JlJj4V!g`lJjywc1!fz~IKr5fm6dHSS0fQn+GHJubkcIXXYIy?f=bd-r zF?q@XuOyp7P!ueeZp#Rfrt}oW$#8c<)D4)Y)y8*E8#guJdV4)!gH|Q7pR|2Ii8V*M zM)i*@0f}{&2s(nb8JZVCCNV|^Sr`G8(3UWe-N+sHY~gRBQKpQ3sH#@reMUrKB_$gN z3I~bmM{uLFM!BYh&m>?6>g4Mjx@cI*glwoz5-j3_*9(ROs2C31A#nH%4}pUN=UhO+ z1s*q+8*uQN3kqlLDsm!8 zx6$vusg}v4n~NdAr}=1z^?NjBv@z zOxi0NIIJ<>J+(Iw{_ZtK-GXy@I_2n0Mk5$@w3gzlfh9_p7Im^@CLSyrjpU*Y@me9s z$Rh9-k*qFSF=~NR0}KQZHV+|mPBLn^n2-SHVuI1I8nMWU7<3%c;K_zad{RY|7Cw;_ zOpJh!P<@2kr!+b^P&i;u8ml_Wc9jtGVAcK;yZb$ye!3u^Aq;V8M(8EoP_N!>3 zI2zOmjxQPHnIqsSfy@zM9{$e+w#@4C@;3_c@d>P}3%}z_cuje@q2MyMJ{H*1UIS*Z zIjr81HQIr7SjBbV>VS^dcSDRYv=)mui*&zH{F5vH06Z-uJL`p13))948a0~|3Y0qtS>O7Z z9SPhikqSdei(2J!`1fBLi*(ibWeIqxR<#usTl#xzOl$I{gyZh}UYJJ9dz*T&WLgDQZsuB*7@8JFgFp=3UKm6|<3wZN@S)tQ$%oJA zaYg-R%rH{51EGvkRTyYNl6dH7UJtuV$r(D1Ei3GfK&1Ra>Eiq~o{?ZM@AF6Sb%tQv5Mw+2%5iQ=_-L*aT zVNgmHUWL`AMguVmQ92zLfH0azA`;#?^n0M||@6>~{sB*CRp4S&8&s zth=svi10Q<38^@Kg>1UC&-lQ9&WwAj)a{Yb25E3qCK>s4Jw#|4EuFz1Svl9H6DrXz zzCiIgkV>{|tPj;Qm9(V#hO2}dCaYE{)o+!9E$ZDzH(3b`{WCV773kcR$f?47hrtBl zM=az6d5&0#;uTVf>KJI1et52LC1pKzG4WLy3h4E+rUj>A`UKFV(kM||dcEIu_z5^6 z)kMUv;7I`(iW#ymkrr?TaTD|a7cxN@i87=p3*KD5e?@!EP=Or|f!xRu}f0~ljCoZ((lW>YV;z*z$#F=F#| zXB$yY2^NYaeM_2AJ47!XxpUG1y^cL&Tw2KaP)#>9CTv zZK&@?qGXH*#MsB*+ZakGa#csf-(Z3v9Z+hq#MUUcg1n+ z1tRU6mgXu<0|H+M=l@24NY@N8rk|~!CDWamqWDx^Kz8%wWM%a+UL}q4useo{Q1n9M zT-cGwt<@&Wt(SB*&7zy>V$G;S(fR=U;wx~PpeAigL_SWj-D8|usv{5Ai?lXI?^9bF zg)*~r$}_e`%KDJKQB1{bx+`mx`5sH1gb_#uCRjhsUudQ#Em_|xsqPXL>c_1pIjKzQ zPf3FkrA~SJq_NUii6w$3v)eCM$E@bV?plDtgT8pucqY&!9=QZfW*%&q49S&>boJ*x zBINNerijwM)IpIsmNuK)i2?No@}y)_G)F_1`qqaXxG&FE@=HIuC;J(pAv+ zmRS793=us=9OhtPJb;46USDxa(qxrN%@caK+XpNecrwGv_A`h>fveL+ZnnlRSPS^TpnX~jQ#;#g|L?CqL)4T_Ga ztKraH%vznjd#=u2j@1b(4}GT;;tm=d54vzCJbDGG{#w7$`pvOshVJTeTP>PSCo~^A z53pFKu97<}g*oPU5Wo~aB4c|U2NVrPI8suqp#SK3wk`2ry{^A`hYU(67TJAlQG~tV z8ZN^VUhoMc3ABCaqtfW<)2B7jAPAYH+Joi(kc4`{vNY%t!f_Mq4~1$aTN*VP!W{>F z2IpHNpm;7$y>4Tj>rkLP(q){!lat2}V%+!D=JetDvA7U(het*{Zrn&cQlrg%?H=5x4c_7m@s;Sct5u3@{tG z2eo@$+n}mYNLd&KHdeD=VPlJh3*Xu#ITz4fXYY?#cyo$RQYK5!uRX2Q9c37y2uh!4~v07a90hd0oi-+Rm3+q9$3V0S(vX2S{ zRS*2ol{|ZbMZs~Zs(AL~+~@%RN)`?oqQc>aF8kRNvk%qj9Ufq$>3ZLVflblR%#<|&P_08a~QNnsZbIBY4NGiid?byGTmV3%ZA4V&GIG z^oCAwanUFenOUTFxKH>erip%G!l^=Qg`0b-Fd=3pRPss-k6!sPMsK+H>v9x|+M2?VFP6wx>$AA6kT8^Wf{?VIcfS~(Gw zlJr4GD;6CNM@Pe{T5xQi1jWvE5v~Sqr{fLTCO%rdBag6Y={!F7B+Ma!8!;vs zaq>}tlu=^w>ag<^aTLp?+i?bsEvjIh8!vY1@;coyfo-(IHVOMIxRb^#+7B$8(KVy8Z3sLzSKB`K$N=&z` zQ^B{-W%18=D{UK!g~sC2((|QXFlzJS)pf@m;0$|z z@^?rqSv%2x%riR!&3b zqu{+K0sAN*LKJScMuqf&tyb-+)A20MgBwqy(OWf0vw6fbV1FgH4V69|Q05B*Z;UKT z^`3%nSnXu7(QX3+)NbQ4MxYAQJxRSvg$8~|R%VLob`Hj)Z!#Xq;oSGeFOD`v#ccr7 zSdGS1%X$9Lu?tIqqR`32e8y$tCdlSvDW8lVjm2sqZmAN9=nC*Jws>sm!dD^5 zcO}TP){5o>e-qAG&Xeg3K~61S@gS^QPUDUo+||anb;%T%XfGK~#5&W-$+zE;rAzDy zdJz|9tnPvixH&5^F8L_65rH$OWsCMe48m3AZe?z0#-EtxKN8;n)4V$}?19}h(fPsA zl4<^%^h44Jfw@NHQ zom|8$VPK{T(vfpI>Pr8=EP=L!d967|1G~+;glzdC^xEC6hg=K2;mV&K$J)RaICaFz!Z8Ezo<(BJ;MF)`(6UMK1SWFXcC(QzDNQ< zRQEUp_9K1CQJ=o6mj3M7Kf&fX4GJ;$yow*l*u|zc+is$4A znldvT+F+YpGbPd+l|c?IatWjq5hL!_iiPp?qgLuzngE^uq4xt&NOm?$| z+!_WK^$us(sCD?9kPwWR>Zyfmhu0Zk zv^xc{kX0L6E!hiVBNUF&6sIP<8#H&p4gh&U3jrdouo~P;a_eRcUMvZ>CkIO9kV99& z^&q)KlDw6*?Ntc+2svU}NVX|)NHUJZ_~4>tL7fPnG?+1Hh)t6-t4N-DRwaj%LGB7v zw3K9!5*;&zA_h=Md*(eV_bA5b%Qw}Lbw@#gz>*g=LA{0z06(ja3=M#3G0wyw>c5WSfFs3l?s5#- zjxmZ5#hEEq0DoP#QDW;CLZ(?Nt;8ceq^${^*hxZaIfPQxCZq2*J|yrkrBW>Lg6w*T zmld`<7>lyq2Z|LC&T+wsG7AT_fYQOg zW)IRj=3pW;`ax4vvll?fMJu&iV$}dA7M}>%Sd_Ln0$3^DawiSS7;~)Q2fK#|8Cm|H z|D=e`2is!h`+uy$&2e#2yyfWXYYLo{&P{cSNpE1$^~P{!B~Jbtl@RMy4M|ydg1bnr zb>fXwkuqYSCT-ZjoqD%BeDihp5h|?bg$Ae;dV&cT3=~A5$A5_{WYvBw#kGQ ze(u8obh}0gBVHk+5)6oGGBGqN3C3j(W+fieF&619sstI8RNkrd5zYc!t@6_U8SAWR zz@gXyPCt!Eioc1BMWq*ywYco6Oe>Ytw&iJxA=Qpn`WnlQ;s4g^;Niv@P)~L@t`LO122d($I(*>a_t~MmP>~vJfF3egdxNB(YC0tuWgFQ~=>>(XpRL^hGrt8%9 zT$M5F>Wg*8l~h3KSYyv~x%lzOWwi5-3+y?ZF|gsslaY!@J{gAIIAmZ-%C35NRx#r6 znGHwJm47^CQ~P>Xlv~RyPgS%b*@T>BoTUUKlv$%F7aJYEFQ11&Z!-22@6Ok2ysi)m z6I@;752ZL7arkUl2jwNk4425^ORYw$u~d%0N?q86==O~y(AulWY;;wa4AmtSFG)Ud zbU?emx8UF3m;SC|+6f$Cpt$i2QB2s9ZllEt63i>H^MzQgstg_Q?(b0%P_v^d?&`SO z24&sdB$j_ya_rO=Q{(M8YW?h7V89^ql&^8LLm;tZkE2q<0fC`jIWh#S{Dw8-a=gsN zpvog;0~Dux@MNj-<}PDrNr=lHiJ-{~in5#AP(>ZGwe)77BNP$Z5^Vx()7{*TC4~QlyX^ z4?P`LQ}Q9cBHh48@07a=NtQxX)ukN1rb|L5-W?8I8GMDp5tC$mAS2)KDL}V&_A3+h z4-K9D1@grF)~7Xzt|-diB${Qu#ay%4+8e3-M4-+r76tcI{R87N|1*kg5b3iQp+quz zFB7ZzVtccU*Vwexssh?e&fT_#&B!28MdLa2eP9ObFBg4$B6sH&?oe#E-PomIH+~z~ z&AtZg&fxzOWK5>oIy^i$#8Av4awEhUya*-(A|!0%CS{G1rNXd8xQUP6yf``rUTYIM z=|nX2-A%34IF7UfN^DG8)r73k-~^2eLulO?_Lw{3;tf8p8oO3xB)aPz!m3u5V_z|> z*VfHK4%tFoOby9yq?KGNlS!hcl@tHMRI|{WN82B&O`vE%84H<2L13)fS}H~062k-; z;0=tp4;gzleYc8a%OdlIjQ6G%A4bzW#FA(s_Ps(5wweG8^nJLsd$6&Yd9{OMHE_EW z!%s@U={B(d1fX75fxXE=gWrTCn~?g_NFiku(}>M%)QGf+B@r}?YA_tj;CZsB;QZex z!NHpsv(?=7UboE&$mJTJpQOE5FV{z97(DY)DJ`K4LTEg}$#js@a!_o@^CZl294on_ z4KCzEwvvTDS%uaEQDVWEdW`Xb%Ei19?o)3H%&S_p9%KAp_$$Nx4xr#JN0zzneXfr( z+Ytj{yHj5b8Il^41Z6bJ(IgTv&S2tY*gZ}`#MoK`bcxC;FVfXnq8MWX=siIp+WCgQ zw{`sLU^7!+123**(})X+G(@*i3_z4ZE|{C;0tJ8mKzrL7Zm66!7V15|T@vk^rP`Sh z#l9Hda_+uvY@A88BJY+o$vCu!U)q8(SSVWXQ7$G@Xi4|_l%m(ml20!qc8M2Z zPB7o+bv)96D2oOZ*J8-0A>0iR*;xvarT1|W!^gomr_EUdUY0QoYZ<4`e8UP;Z!K_r<&<#TjP({UHtF2n`tr9B_vISj4E$qDHTPEYNey&#~h1crdyOWN*er7p#Y#Y?^f z6V-qMaczd=73$w3R=L z9U*Jl1~4XXYj;~90Q7e#fS`{>gh_&Dd%LHnM=wN03SF5{eljQx!K9_{QVq>cLf!gq zYRYK0vU?KRwstr$qY+t&EnF%5+BHU>Kpni_Wpmf?%7YogcXYA?iSq~2Mr_=7{XrwV z%0Cjn+xJ9#$n}#8r0W$et0hr2pbVr~%7hqsh*_U!-i;{0KYHF!>fzimbb?HD!rMV7 zI<8Pl;8jI8;RILJWTNC)O`opK8S9eGK`ZXeO z;1B3#{n?Z1v~ETyK^JAy+ad}Ov>;SC;pvO6A&xvxMi^=o@6CDjLG-*tH{oUV zhwQBy>&ukbGWm&aX4s5*;5bAY9!DCGH59uDOEU_2v@g#ueR@eACZx#GhJ!oaMoFCH z!W4vKn5anXwCjz_p}L5k2e3TZFt9JsMzqJvm~2HnIteDjh9zQ~Ifs>P7$s=MC)t`$ z8tT8gN*J9x?3b>6Y32FTSUgJ& z%@hHPu&W zUZ;@n8Pv#N7HkA?gKJ2|)IQ1Icx+nq2b+B&>c*351zDr&4;68;y9c~c^#{8f73xRz zhm#s)TNJN1>W4c=O+k5E4f-gb=I)*Zj+XuFB@`F;oD|tQ`LorC&y2O*^0YV6PQynr z1&nw>yxwV&H8Ro`2?GTOhJnsoquWjyO(br`r&hxycIi`l=y&i3(zF=|2?2Pv)e($M zWG&mHN(+_@7FjKo=Yr%VRMw)6uv$$8O0{89t4WYk6XLX*ic`8+%|;|u7$La{#Djok z=C96xwYv9Nc=svR>-tgjO)Vgv`aD#9);h8Z)O3H~T?gT_hrNtN{{8uGVsS#Bb0ZIW zVRR8oAS2~p1SYJ{9|8#Tz$+&?+YhjOX0K5L5GDguCI6IY43GR-OjM6Kay^7Y_I%aF z;TAFg2y74kuOKK9d$FA2C#fZp4`!aS>71%$ROvhzbVk)VxKo)c^nRUqgK>4r6;P9p z^1}=luujv5OH_?W3>qrpzKwI{X`Im-XC?z=i>_3=P0)$CrexT;LnedQQf}e7w+`hc z(-CWIOKBrsOf9dJU6-L6Pq%>o$3H}BnaY?ZW?P$<*79lEWAl8iQBgPJ6b%FkwX9_r zrnpX--M4Cr`GS!hZ>p=n`nqZ5?--6hDVieFVsn2lm&K-wvbH)3z4wmlO3mJ5e?;hQ zI8L?Q+~3P#yO~g=&a6pP2K{QJE=Nm?{XNt02u&^a_Z-6(ak?o-!!`lg-&?2rhIPoG z-yR1%Hz&|D(j0firbe)+-T6xU0APsfOu&2@;O}N*fv6g&gTX6A1 z!*EL||B`fTEEq% zDXfoz`3~LNa1Bd=L$tppB;ir!0?rFZ_?H88D91F%qsg-;a3zH%MNnL%l#3+MsGC56 z?+3T%TOtnWP;?dzOZ`R6uu_H_FGCN==A*Ev-?Qn*jx3f$Ca@%A@#qL%W*4ORW|7OV z{(@YFq%jsz{sL!6G-^1jQE)YlnpI^#psZ?#4!_qGbJc7(mdvPN3*rSipMg@mXR*36 z#w5O)G^ElMDHx35F6%)`6@c)XVV}nscsyY8slBSD29{M7xRye*d2}qwaY}lyXdBkl z%_QHhiFj`Y!DqHcOGM}41Y|bn41$R8&=A;Z6zN+Kn|>GdzwALVxTTJyljR!eV~L2^ zT9=3_qHO%d&c3W#tQEC*cm{RWcOX14=tM)uhNFrs5KnEc5|I=J??oMdI&em;8S!q; zRQ;kJ-uBOfUN~bBlI>yhV0&BJRLcU^okUTNEznKmSW6Z7(o{!=crx*6)dDtBqec_A zW*!(cbLzEr(uim*&Nk3jTorx8-Ve^@I1_?LwKQben0*3At_;@cO@!1ur=bB=p;c@I zc#u%Mof_s(=JR!>jl=23tBHdE`)J(uuybuuu%C9I2Pu! zw9<04Xn#+%S}n)w3zFWOF+R@GN-Q8XyAyA~Bip1r6dov`MmMt$TNRC$XrOIF~JXIZlH<}tY5G)vZ$MEA60 z3Gx>3o%Oov z2U}psU#ygpKgg;QN~Om$=K3{t&_+w2j$ol{fVEEb*Dd;MymBeXH+)@H~Juf zHdp%BHPP;06Wc>$(yIyTi&O9QubpK28q83r(vl>jiFc&!9hwK49jfYAWYtl zQcBUpl#*cG$V7AZb9#8Iv@F?Oa!$45v^KVll^{8iskJD9OhJLWjM&Z`EeX+!Fu1r7 zGQGBwGLcu}i`}wof4O_`0x0Ow&wDR`oz1r4O&X)yIdjtIIoxRJ-NxG=lP}F9EbHBu zajH$B3F>B0S$y@ z=m>OU_pUL}gggStycQjFZgBuSZq}RLc;w$Sgm`;J43`AB zMHIeFBLX&3EoO-f+pRxl6$ud5h$pcvEa5Y>^Uz3R!qFOujPYWwYE|jevJ>S| z&n3n-UQxV??fs+UH#!L)iDa;S?VR7Z^D%Iyp!?H?Ol0&qZk{+E% zAOj|M<{2rIqGPY+Z@1eW0ZEzK6@pr9%arjxtqCMKzX+l)qO>H$N4k5j;NP04dRY>a}tyL<=$=_fTEcuJJoecaSEEsscR;K`!Z#ZKpVh z`D0IWLs&{v_^79ZqY`@2unwvW%XmXI{DPl*=!`{(PkfbK_N#)Df z9Z7HPf1!Bb2h;vNoiT%Z2(Z55r0lec4vB3)B64aw^r-FY^7FY+4_YPh`15m}dg+Lt z1IsqJgnAo`3+Uq42^))*p%3gTbhf(m@d{?)#4Px9eZ?pR3SIu&?@LMoCKg+tmOc&; zWZS4oEI$%&_Td6A)H`^_4`A#4^69iyU940S`9As=6{=p!={Q0@q=hN$MBy3`r~ZEe`XN`Cs@HEU~SjLQtQ*F)@TXCsL~4;F)c+{ zHL`?o*ZO_wmy>_}aJs~m(4!jteI9QkrKa5?tD>~yTFd!Y%YkaRfH4;^IS%SN~>C{PDU}dctn;th7PcV?{X{(|Lqb888D!<~ti$--NrUWIX zU!|pz+~GtUqX?{)22;cLVk_vrfMT8z^VGQ3@p+q`%K+Iifu|J9CdKFx=w5NbzkquQ z?7PmeHwp2-qCCT$rXxNU7rX&*8$~+MQ4Ni@E3l297m3EJC%E~E>Q^&geEghN*Jo7$ z&L{d^RjMD2YSznc`MFhA^*Mw5RF^WGHVO$J zQDHD5+)kv9z*)ns`Qlb7tog#)h?M7;SQo~u_^&Yk>dCRvmG?ieHeEi}-xSIQAvE%8 z(upD^rf%OJ9unk4q7>KT`~aZi zA8u{Ii}u@t!yh*e58$vbO6H2EfomeUrXE=!hQmsg=1QWU&7Ozn5!szelM^c*38xV& zTa2#*_Rppz4@4!6DAKcV+&7*{Qxh_K*xh+?#HyAf$9&Eh5%7k;&^u0>QXsvJ<(OOI ztYC3t#|U=VBG#&tWG=>5NS{rRTjN-!aGpdnb?ZxJ$L)68U59rHDVNo<5~Y^-Ws?Gu zO_!p8DO%TpMo#7OvP;95C^HJPELjXl4y(}7gzeU*oP$|qQ^~qqF13VnM`|*HZbO)B zh4tx%YuRO4I%&oFeE*N9rha&2@Jni`E;2K=$v)P~M>W|ChBRs6jCNSU zBvnst>C;@TYfAAPXB9)&AI;M^D{#)7?TiK8xlfbX<{DiFq~r&VY=%rA6`#md><6^4E+!JXcsHv9LP?{6k>> zWPH|qN65~6%YF1nXpIg^`$7^FQPWh-*cor!u}SL7ckhz4G|!Nf>u-Ct^33FBx64wn zRW4>n^-~%rCC%!Ijh%PeF%?Fk5wmN~)EA*4GGu)UC(d=G)kmjh98}b&1*2jif7@TE z#>cSJ(aVEc-uEwE>CKf58Gvzs$uBO7S;$>Q@dT<+(I>(^M+xc%7I<*-VKE@&@$%;$)?&cHaKbvE*XP`dqarSY~zncI50Ly!VvsPhJf?Au%Ook zdUC6gB^E@bUPo*jxD?ji$vCJpfK1hh9wAr0Nkv~a|3{kP6i#w3pv}$Q-S*Zygnuia zR_&?Dz%a?2X9^dCz%&xjEW*JBS`ZBM@FCmmN_z|#qrF${&7a}A!*|8veDq)tpsg~L zUXB@JcmI7k92)K2{GXSvUyE*FW27Z^KGF&0|CX~AcEu6G#?<}r3X?UAHSGyU9w`n} z74HVPPZ_^M;}|q@G|W1kt+u6rB}ky^2pWN5+b^JZOSE9+`5i{`EQzRq6trQK5RN^! zTVn({G(jADse>!S1IDO;6>8dY^@+kwtFtiIq||@J+ZrrFe3Wv`(Nrmuim5Zjs0rfr zhVt#f38A|&ykt~{s0f*;A;iIe&u5t_rSS8KlHYe|#*5MMIkrwDMd>ZXx63pu*67AB`l?oj)4S|J{EVg(yJv9FLsDMPx`dQCD7) zic1V?B0z$D?S~OH#49vXP1L-iy0KB5n`=-tl`|YR?!bU#fcRuYc(xGx3K{%hVKysB zN6l{AebglQo@xL;l-0jj-W5mdjT( zEZs|@LK%aCLas-TltWw2MfxLe*~sJU@~U&A%9uX1x$79xdP(}+rSvcZ$_(~^l69M8 z!pMjO`a6v}W#dm}j#smpXS8BhzrtL1KgJ_=8JAc>{K+!X_V3@~8#wzp`_B-XX z3%~Y`#7}-WaeK5oDucjaWJ0FhgIo0Vyr%FAc$kqDACQe7%$lacKK+sF7ii+3t&T%U z6z~Eo84*DQB*v~Za*l6q$fwK!_%RxR1@Ys?&YUzV8ksu!zhLy1oMV(^dJLc4&aks6 zbhFS78<}QaBFG8eeEX~oC$O?TLT*LlF!O*m9)4ESY5x2&ETf~o-BI1iS`+~SC(3XT zB@-(Oh@Tz2R(DLeQYX0?Z` z_{&i+8PXEy++lsr->vA-y$f>}^{aDZumiZY++X?VO&V^HxR%KR5CpG39N%KZ8VWw) zxg%-Yj|LqZz2TLsieL~p(v)!V1aBbT4B(b25mCtXA>Y1;?%MYyblm@&9=Rgk^k{a^ zFK>D$C!Hoo)Pi#K&uAOG*c0z|#kY;+n)t4gO+HTr#U>KCI7VX-FyePNu%z*g7c2?|H>;R zQ0f`{Li_}~9o&%YJ9^ar_S^UNgAd`fGu+r;Ifv%0=+s!shyd|9&svRyXk6^m?&1%6 z8=rO`zt@f2kWOdFnDejyBiR-A(_}hsj=wliztM z$o~iAdde0UhOw<0c{fetu#wVD2If>Ns`jL@S_9H12gBnK9I!QV&Ch-LF`LremCngK z|ASxo<2><{X@S8F!YBEzIp)~k+;M;1j~(ifeo1YGNyqPgDN%^_hcmt4(qSwO-?*=Q zSA5u2oH7dNf#>z7b!^{U9{a)I2(HcbH}CMdfU#P>pEzvF1bw(6o2W`886 zU0m-V&_zV3Kjiv5GceX4XtVH_)xuv^3x8QHOto6bGFwpg3etSxFSCU|z--|^+HT=b zZ9nk;sm461ym)vW`k&Y~gK1sZ4Z^rR&Hr$;2OY)>Kkz(JQs2G@qzqlYCS4%$y<2Ew z(%MFsM!Sr04u~!?mX|Wp!H_|DR&FLECP#gMgh{@O9;ESyX@=#y9aYbjhcFH*oykRN_yq6*qOCd z;$pS=q*3z=Z4$R(U?_keoUNAE%Qlx@ULFt(*6PEkjla-9Ts+`F?79eqw+)RQ0e$|q zv7!S>UVQiT3$5l52FEr&WD!((^V9a^PIJ)mZ(6nq5 zwP0z|&HIruqoFrFWn;jf7uv{xk1AHe$3(JL(*DK1|zQ%Tn_x-pg74sb8L5Jsb?84 zr>O<*rrF3f1!Wx%!?dH28ZTu*@h57p))1wrMpA?p1MfNv!e?{d0)I5_Pj@B-{}s3P zsZ!}XFlk894vw~$R?;ZiL$GE##@|B~Xo8V`?IkpYag;}~Jc#8n98L!EIez0;^lc6f z!_?O2zLeOrJ#9m3z5AUlrRJK3hup|^m_@>sjRjr2)28?%Xi^?woOnKmFs^J#(&VtT0J?4N)_OE}8|7A$vPT>FCa`<9C zCjg7+)oJy#>Zo?9U>^pY%}K7xC2)!kV{qL|ja+cui-HxrLL4qBWOhw4vn6F#SuxPZ zLeT)0?5CR&x}EU^xbIs9WVBGU;(O)kON9C}J8p%pH&@BrsPxzqiKrHkiBXq$fMupH zy%fyg7`$n6bxg4%4&u@|!da~9YbAWmx61QX<>-QOvF3^65p#dP3uQ?O)Pd8J8KDDS zMhhJSGfLy!jv1hXh3MLtMaDKVqOeX|@CvLrea&C@)=N2#4+eLX!7I5$>eG5_`c5%O zdCQ?;+1=UyF*CM{(bQ71GGkNB*by>Qv?(x8N{JM&jia{ZJ&@w`3(1jLWa=#Q`zhg9 zq{WgEN|_)B(_*i{4%CQDaxjlxA+lcnFh&T&AH@rm1XU}<^g4@cwi_`lC#&{&*p_(s zlxbmC;vi7l(9t)?JG)01&1nP9mZQ4`S(zT9B_;Gs&QL80bSR}a!{LmUvmDq;X?L?4 z4R3r@vtgr*CCNH9g=UGtl|!XI+24be?VkfN2(j(~tRvqWbUcLpOabuw!~mn^R=FH5 zH5SFv5`IOV7`YgYpIfqPEEiKXwwC|D6v$5rS8?r0BM5XdrNMIQO-G6<6heBvN!$}g zZRxwnLgD^Ey)71l0uT9?3essrjQ(b>Cyv&?$_xe3e z>_==wrGjYXs}xWB*r{Sn;po9;{K1R(gSSqVAV4c8j5dCXuO8P{YH%1}@XiLl|0rR} z@s;>2KATIaK1p9j7KY{={ce7-j(@3s%6lotsYf+^f|JkeGs01Jdp&yM6lEDH(R@sG z|Cb~e2m}v(UiyWC@4P%bLd17*db)%(guWTUF_u~@VsqnoW9d0V$HUV$hGA$gg|P=l zCVDD=nFZ`{J>BP6_r?xJq={;tgL-A$rTz?rHHv^2Yg(r_>3VI*0EuO@PRi=cI@sPm z+QP&ycDLG})YJC%$}=C<8( z<1TF`Wd*)5km>KaQ<=#k)MC%;hHd6_(`&RW;M#Z&D0WPm{$;dO_C|7C)b}<*G^RD@ z&#+32=0I1wC=4eMn0~~Y#=EG~aagikiQ4XY81yD%Z$@h9Gh~=PY?+DMy>6cLp*KV< z*kCj@F%ZK^*xsGd-tY!RhS|0LnvD_?Dv!NW+6%>eAwTe-RYod<RqqtKcBM&kt_X#6*L=75M4k@Yui`xCMpzuXBiJGE7B8znfBh(4HmrGXK-*TE zZw}!32W@V`TZzUSFY?kH6oUivBpEq$WHpvh!Y#VN;QO#GWlxNV_0*?mUX1Q0{Y9sG zau(P-2ru`v;DDUUeqJFNr1Jw-&d?vRZG;snoJ_@1djPUPO}`Gr;Z<;r`?-eX6yIOF zBck2%_~BZxg!5j|d5^K-V2mL{NIom)9t?vgRvRndHJ&bVuv**+aJr(@wS!U!j%$T0 z7)nXHJHk-}EDHr$2v|NBjWN=?hPFi7-NcA4I;E zO;@UVo!HX4oMPd@IJ><_8iyODe&zLsF^SwDuruZo&rRikfu`YdamukKSr@~ykt)%I zDFU)tyth8Rl&HDwqK%RyPOxIsnUYRF&_$#Q%PXg+4YFBd zT0)VnqX#R?4I&vZmmT7YHOc%ZzFmom!e5Q=9ygX7t1U6R4G3uS>YK)6(P%W{g{(p$ zD|t)VgX4RIinDJUt0{%4*0Y=#AL%Y=YL;ufBHu8rgpsQ{Q$sM_VJhie2|NItj7zUy zH*3+M#kvS!1E5*A(x-BY<5UdaGn?~3NC-PN+sgO-6iFfE&qm`A4ei369%X@X`3)c*!$K1R}bLBVYy0fpZ6F`6{` zbEoOJB1(;i#%(a6Qq=j4)EFs!^4NxyaNoO?nvFmZGA~{j<=IKatTtAcF>EU_u0Er?uevUQ6`{>GvKmsDcz0y%L#|lQT}a> zD5l?^5pNyFwH)q9&L)K}k*=-HYH~hA!hj4Pfy$QT*Lpyi%d;v@2w}>(ATDNf z;c!osI6@B!GU04oa##Hu$r>~;-udqw+}T->M!cxSr50oB9h3*omw$KX#o@-`&+VN} zvEpDPzd7^&v~_s2bFeQ;efQtN=q@E3ZvC{wMU1=;KGMN_rEDAu_^(aj;AjN&tp8p* z+}KBG0(|g$rPGZShDscxJW+qVTFspBSzJwh*J5L)m0*bou z=}M<~gLA5ZZqr~*{v`TRsS1jh5Z8M0x15Tj95lv2waLB$ zJ?ue^`_VoM)J|0^YhVKIxR+iX9U6p2I;htnJ2o1R2>q1zc!4hb$OOstsa?_0+1>4- zuH%-a(+!LSOOGonz>cC!9<#$c_AWoF5=JzNbzKznJ&$~8YAE3ydccvvWucIZnb3^( z%^A({%CGVHIz#EjjjY><=sb)k%oslG&+}LmRash+i?H)>@X&ZQ-_OW(;s0JNSaYA5 z`j1`~_a*%{iqRjyw$4;PMzn1P0#7a-aaO_ z^uFcbaFCr$lo}ltVvlMvH5M}Po(l{x-$u>}4_J{*-*V2>`cI1Q3%vf+@Rp zf?^a>M-;L$$^ULSLdW=Pa7BG@5MZ>kGAkNkMb-#83GrU^k7_{&e~BDy5XK5#CJV3o zitUhvUYLavh)ld#1@JIW;V9mK!rD>m{R>o3 zidIlnX26jt;YWlG52CO@DqYX*G4;IZT>#?&3_>-v(qH@U!>bXTONj+R&0u7`!W3k^ z|9^H%K8sqZqmMN7`Jhgka&2bee%xVT<0JH3BN$LSvCMwwvBN$ z5M!ogCFdf!sh&`5`W=nlXsP9i=SID2Y4bc3HVuXcBKYAEn#QT8g4X z=};O__ye14uY{qZlRID9pUo;uRoUXvD%SB`H%=9N&F~yX?Edm)&w-V$6k&f@DJX@)tqMd4LZAc^2z}fN&C3UzgO>${i+U>2~?RFb)k$8%4iMkf|t5@Go zRUT%n&KERjWQj3z+;rdBgf2_|`sJmk`GoTiQ>m0{CIu>#D7FJ)ls1WD69bY`VuBAb z17Llw6oP(-_^#qjYVabY8abZ;<%X( zm66v}=dC9uqf3vhaK?d{3@=A+ms&{0C?g!(*62GthDOLMlI8ElfNi@ZaFkD}**=E~ ziEMO;C6(6-+swuUShg&Sp*Si8EqH5mfhWTqX|R(p%YkwHGByE!?X`QWfi$>OI-ryZ zIh6pHnr3;K(~uIMJjEx~dvEPS!D~=lcjt&$uxwG(ox2gGP2w@!^4aV**r!=aO(Wny=2{ucLObB=OxM%*`*5cVuEok zsDgk?kkA=n)JUarL%#|cg=u{4!xh}rbPZt-Hzf1=P=xQnEZGZRUE!ObA^#&uX+hD^ zncS=7fA0qKn8l1Dg6?Q6hLe$3AA2`ri#?T%oW-W9^T6U!XQ{_iZHRK|#}nvvf1UGx z!gJoX(~q==nZ>Y@%@Sh8P#5N-Mf2K0+}T+q8QkRpt;#vBhsQTuJnw=FJ{I{nFY910 z6=eI_f1x_nOCc5Q^x-W7Q+MW+^@&?A+vaH24flL&EwTKLpRTNm`YZZ-zPEOCxRq+u zoLXaK#)AI6YwTSrM_R2I8KHuxQ9wKrOxEts3p%sem}C^;JhS_ll^mCWf8nzSdwqAB z-Drksb6TWNt$D8h#;$p30BBAWh-csPi3#JDsoo)PFbGC*{kb0+l#of!=B+q8bLJKsrD+F}gD_>e3X55Caq@78Y{lejpE* zZV&~mr0GI$wgR+_93G`Tt1ORBS6GC&0^3q6@PZd5Q0YO?_6Fn8Ex&Obiz?m=tgG-4 zNL_{dz;t2mSfV@_U4=OTx(fdvp>t`&(f?Xpt^%^5**l3m%W<#!7Yc0vb`M=y0=i)( zwliL_f>EEBBQ9eK9;#k9aEsN?N8=vH-|BnUY{w5Ydy~!sG|a=S8pc0RAq#aGO8F9< zsz{}tpvU&()6-AJ_r~HUqF+xX{X(`I8rb8bm2{}GTGV^W>sEz`TS+B?v84u+A~pHy zZLh|!tL8N;V??$0_c?6J_mLDFb*`2)JVCU}tLeOONQanOPF5XEhM_l_oRsmW{v z&gaHWb^QYtg0T13s;H}fwSnM zIF~(nEwSV^(it3o<24sR(j(q=1X2|tS4p7&0uXr&;1K7txdc3DqGsWgc94x!G&QSR z30}Q$S6{HgT$pT0&1OORV8zWzqpgyDTEupb5N0_}$@nE4xe;ITfo?Ok7MhS*Z8rDL z*g+d`Y*1L8pIE~yo;IG+mZGSkyE5Qo9l87$-q;0}LrT!Gh|U#kJKCy5MPCxs2V}u3 zE`xRtJVxOe;rd&Pcd$&IQA>L6v5FNI4UZ|JOG(04RIQ-agBhKw^EzYT$qgGKy34|z z3OyYKS-t1m5zbXCUTB1uhBpOW3Q?{Q;}wZYyGmCl6{VEmiD294h|vbpoC)VfnuI%w z6Xu+d1*K&Xb?OFs!bjjqe2dX+Uf|NjmxT%y;;yO`&<@55h&em@V?DYk;vVE3%e}=z zygTW5kr#{dsm|#TT;__*IC7gF3~HYs&WwSWW_BpF*P^GwOdPH`^7GLl=)Ar~q;E!G%V z%qrS$#YCKEhHcKrvPN;6qUs65*@B3BjSFCV?B27eO(ti()=Kyh8brYs z56mWGRL4)8sg+ESMM`f;6r~VsI4R{_p85UKE>4brR`LsG({xZ`$ZF+J} zh@%gIdu_r(>h>#SZoI-5*mBI8<)MQjNeFA4{Q*dzwMbwFQz@WOht~*>BqW7-*Q1eB zX3GI^SCH3L$?v0Jff#+lqKu%#LXKZ>ngBL{uG4 zh)ss;LlD1j(^{3~h4Z%CXrp0CmvI>-tLt{JV==-q4myfp{J!6FiCwsY3lnm73$b~)kI2+CooX9rU| zx;%;8tVB`BS|QB{g@PFZM#@Dv-Ol?tT=Ek(H}UIF{5m5EvSY_Z5cOWC!~i#E@EzH{ zI<)?G-OBYyx^NunTZu{3ArYd}9C2RMh)czedJfAXrF%2L_RHhZ#L(5Np=9vbp2x~k z;ORzE*M6(ye@YWDqe`PDf-yOGbG%l91n>htaAfgQ$*{|5vg@06IO>oHJBndYK7*}J zJEDFKV=ogpXXS@LQ&QBV>y9Kf8C|)CBaOuO|qTCzu4KW)muCZ}lUhHUudz`ua<=+vmV3bT@>b|}9ak9*28iJBb z&k~v6I#4Jf#ggjcU6#yYjwSQ3=7kI54MtWTPX_MT!x;l|0pv)}D~z#TK`M|f8=v58 zUwAGq1AC~y>_9)v&}6VwcOOMHNRMghUXrQ%2uV95{;LZHtLoBWd*%2cLF|s)OGNp( zy#t8UlyS7r*#C?LdNrKfe3xQil~kh6eMgdKfQ6A$zd*bvy5&7Omr^>ZxRZl2-}T%c z^55A?B0cvy&)X;9u0Kqxp*)X&+>~D9{yP`g%lmZD+?x;DJuNtxSKO%QZT3=4*Ho^} zvAB~L5=mOt&@xlOL938NeAPfvYJ{mpM`UQrZ4vQH8q-RKaHP@r?@G|-!$&i>-^%jT z{bxW4#l)D}(0LAvb8`bK?+Vkpd)ls?i|pmvK5~yl{9?v-nd9Ixp`7Lzw!1C;!hDYC zkIqG|tceX%$g@`pb6N2e?yzF#hc*wJeKRy}x&?oWC${Q4haM$i9{$vpq!Gsq#Y zODi>uzb;N#Npq06rQjxAS!pasU}x&O!uB9z^S0z6Pt4OQ*ZL>ueKlq4{%KC~#Bn^8pnOW*;92Otg?X-SS%f#6 zC79E+w{RzxmN)$ToWZ>8`5Xq9SxZU7F^~Kk!VADJ1Q#$sX=(9%jWkd|&~ zK-&oizOO@wN-IU|xQ@iBGY>|7c9%&Z0yL}HK=N}-1A9&Yc5I*|@m8|*u^G9r%`4Bw@wWp1t%V4f_2l`!7k?Vb{7=8AY7dq4d_1R zFSE5)cLjb)nIkqIm4>U@_Eqfc?;P*!A02P(H@BvN)ItlC3F_w7QS)$zM12SVE>pCe zsi?A;pQs}SaLbj@5l1`wFL$@Z{=xpytBu30&3qN;FkUm#_HTd&M5}W~a$4j6hlYgp z|Lcs#^d&!`%PzP)zf~Qy9PZm`dTLd!o2SNTg%|356sCx`Z3EZd~2~h z$K5Z>L+HOpXp_ZpPZ{5oq5WE;`scZ5|0iEIjg3bkQsDC`1>$f+-i!?WgAzQq%N{o< zYpwS&pcFRmzjCkkqi|XO0kYNyTtNRZo1bRrKTXz#J`FzVH_lR^_0K3W3ITas2O}yny+hWZotv9TDXm>Jc|Y*Ax_3L*hKk3F_;P2# z3<4g9ozLSwTmKCeXZU_OV3Wg2nK;O_;U!y{tm9BebT?is70PVb(^c3

4!IozwPL0)Xvs&BGpK~( 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Μdbf%V#}+doECxaQ(dh`uO1W@y~y*>Z^q+%d>d83aSha_o&GlgujSO z9_Y?I1wuQvrWlj(N|!KM!|1xnS5zc&pCs!GrL0q5yIQi4RCc=Hbon6+m7QIncY0-T zz}7!#z0(fT%rsWdGOZ}=Q1$hAe}AWAWhwMKQB`sOa;b@10ZZ3TIXE-QGDcT`-8oo2 zbmmP}U_NS+{sCTXPrEfG-M|^qxc9u);7z}l%f_0?30|YBm|h0yATuYk;Y$agIkALg zYW}6SZl}^ys+igRa_Tr+jWWAsR{KxtjA+vwhLv_F_vfywyZ}qHgjX`bmF^0yG&Qi2 zGOx57=f+k#Ddz=Of-Xx(#u?@_wBMv%Ie72cKxe4#)xu)EiDA?c>YU*Ye-Whxt)-&_ z=E^Rm9lI6n4^V}>_KJIKX-*-QI*z>u%(9tf)dx+XP)xq|peQ&#^mb5VgVpYk3==

JoH}p#17MR)?wwX0MkM5tEQ@A+cmJgAT!iA6Dc#T z_&^Gt*gFy5Dj_gcg;O@$!}G;|$w+_c-OzfRhTUk{~y7LJqamoHZhphn`(A6|EL8UxE0c zMQv{N(#}x7Vsd40-*c=MO+{h*A2jJx zPCRkjRd>$FRwWnVXhaskc|5DLl&st412i*^$pOo)6|9=HFVNwte|APLLd7Q`kWx6s zhEdEH&HzBHoCfTm*<6pT4%J?yO|P`8JCu}@_alV+3y_u1C*>(5ul%tPidI8^+?foK zIN=AfT%@OU6B85Oo_e3@|LLC4PARE&kg-FC*6YAG5|okb>u*!*npbjunMsgu-^t6+ zls2WDN)D{d-x;c)?ang$I9j@W7+v>1WB_Z~U0;*MR1roXnZS(TN}_kLarr~eLLt>y zU}Pqw3fn{ZG|c6Mb%&9M@p|ZZ2nZmm*A`L6k2s~T!{O2*Z~TaanNwbICP~eNs&cYiNl7Q4jF;jGQM*b#rcyeQRgaUj7y{BI4RJBxdEBJu* z-&rn6;zI3Rd2j_gbl6Y4>sG{-4{pZ65cN@$%+0TnHrAB+Yk-km5ze-DoKkzC)~50t z9<{gubh9DlSS>27nIi`^bpmQmn9+ne>jBv-!~dI3y*gIKGI7bQY_CB`uE$fH}D+z_cV{wFzYm5g~Z58thfts-4 z*!ZI1tgO&S8yN9BsQW~+^@f7gGImr(o#&$f7B%)`G@ml{nfC^GS$Z0nP$RTwlOC$6 zTqIt{(OMy(TU9(11;eW_j)oY^vzZ?W@}qW|vU9w-Nq=ALY`i@38j~@84o!0<(f5|{juclaDL|f+_Gri6y|oOy*1J90+>4Crg!5* zr0T&M+w@60iDHvsRG>$XC~=Q9KD!q{`kR?Rj5mBKK^_}!Xq1hgk_TpN8Vy*hy~$wI zkm7!vwMVpzRI_>%(qVKTG|Cy@=aLRDsY#t9R7s5kC*Ny%yA`zYQZIUcxv^7IN+_Ra zFxPMu%^!M4K_J#FN;t-5w6M<5zzoik7qHS$kx|9w(N2Z?J*9ujkF0k(lR?wEZD*#9isgCh3UhyfwT?p zvQ~YLI3Z;UqMhB~b%xag8Ak`oH!_!r8V62)Y4hvYvYqLIAc6o5*ZKaIIP%EzucEMLoFwbY zlAVIKO7|4|DVBZ+JfQ1bWx#F)L>s_admO~qe%wpuy`XvCoaca1rWAx{gDXARFrI02 z2FI7|AYzEqm{I76Q(_=L9EWi*zGX;dt*KD5>E)2Zqk41QNsQ)*=veQeD>_Ewb%7PD zo;lk|ybMZi%mJH^FN!yiV%^KebtoJZ5 z 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%0Dfdu)gPI8boY7-$VQq;4PKmG^d!EWU1o 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

eCV#|=f@w&umW!rUqTi5 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�dS%^A{AYsNlehCLJ(8`7z~jlSwI>}{rr@pYp!U`BmUk7383c%t~t zB)+K^y3g>-n+L+H>!SWT$?!bQ+DWkEO7K6Gv1+x!6zFL4C*i4=w6*2(B!_Bt#P{LFLa8&w z-c7XUkKe{$yiwl&80X7J?_l3_`u~In`F!n??tS%=I*xwvHk32$Ajb7zKY~d|Km8-+ z(HVzGn6=zZ^ue27NhyNOJqyHI_OCpNfzWyhqp8S-Rc;&D3b^RW;Av?F|8iPDF{d@nXdN+eH$ z&@ca4>>EUnD1p*qs5*Fllt^wAI+iRzU159`(F7_b3SwydBmNiJwb|t zw`ZV|wtB1Me!Df>0U_sJ+63dj_gBxmTkShacvm6(QXx1$Is^sOt}I-DDRz!0JXPS!~P;|e6hE#uFRFB#JGAXc6fph4i<=^2F9F^c+*LPf|G zRrG?TOAafkWW+-0W~WM+8977+Ct;FoL=ZG`neR2x8bzjPIb>qhC=EwkVZS(G5M~x1JI{B|EN%)s2w$D*}kYPls zjMC-RsQlB_$qM+trP={O7IvzOtNH-Lg8K($_TS$_4^QS%*Vj5|)F8p>f64#Z3h$8E z;=fUvzF6M~rl*q(yriz2jG^WW_`ScPZ~E8O)$xCte7$Ma#Ne#>=EY0>7Vmv{qm{Lsn&g{uGmkKyB+Kkt$II+&*{ G*#7~Bu{v1* literal 1900046 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

Ut4S54R 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

-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

+=ez>pkA}9(BF8{yWXR&_dc&v9pR_^(AHLB|q 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%0Ajy|jEdwyn*(wmAY+E}>8!C5jes7` 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

    @Iwo&x+@gD)`EK%O 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°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 hW42#cm91M^17&EaqC$42 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лPWO(-5=Fqa;n9++(GEo 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

iH=`098&X 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 z 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 nf07z&n1PENz1 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%0AfT^93gj*8P`aT13IaNHRR z3BauCqgBAE^Jge%)jM0peAx%N>uy#kj>?1{aSM|k$jj0LS7@BYW^#e?4H5o06Qv|} zyGZDEk;v^Lf!jsmwyTqc9~1lbR(EaW%9r@$s8tMRJ!3!;WXvIyt@KV9p3LE(xj^q9 z?ejg*Ayyzd`5+dhj6z2p+O(spEP75tFOCO})CJWnmn&4D7tcu_KH`IM7e0&O-^O;H z$MBrNbN`$_r$>hb_)JKtgw6^+S;NY7815YOGi8z+co|`##l~k3IMFbLHksxESx49Kk8{Xv=iqEqzN zAfkl}#D(`mGCUlLc zTIZ4=vm0F~iKxqM)fK=UM(BX38+I|tY`Si?6)#&IbpdY-0EUdEEUMn_Hj&v6`nr>M zch<&bi>lk)5zFicTqud?gxl&w0CyN)PKvtUx|n44f;qGCMFReJ2XI7Ye-L#Rpv?X- z>eYnu?yTETW`E;rDDNaGA&NlK@ti});Bz4Z7_2#f(+=R!=@7u7nt4Q_aqSTBuKoYa{zu%$a{t z_Jo5`Jr_6{6`6m?0UMOr$DIM(d`s0Rzg#6ERcoMG4CKZ+u8tDf`uf=xu>@>!07qo@ zXRfTt?AbZq**F{MAw(!8`YjHw!7U+l4c4Tq(*Ydn3;`Uf37B#K$5J7H)ob%^(duDW zCS>*}uJWlKbJbitC7OJ{ws0L5RbTZiiXi5&h4O=n8uPH1~Rv|u*Ce;q5sM{Q`07qo@ z8K-DiX1_nzJL%sK^e_uutDPo;t3&7-tV!3!4&czmA%H_Q0hc*|W6MGSt0(<&QTwI2 zH77#ietNFd=M8UGae)ehkXuFNp}Do~@Gem|Jh!%rFh$+_T_R=nX{YF5^~6-Eu?GS( z3Z3l?w)qQDcbD7QT~(bOt%Z3uK8mVK=Q+|Uv+tfatF#KhKe*B=vv~*Cu*@Et=ap7@ zcdOg*){ss|YIZu$0UVqc0ytO`u+ae=Y77A!y8qn#84Kf2wG5An+Vs40@;)=qBd*5+ z*h6KwC%{$^nUP?djiPR+OMuK~oT7ul?n21yIrm8Z=n1_;)IRNspUkd`%_e>l@M8|( zh|Ip>5+Sp1`iPKsD`HMVne}#Bo7&T^_?-@+cCaSkDOdbXg#Zqn2Y<%G_){%@a*Qiu zHT90fePL`CN&As#bjF>0nSI@rqVwqO1<~YX7mkgMTMP`Ca0APrzgPc)+x>nBN_!l2=iF zxwu{xFrTS_YCb8hpQ?dxLX^KpAyQfQ6ijeads_1DUO{sC9pChdbi&?5Bzd*-7av~1+2Tg z{xU#t(1`3|^sZ%x{?qgQ*LMc!uM1r9DC-X%_{0MLHSXbCBxL+q&)Db?Z-M_hJvW?x za{NXB{@Dxt*Z0@C@Qoqx(}FIkOb3?vuPe_n|5gCLyv%?7Qh?#jf$KX1@QD@vYrZKQ zUjDr|0Do`b;{*-op#OscJ|(r?8vixurNjbqbf?Hm{@;70|N4n@^nWq{zx^uz^~JjI z{^j4p@Na=fKFZ?T1Lck3?SuE9g?|e@@Y4c*`aI#kEa;c;w+i@M&lCP@0eJaUg_8pQ z>S!SH3BZ3(%)M;(toUBRvs;9>Q0M1+EFece4)i~Ly%_)XVmvkIm)HLlfM?s|u3|#@ zIS2eNgYaDfzDsyte>?m5Ulq6{{2B4Vgfnv@zI9$p{(dX^PXuEY0e>9}*PrtGW{6HD zZ?vA5CfMxycR?f^ev5$L`9x$^_?0!_Z+(hS{PMZ8_kVQ__t`cj<#nOaXB7T>zAmhMj^j`G%j+FK!CyYt zvH$+^08v1$zj=;b_m{^Ud+jf8aO|+ZywS0*{_-ZrZu-kFaO|PKe7y3%B#l|AzlCKn^k(5>ZjQ)I1fLp8M01s7j6;Gi}*&TB6FF&>SYf*kpG@PDIHOdESl#kaa zpNZo9E@$$SUeew8U^IMOAB%?5|D>Q_e$~Dp=Ia|Z`h6kl&Ykz~4MER~0eWzE6!G60 znD@8Lslgx7-ucq4^ta}Ok889>xlyD119SMgkl!wgi}8L`_A8k58yV+`a{0MYNzWGv zf3^MkyBg#AQ4M;2Q=`18p7$$1iup-Vez7Q*AELcolqc)M@$}RvAFL0jvm)>(0`v9$ zdOqIQ1LOTr4g8;|QT|Mge*aPQE5Btg`Tue~m#dcoa`i?H{0rxDJo00S(tTVxH@y9o zR9>xbTLd2YO;1Vl_PLy%R|515*1(?^c;x5We=N$6Q+bG=nK5n4uHDCu&n0%ywfi7H+5Ppq)1V+CGmS7`Wcj^sFi7Y9YaC0wQTG9WP4|LBgNf%b>7B` zo3+_Wv53DH_1r1$j;;JbvGapyB3L zAArsB($T7y#FIRP{p>g7H4*%kAltX^?(5yrt)yC0t?S$uh17hBPW2BumEMv4iYw~C z9h7SR<|6+)#j9VL8~Q$>8ZQ9E->~|rt$GDP*efT9yl~>G-fC5Y&5DwlR*|*zOUW=A zoL|X?{id<@+pvQ_=<~eTwC1}$XZuZj;H8XJZ_f{XZ?U4JEzA8?z5g{THQz!V{u-L9 zR|bZ@nx1_oQda3W*lE{3&IBtwYYdiUTY(??FV%nFXgCwptoC4*4kLsGvXK9 zTd!&b082=0>8c=1ZH;ri?@Wi`+T z%0N$dUp(2GY;A9B+|$*)ueX19<5vFH*f^307dj5EXWX7D#i!I6D{hzK{B;I#)i^KY zn;ILF*TiQ^m3Rgq1T3!SaYq~B>!ISR6`#`WJfNM4m!RJCliwJRH>O-X;NrwH6?{W6 zhX%3`r*Bka`}^YD)dHm1xT&?66(e5OGKCiCn?@H;L4{f_n1;8a51gh zaSC?z3|E*HoBGbHlUh6t2&afEdDZ^E>^*CD+cvWO8vY8bZX3nBBK4M9S#~Q+OsuoE z6?p6*QC;!y*!;8A$Y!Bx7r2XqG}cR$PgWUCb`eU}Qn9 zNZA~SHgt*8U>n!g%>u8_HPcq4j*fbQC3&_vpBsKedxCkU?-|w^fnLT8);AbmQhs5L zL_&7WkdQ3TsJ#He!N$6&9;4jQEGkrh#H84z452nio96pip>qv}0EB_E%{7oO$=(Jd zBkdjc4|*WLWH=zlgZ{4sqAn$r=JW%-?+|{I6{8Ip6-!%z)S>UI8EfN#q3yqz5r$Sq)EXb4}=A60(LK!bV*O+6}y! zG*x% zay{Xy%m&HEgQhafWt`Lq-Vg~P6^RZh!p@1nb~uHOQ*!*kiXJ^ixA}(B8`kl zs~yjwCInO)ajtDbPn!#S*a`f3;7j0k@;h(dAUnQN|1Z2__nus%X0v{4{DL{}5aVdNt9*#ebDrx&B?b+$h(Z zB?tk5h2?swD&~J4Y5qq7uc<{Y{2922=vz%MjOk@ddi4t!S!$bepT2(seo1fG-O7<2 zc+G92xwD!5WI15pec~DZHo+S+NOc>$I*CU&%BLAr5dQ|RM0!Q<2r}|s>lcRLmsV6s z>pV}|X?U`mc$Xw3wnZXhlXm1qs-8#2F`(*RRQD8QE{`XNH@;W-k zSz)n!+~e~LnJx~?xIPP!^BSPIT!!m4LK%j`OP?|KR(}hV7epdyN7=lvC~Ue#d{M(kx}xf0|WL17iF?!qfhnI+*k) zCnPJ)(K{KRj3??L$t(Oik{A+9LVj1e6-9JG)B=hqXB7&Zz|0ngv^8qx)8|WSW;v@+ z+^$a+a7LiTEa*m+xEiR7i&)FuT~8KzeYL^)#UyJypKu(_gCP9_5Ogg$wd{?tQ zi|(t!Eso}yIVHMrM(=M%g@ik~qHTz>oKRvv5KFVq18NeCGmnxGs;`I=!!D+v(96v) zM-tU?Cz23~Ba(hdq2ErthmhO6wQn`c!b>1=N0DluTM*&j-qJUwO{Tch-Z>*P(_@>b zII949>rPfEd^jNHRcKjK)}DptsMqYY`A2%1XS?k>HpF zI}fr#g$TwEUW{lufoI)N+JDGU3@l02A8{k_op^_BC~OqUU{cxdu`S-XE@I(t(|uWG z|C#gn*!#a~b+P~NIrV=k_W1a9HiKjeF^;vwfKaOaL^v`FBa7CLHi)}etH(s~!>yhXpGDa1A^f*Ipwxh=?; z8!q14?ek2DwBxxb+)9Q@9#WVd&tsD9?c^_ff8HvFUZmo<=S7Hh`74KNeZsE{BiQTf zYvsC1LCZh=^iz@MQghJ;(_$IBw1#$(y+q0E+}>0sPr|L~Z8W&1?Yj=OJ8jRPAu=^h z;hYv^GOI+*62-t$w`n4x&~_#IWg>kqvIP2*3PRR|=IzhGbm^ta-a=hGQ%_Y# zU5z{HTWUq4>9p-kHuNuE5snjh+tMwJ2tR0FMj+2&W$!Gkq`o)jsKOp>Tl6|{Yc~bd zE{4g8&dqQFo(>7{JNQP8gq2AgE@n`cLn}#*KbXIR)EMX~N!87B!}C|snt)oH*mSY` zq&Ys#;0}^wp!L}c z#p66|U&inBTIEy{9(@5&{LR-+J(EZ9LXraIt1PY`V(M`XU~av|M-42qcLsJ7mcuFP4ZR05{m*gI(I&kUQK>9ZYp z_q9*()7q&J&qO#dzR(ZXJIx;{G-dOZ*&@ETQzqW^PFX^GEaptVz4$M+UU%R7Kg-oh zBkTW{8&%=|e?|WPqNR&O=0QC4*i}p#rq|JYUMe|ZBwyQ3I*XgcqyZE*O4ul&|Fil( z-Zk-g^FOz*|CMVv|Cd_-Yc?8U{qIqpTSN1;rw>r2Cct^LpU|hbPJ_?`8%ziIuSTK~Oo{a>v&8=3Y0W?7v7A=ZDz`mb3373;rGN2*v$6>F)& zD}C8s>3aTO{PED^?Eh@kt78A>v+Vz6UpRiD|6eI(&;P4bs^b2Kr||!C;Q!}h|34S| z|GB09e~J75g!$-rJro+~TqrLK-_GWki3DJ@gt~dfEhtae&0gq3EgsE@;N~pMVE#Ah zbti;ElL$NnV8%F86=Fd9T;>Rw1JE%X9GJrsBmZQnO^7}wEdg8u^YMs zB;#DtOkVPqRwXh+lq`wfKeWs6dtgWH^AKNjGtn+uCFXyy_YfT`8~P_pDd#@Ut0M#G zp8I(Ae9S#^s^PJW;A8<;m9(D|F*9Nwb4IYsg)efuFCyF#@w_nmzwG3pFWLW9sWmd| zKb1(wQK#1*?-N?!i5-E|cKBtUz+&Sb+!;vWBhw4V zoEkfMXYS`Y@-xfP{6*ZJc|Ow~3i-JJ>#VHU;nvgiL(!T+ic0#<$h z)ofX`KYa%3 zJ;Z;NT6H1*tBLjB7oz`Taalw8vt`t^;y<=-`TXL)WD~x+`0w-PTm1{D^WtG+OUhOe zTZ-6HJWm||r4Dfa?jG!awX|UW>s2xT`$Fu0Bra>1{|I)a^{0?eywscA`o7E)NVMkZ zmw1;NZcm%dE#o5|>-#VjOfNLsHmrMGi;X)zj$ltU_mX&EkPP7;2>(Dlk39domi@1- z*#Di}|6i$8nqvQ#nE!p|^S?=7Ao<0fm=YG2R9I5+yiog}yc}+A(|GsyU$t!fU#p1o z|6hpx55;8-(;tGawEEMVsbx+H!auRyk3TA3X7%F+JtKo3aV@s@oS$>Yg3>cnv&2NZ zF#qBa_J4!RLqFgCmuroT{jcIDVZ#2u2>ZW8T-I;}cqwW@KeAFQy#i|3o@hgW=DOO= zawlMEQ@*jC;gQcFwucMPLOfsp`u~0I|ErZN3;X}7bz%Qs(E9(n`~TRI`da({*h290 z+y9qr!Z))2?-WeQet@ZzMwNlNT z|6gy4@4ueH{@?HYUx_HkurQqSoBMx!p)e;?%`x1Ttj4&JtQoG33f{sqxTnQbYP_hy< zdzjhE0^thqO2GItxozn=jQ@jvR~?Mi`x+W|%>OhhN@iq*F3-Q$(!jGL9dR;q*5wXqhjw|CzvawV_Ad( zdU*c6;a(ZKBHa(k(#XKUMx838O9R&~@C;(wgzxUa6c`ekdqd6~cjgtywdr3F$EAOr zz(;S-JTs@%#VrtU7w3kH4xgcux$EGF*1=cgzT=r=Sg_TWVSZLL0 zIte*(0*W5($`t3_=wP@3iB53JaWB27uc5_%aI46A5tYH|4e_)al#bk6$3Y1slwQ2! z&CqB>hHV1?hQ#z~gMh_O4tp;L6rI6u+V^!Otz;;H^WYSu^8!Q~Vq4%57ckqn4nt#) z$9=2@i)l5^aFAA%7yPRbRhwRfg`f$bz<~AV&^;iwu{;8;0aS=>3SsR4??~b^k3*Y| zdB_85=-3A*0x%)x8Lf~WK!E2GjnE53aAwmDkufAZQnf-Ae8ang1(sC0Ogo^oQ_bgd zj93W9)XYnufqvt-m8e@`%sDuR3t?c0!waDGNxB(|3|>U3+0d)Osb~BdV1ONRAx$$Y z9k&=H!B1O=fkPbI;Hm(~w9^2{wpfcWn**d$#eI_?2t*&M#2_BCQ;eUw28gbnZU_u9 zZrK!6-HoNH8=FYgI8ouxM)E?P8 zA(MTTvahGUR}Y3qhw5NLCTi!9{O3QNF#zZDq%-IdsWUhs>aRy5bv%ZG!x8Bp9v$@I zCm35G0IwNv)JUSYVRf5gw^~c?VPXAEtfdc9epiTlU zfkuq?I|m10^Q495VGAZ>(j5*aqdpKj9F57I3gmY74pderw7AzFsohC|Nc}W>ki&#L{8PvXEJ2je~$8p^ZoK4&-x{ylk)laz(U+niwJ(-D8=SOJ)9aFbBE z#>!x(fg%CrH3OA^^KvHmDFM1H`0*+PlGa(M_+r(D^&~afRI{lSXFdUFrz=w<>I}v` z&Q4}r1PR;=&~h&Nv#5fY-{fSqW9WZj3h0+VjHwT@&AkuLFqY|%U4?UCK_MZg|Hmm( z)jl_EV~KLod?|_XzW}UEof)7MGjY#t{_m1sp{tv&_n`4VyZ~(asJ1X?f=1*KHmFrMg=zpu|>Qb*Wef|MvkTK>!HZV z2uod1ww&i{-sK&oXtrEVm-*zGQHjI?V5L+l7k@oG7*8*ZnI=;W1(6aj>6tB$X5g}% zPsv_csk9P8`Q+)+8ckjY265%sHL+~F5W7P*+#uBE$7Sr|9l0Tnb}>w)<-A}v0|z54 z8otszJ>JU{T_4*nrcyBl%)8F_K+&4jD{w9TiSe`H#>7A_M0D>8J>47eRQoedq-F0vd31#Sw&y}LKK-P^OOhhcqI|7gqpxM`{nkgXM6Z8^N(Pb7fXr3CWf=bZ@>c&g*Jr zO{CNLYNXH=9~tyT0ybtJFxdBU@hz`OG?*9TNnhE9qtTBs-dQkv!^HASTx!V&7n$OqXv|QTg+D>hMq`dC)472=D5j?2MVf=% zn;oG6tO<%{roCGOC0}Y6@n=+50;-MHfjicrHjT=b6)3Hhv!xeHpw@~hK@FcIm0m*5 zroz2wJ4|RV7BeV3yuu(#>cVz(wYNh}2OmE;DJxT4Il^~~?Buk-cXY#t=rKp9%IA>A zFKJ+ev+xrb4Iqwt^K*_A8ReOJrFLj7#Ws#7_W#|$mZ`GDq4R+8U!~NnH0#;;uTc{I z|D!zr_c!qCT9q+$dQHAfW|^n)RHl=xxf8AYc1U^0gh+px$k{E6C`z4o!U>G{hX7c6}5PSUhN8Q zmfBT(YBDPC*<`Sup07_PM?oR|Z+zWeS*=e$Oz*fSKAD{}(r@+pJ<@l=O%nsdVLGIe z&Y2+^9m;QKLsk1&Sff+Y&-AAY#%Pta2}(RW*r)&r`z6h(Xcm^#T*V~JCDASRS^C(& zL|+wPfCks~fBpX2oJ}uAlVsiO4Ei0jIY@xXjHk)FYx6yDJDrYp_{kmS-u^q7z>NXB za<^`t0?!I`TRZ_`e0-A>PvNP$<67zHvPtFm_MLZZ>->FwwSkK}~zx&P{#;74o zkha6$cLSD&b<`mp;NfU=IvN0XNk8w`ud)rip~v|2dfgmN`{yui@7~2j0Gpgzn3cQ1 z(hdH#!F$`Bp{ERL*HQ6s*hwy7GI!%iZ!|fp{EP9|a-#ruh$-&$)=fZ1n6Fp<`j@ru z3}D#R+R7TR{ATqp>)(F6{`KGfVb0<~e;k{lR)>iOuG@4kVpuw|$4G!0Wn?x6n$cJq z)(qpgr|MzElO*pz+-0#<9eQPUc#`7xsB!L70XVi*G;Kf|Z!?6mYU0TRbtiF>Fk&Rr z1;k-u$>ZRob|1kKzL^cJr9>ZXG;k38GgE$Gd)Xe0I?&5<2|Hh^RLsZ1Qrx{5neV^< zes8~h0K9m6`|xo8uuypXr{@3DoZa`p5P0}pv_n79)rU(~OJ;pQYQk$I)_TKSbO5ua zmcZ7I37_`r=6EFEdD2|bxKG-8WYh4zA$t(qxLBL6rdo~J3}~S?iO=H?XvNVd1YaT} zBdXZrE_7g(wQWFRsJFiy^=1GV=Np$96=isq(2HgMxc}Uo7lIYsD8wK7(~ZK7>;bj( zY{O$X3a|wxqi%ZyTwBgQINaZA?;mXM{a>&d>@doe@U&^|12JTxGu+oJI-wmxCvZ4# zWxmLQgj4CQN~2+kQPkf~J40094nt)nsdT@suhsv`s|fsVe+UN{jf>hpZyz4*?C-UA zo<+QbXx>&XUUvRDnp8~@Sa|w8ot;-q6E^>N04#Djsz+5EvEco3rE0#eY!sHT926@9 z9;)E?4Ff%Vi3TKORWd>q@;jha#$uW^y0UjiQdq*?5rpr}>I!v60Y)qMC4v@U&`Ugk zO#iDU`p6x>S^3C4zoBZ_Gr!Ku&HufBs5K)TC045FjJDg)b`IO^U?;GN)VFms`^0XB zO+$yjUHN*2`z$S$1Wc(4o2@e#ccvHRUVnn(hjP39d}nvN-L6!yYtSV9e7du@dH8E? zvupLg@bu)g3!EpqRH7GX#d1F8PK9|o1q=ntK+RYbqP*Z`#heO zODI{dYxxrF$)+ilxNGpHEwY@pmS`tf3Bb7afU-k#huH+3hnz5{P~3WTh)V|B4O;46 z^~z8ME1=$ju23|N6XHZT8e6;07!oSR!}sOV@%GVi8>jK;a0@^RcKoq>0TmV$(k?!W z2T%qYxkS1gx{3tEBu1a#9$ZH6`;*a-{JE^lR$)A2phrhPwYPS6w)c*kJ%ZB1k^65q zUmgF{KHA^<`@90j$G^^dwY9&ux4nh-Hhzgh5oRlxHkfrCCs|&by%Ri1z+rad+yMWvQg+ZgZgzyl?(H;PGHGqeP zuC!72#w zOFDRrE%d53N1M;L+b{Q@ZMT2fJlun$`mejHrGW*PHD0!8mx&xLOu~=}*5K+U(kim! ziOlvM+O|CdsGsJxeK)DhC$n{dir9qOzvvUk+(CAHVd$^&#+xD zMpr~9SOIh|==FmyOC}UD%cy9-=p&3Kpjg~)#rF2z&lU57p)Y3LP~fMsY}Ybcv`#0q zZTFAh4#DdkQEl|g&R$e8Uwvib%klKO?882Zj;?_@z66eP8oi-iX3YEoj4u$g_>Ub5 z91TlTL$;>pGhkv=7K6w){s1^}N;lU)ROEH6bI3#;Ge;lL5*A3aWE^*`cLNpMN3#8@ z57!GyFz8UB>;s9CIGO5>yMkVylO*W@%po#;O*5Pg1{?IF-97Ky2l=Rf`}OwLt7F`n za^wWa!h!&d$sj1(Y?e?XQ4&gsYZI!in^Gg`jQfr5ppWuSK!8h2f~TV#xJ|4a5paV3 zAk&Af7dzPwbE7iURKw@ga1B071eW09Y$rK(R&hagJ3+xyRsN{TGEh%ddmh)E#PfqQ7$ zA;|(%LYn#t_(F6!%kAy6?c+`07@lcg^>^N;cV&aVc~w^O`-Da}e21bPCSUL9GLg*h z*Q=v#C7g>`z0EX_WkOB4R0XneUcI1$L4AAG(dGDInzW}Qdg;F_BIShs6X+=vyK1n9 zN=#X{fmG-X;z_eqrH63!w@HZE*GKlYZ?5nI5gD|t$E?<6fJ|Is#ESj1Gk%jIDw`$1 z986i7PiDK#_UaV{J|1+g+f*fKu9kwQ$+R<>&c>;?xT)lcbn#+(IY>QXGCi!wJ!)UZ zmq0wfOFu?~Xkf*F_qHP+0nvZfp1>X744%OJH|yA_Ki=_#2&p!+l}-N@I(MbtAfB~# z5HtDDrGoc3kJ8qD_RojF9pZ$Ow@hj#pp7mC4QZ}^!%u{p)hHcp8*^mmXkSB)1O-{< z>dL)3eqQ@)SVVTiq9Vw!bKiJ>y#mhZ=gr-nXKm+Qfi>_}vY4KBa@#YcFBcOaQrkHD z0p5oTs!DjSYVQpBhLz!~J5KN;JSbSOlO%1nw!okM34@=wU)m%{gC8ko4sRPk9WUZ3 z+559x0yViyMf^>R2q#emGOu?sI2&Sgm9ncv!YLgAB2dy03v*W>CVcZ? z2PyG&6B%Yk=}A>yE8oViebE;c`N#I&GcChK=nRB~n4D&U-!%hI;H9Z4;P#AUL|kQO zZ^v}H6z^QBSYZ-!sok^lHe9gf2*1#sjIU6Vhm~KVprZ~T60MxMJzFK76ktNTXr0Li zC25tAH-JNiCt=X(#^nf@+-k&9zifGAl%a)XRwAGc&EyhgjAnTm?n?8+6I_*~^PY{F zymj&R6)h3Hpjc=Drd|R90r6k5#*ea_&Z`)d=SSuAdw(yyCDJ(|Iu9I)<`Iq5G*gamZIuO`t^Jmlw{qaCs_HX0L`m zqZlNF5OAfW3hf4%#kkYGD5vM7lhDnCuu{kb-tzHd`B_^q4irvZW|m3LCl!G>nw-bE zs4CsuhO)AYHuW!9oM~vX@cc0Ko#N`Ee2WUrFY&LCJ+Apu zMke*~Uf8hf0BFyn#c>hvTN_GxQpxC}eR|UxhC({l0qIzQ=6P|rv-eDIR3MH$0t3Zc zX>swoDWNPEgCoElSN~%36%jk3Hv^*l|JrPCzXY}jl^(x$YD^j@KO$O6)J_QTht`4e zK)k)&IU>Ew!R8B6mxyiA?;UGebUNz~dPMS|+7gZxQ9S{rN9YY{L*N4822bELB_V5{ z%r5l>?8tut8{Vc$?%5e}khD;3@y>uVC96=x0X`?5uZ_3h5mXTMiKQIn@XIal;Q-pt z%jTEZoWn|RJLZ_F$q{luB!6R$aU^z0Llf7?&pwWM0$&1vukKy-p(D6S2wyGXgAKoBd~>4*0i5CT>T8b1Ys3;BGsB0@bh zOTo`j3f>y31mARlKW6T~H$t>+&D}`ai((4ful_V>*|RF+2oPv`CP5ooQPPU2B2EWI zNZ|2IN3CIptpTmk2iBtopxdZWo797Lo{gwf&=r4*hNG(=%*n6A7EWf`P!8S-p;7=3| z8qM(3O7-XQ6s`$4iC7=FAW`EbBVIx=Iz*>#s}3M(BMKV@#7nd>fI^)~_X0O4#;_O+ z*p!p84P8G{`bZHB;un6_P=R)K(o~uqE;THY$fS8H%x3Z~z+&RBVB0aBUJub>)ecOK z74K^am}4Qh9zB5d7~(PNUXJ|*sp3+=MyuSusyYP43u4>?^9L=F6;sefI3ML-@u~c_ z(O@n+!*iTW9YJ3dWXJ-Zk8t4(1v$EI4G|ukcOuErR%SqPLx6;-$SLy9k(*uaM$^zZ zg44A2O(nNvz_I>_I2`px@EN?Q(~I7S-gp26CNH9Y0VZvXMXJ09yt8Z+k{kj%?o7+2 zCal3w2}v?-psvUZ?A>Ch!lp^ondT(4)95?J-cypuPa@7M~tQKaqnug#2GQ? zQghyDa6;-{`I8a~F#t;V5dW6mY}^492{TBK@7EBNpMGIoHGRec+p$`@>**9VT} zbKt{*=wi|}jN4|~na&XBM_e(=(R8^o$*hayU9@;p*6lu&c1urR?d(1?+j~Fn9PaO- z17%5GF4$Pn{?R%^5s_3~L{jxYBo&ORIOw6(M-iz8R3G7Y!0c_{{HCK39>=2hRjeJ! zU}LYb>1hpfmCX;VvYF=va4OIWSZ4Fp@&4BS-g6=JsuJ{RgM%lbUY8%0v|pvV;Ljyr z&)|cy`c4>>H<|=(wMmgQrxwn(sntZvSCVZJtmiy{ws$%83p(OWj&Oye!K*+ye5Bxb zUTbjIb4?1*@EW(KPAEaOu>5{#4_={Xzy-aZVp0JN9F3;IT`!@HPd>C&SM8(p=(g8qy#Ywa|5B+BwE@DadXa!;R=Qml0|j zlxpTc%3oVMGshDSymdJuhWzpp?z*!<=R6^@rlj@kB=9>G#guCAk-Mw?On=j@6uaHF z#RDrcU@OUBNSjB7zS$u&QDt}P))w=(T*^FY^y2poRGyo)Ctt1NkZmK1&S*-#raf8# z`{WLA&cR4EM{OwFC9+wPA2c4ijUnE^(U-!2MQ#D?oT?C zew@(2d%atV2lRzl5&5)}USRpP0g+5fiPQPwvj2MYre($uAmM>>J6iPx6@9+t2tp+^CQ<`j(O_BQ!vx`-l2Ky4P+$U)R9}J7zy!7bSwjOZ?pS{J zB29n03qk}*PS_13s1oPlLlG>64@IUFK75_6FE-9VTiKjMiN^U%fQg_PxTYYve7h$x za`(zZgd3Bz?aZ5?y`0m2w9$+==Xs)by#DbJi(h~HG)+LeAZ_Z;Z5v5lGz2e~ ze!c9qf9f-hh8~zDvD5P#VB?Yyeo5cgQH8PIXq2*BxKuy?gN<);B|17jPZI4O5`qz- zM(U~bK&%Ymh8efT&OCfL?M&d>O+B1V255cap5g`A#wm__?%{C6=FYBZD0p^`d8$0( z1kD1FFnJfpBw5BH;bt!-@A_jbg0g4$AfWgKMus26HNj{6!2|OmvqG-smfRbFbd3 z3>m-Mep=@aHPG|ls!|A_RSjH0{b{*m^30f|OQc|=wwq|HI@Fe}C1cQ2R3%g4CnyQ} z$P)&8zTaHkFvb4&^b)^4ek@(@C+*~_k0LiWPe48EBjL@c&68sPO?9=p%A!n`c;ppX zfg&UutTB^E*7nc|uEE{X`^q+N$%osUR{Fs2ItoL)yV*4rP|o?AO>a+VZ9IYtmw^&p zPG_GBHbZjwwvFfrYVBh)0Ek$Gf2Hc=Z($yvEt0!xSz24EZTorSq!Bj@S0OvMA#7O! zy9pGTARj{YbleINMV6*CDXn|I2J&l(??;jjHc2ictN!>gtb4$n*n&AL;ee><%A3|A zP&I&xL#q)ab$XA!ur1s7h2 z9*B8Wd$ww*u&4Q7SijL=2p1&}T&;$;X$@vi;ob#>5HjFP_VNhouy%OY&2mZ|;WBYnZq2>hmx#aYT2;z}g)0Wi{sDJW9vs>h9EQ0>eCC2*&b(SujE@ zIlj;vP>NmjVcl&=Qa9|32k`bmy$|R>x?oO69z@TfWYI?XkiR*O{=Re2KHA;?g=H$V zKUU{&>#N|JR**pb2zAR>1-YG`q5PbQDb+J5m2CNxjeNSR=Fwe_Zobn#BKHU#sV^zW zrLG(`l#(^Tg`hdL%MMIs{>D?S#JVRzEP07jB??ZlTl|*f1#LOKla_W3>6uMIe4Cq_s*#H>9kAY}Z(LPB;a(@aKOzHTi=AlTdsh^4}vvVW5!CW)sdc6Z1>w_6CoK z8Bk<9V>@BTR;Knl$vRrP%be7%!RT-O-2*vnARK8nf6K5L#?R?r!?4gJfl2VR_c9 z2S9z`1Bpv2i;6o^Qk0dSjmVY;f!WAEc4A?+Mx*9wXQGgLiy)DWsX=cN%Jzw+*CArWKyouv1Upu)^P`QU{`i(w;WZV>Vzl1(93K%lw6p$)xR<}>2?Rj|;B}0y z#sCL_B`E2VWVCd=0Ci;GO-Gs*&IY{X?0_ z=SP$#BL3V3ww>_kc5{-`^bz`b%X`EkE{Bj2cfu<&D}lPW8E~FCpB&)(46r1|6pRTc z!V@w>@E6qmZbb`JvHM@I*x%Sj_LkGw4{7A)#)iy8&IEsoKa4-2zT*>&Drd+T2jrfU z%#(_NP%_}qJd_gFu~AT;&J}izCQA^UXkjD{2CM6s^~%5_4GlI;=_&hXlG+zFrdKha zuS-$q@I*5lLvr*CG(F`E0zn2|A?$Bk5?!mArXjujvJ1Nq7!41eW z1{c0t6XnV6rWR7d@KcF}gJPb}5MwkUL71jet@gJtPaIxUf(3|ZXCtWezGoBgz?J;! zE2H`ZtH3a&6PBXx!vhdG<@}8sJ1m8W(Ssg%J-EYU64QLGmblFw(%rb`R>FQo?6c){;w@w*wX=%PKku`O==iJ>mPcmPh z;0eDymw;QM{73|tlprlaf*3mxC*2O<0JN@wu7qun>xnmvd?+QqPAT%d;PO^=HthdC z3zn61qjy|?PdTFwb%(QI%9^3B@VX?77JX~bV8PQvK`EZ4#lo~ygcW?0QrQw zj3(1?5D^=T!*gEkA~|c4yd6aeeKgT^F@6GwzWdOj#MMfTT{v!k*(f{!HB$E45_iRd z?&E&%gG%m!oNvQb$Mc+8fwcI)hz|1keb4DSbp>jaZ8g^os*+I`NkwbvlX)N1&#pBJ z(fy}tP$h8DOazwQn&b2No6~!1v1G+Au$tdrOd3zv=-RjIr@Ns_lA($_)UtM8#95Ig zD+Dm7VfH8pCpSAHoz_r}^k&sz=0;1=KYCb}=+FXZhBXOtEkz zL~tm(uoPfo%FA?J0OvZ-vWy*%DPE4lOo2DD7D8fjOr_9xiUXST+NalTa(Bjuj9Jo^ z)#Wy9mvJ`c__U@!bcEQrhirW?SEhb)%FH#22`T}~-1qZ-DX{%#PL5@@6}P@L9E8eqz6ItL;? zn+HZ6gEPg86e)|ks#YBMkT#7z2poq)lpcn53HO@5m;Gpq(;h}tU&Lq*BZ`b{Y>UqLeJo!oO?~y9W^v>Fw@Ji;3E>}3_8h_1#|(qC^J<1hL2?(YN={NgBL{D zuLczqx>S?2`6?6>Wl`i zS9xq+X1i?Mg@SjKEM1ebFT=A)5Xi5JH%CEmpJRFGF%N*1@`fIrtPsPsPS#`eVD(KH zGQ}^gm@#aZuK+YhKTU^zqN9n}>4PBPA_}zshf0?chPQ&NFqZ_^ zz|5ljp@__gt(cGD1)&CVDD^@vJHd15mCB`k^C(|vWgZDzxI6K>z-iZ#r8fmjk;2T; zOm0z4q2JO>6nQM$YlO#qRe>oebq>>5}s?|Qz8$g`1N96$z$ z!`Yup;4x=A<_4DyCPo0Qll~}C!T-lh7jJ@RcyGZoJ_puS1`*1^{?W0xUZqN-5a|cr z15McrUun|hpvylUA0ISU>#MDa$ee-(euD0-r(57Yl9(#D61s-fHqQaMtmF25IvHJ| z)^BBABU|hmRXYa$U>!BN1Bve3_)xpLx~d^7Rf!C z4iJe}iqv-AbqJQMgbHGrg-YZH*1Dx{_v_Z(dX?WH?aZqA-c7pZ87N?@9)yn{KNhGz zg`1lj2{IMz9tWz%Gr>hy6cP%MQ0gH$mp=<mu8XMz&)kj{cw{gfBQL8e4Ea7F$~vAB8C+0qAxz;-?~W3EFm z*>FQ*1TyZgS`cwD?UgN+E@thYxS8#jn_EZo+F4({y%j7ouZ@r(&$XRKk8+Oh7c&7S zN0zSYUVoT(f`ibiO3BN`dP?4PK*Ixf%Fvt}gbHNJ^r%9ur6eIU^{J`O&H-072E694GfniWgJUc9&(;Tt?yQRQ3?%{dfHev7Z|OG=Z2*L#F$TJ zW8}RY-N8?Rm@>=DoHlITNDMu{{IVWb+P3Tn+@XcT zb*DGV?jg`@SDx686mg$>rvs)k?(}qN(Ie=utAAT_Vj!hXv050c35K-2|6HR<_>Nfq z;HaXnM?+Fh4_$0bvSgDj;rCQ!ekGu_)Q!!}Oe=kjEGXJJ&A5)^@C9w;rq6;Eh1Sa9;BX(nHYmYEe65B= znF4@IOI##Xo3m&wdbhCR;r5H|*QNRIf7;%B21Cd#fkvl0bD(d*e%(Vqg^JGtpanx` zn6{#$D4X?Q=cUiHY&<;A0Rd@qjD!)@^P>DSS(T1ovEgNp3DW>5rvqPi_S%FTU_Rzy z<$RjfbDpUNek)ZvA)%zw1EQW<-lMcf9Gj8=KxeROshHwua&Fz5Sjb=Squ@B=DlhX+ zC7S_gaRrZ%bST!dA1eA?;Y-6t2hH%4*+|9MF4rwYVhOW563cu|9;XI-Rz;1LG4hgF zS*Hy~a6~1SN+M5l0d-}cMU&IW*X{Xivu$CW`^3t<;^}Dej&6G;t?7v$0$wQXvv_ny zVO(Txgy6E#B0W-)U!|zY0Iq5sC*-MsYJv@0hI*s!IyYg2`Tz#ITF|%zJ#(1+G>{u* zC*%cN3=UDnP^#5%T5B~FWiqSuR~=x`7K^?qixLU{HSaLjzODU&e=G1pZtyepFVe|} zN4?Q7_8t9&Y53C%;K+GV3%(>1L)?9*@p+$3mC#~BH>c_WJyVad6kZ|ja?;-)MO_z6Nl9;e zLNOdTdex5u<5L8|nx>X3TxYmON>evDH4sN(1)@O`i0a$e-wL7DKXcW{YS~iS%lxs? zVS+I|HuK-(vAU&*J78}p_~~l?-o6Ap#I~EflC>IEmP{U+^(TQ{eDF0tY7p!Yskw{MM3p%H7PXm4 zb)(wMX)Ii_Jdg!oWfJ~9Kw=ISf|Mf+V~9QwcDPob5R5Z{@(fuYC zn?k&9nNmtLALLF@ub1eGlD&LQ@=G7zTJ%FnZ|f$~JiYb!Lmb_qJ68L73#7d6e#}d$ zoP|@bIt7dqq#k z;5}v7Ij>@NEm>aVi-!EjGbpO}#An%F1=qqNv76Sh(Jn7L{UHmv<%U74E!U@NN&N&- zHw`$~3fvgKI*72~JQMqezqXII4>k`s;VVj{Q%%&xhjc@;B>MnA7a{;Eac;lymjQ@= zwi{uzS%LYP0MW-60ba(JbU!$dp9v5EvHa&EHR8_&m|T3*+F@tvo2PO^!RG^m3TqCS>#X(V!B3O#E#4&5fx(#Ab;qb_FMW_$`aclx=`r}rEU z)!g2_%Vb#mnNkLzSqEtVR?(EhF-bW0Nhwg%qW^)t8Eg-%H_PR_IR&a_Pg}+F_i_{7Q?=s61y!F;5cy1Ra^;D5irYx^j zwshWeL9AIIc2z?d`j}ncW0d^*A(T`eh629#{gH$lK(!w!D|NlqYvGM1L*v)~^=ccj z7HLl49bq=_^}*)xPwnHw&Ap@D&0|U~7Q8;%I@~!prm*RIn=iN1uMf8YJTRLtw~v3? z$I9XBt^K{@?Y(1C*yOaWuL1UpUL`BH7CRQESO`s8YCXsS5 ze3_<6FL01!{TWz?qV&Jl>$9sa)pB+K_%<&*a!DXH$r`kDw*>C4ech&;upc$sb=Y0j zY+z)q&b8~0(^*S6prl@}^GdSo)w}rGMq1g~+er&!{n!{93_e&wtb=h}J|6t??533R zGtJ6gsd$P`k-F8Ccr$aWQC&4)Pfs67;W>MNK^gq8HF@)xVvXbh$<8iwvI>)pJj%IC zu%)6W&KYw-g4@&Bh-YeDvW?qAb=8^p$tC8@y_mY>O~1^4-T{(Yjyg!$Q)yC)dDS*j zB!!1t=T@qkG-_tw+)2l!C`f0nlL#v22RfAz$;?fN#WoB-^%18&OJPfWoWhd&I0ZLa zH<533=a=838BMJSyHJiI+SnDoJrWh`Q*?@1d9+fCpp%iuu(c%3& zhPCe0F~PQ^^D&KOaiRB;Gol6@_mCQn`(we%`C|#3rtYWG&yC2X>9IY=0m&X94sHRv zk*al4df)F5`ibC+IdO8=H*g2CdOt^qx>!QGG>4(NRa@f+4hld>*y*gHgJZDNq;P&r zFfC!JxBxA`*xi4+xqEa{a@9&U5CQ+*$b>G-?PNN=WIkjHjGh;D%};f5=IIRm-Q-2p zdfc?iQa{#GO#*aVnL1`6DL8b-!Uc77&l|@aEGNSQN(L{>+1O`#3N~wt=MkmR!@P3U z6wAwm{6;)m3L+sHS>>ntCbi6q|#SP+NO% zORmNE%^EFRw8q{pEV0X7aotzFKAVc@vg?9sP7+$p&t1&Vv_1Gdvx9jy2lEULKF`_! z4(Bg%={*LBpY{`t>yCmQ41e1fx*L50EWiAqkY%PgvtO>PwJO%a*oibhwLnDcuRvu! zbBLx1`HXq-_gRd#q@}b+L3S0J%`m<)&q!z{@W-Z)U`t zV$S3cXpGO$RLXx3eu{~ugBv(^Rnr%v+<4{mSjFaaL&>EGb zhe(07ZnHxXL{ub&Q~uDs((LipxoV>=ZQ_aHSb|p+=_>oh!D*H8c-#9S=nVJW%~=vKoIK!)6g+9pr-9!3c6fjXftbv7_}ympu-9Iph^_7 zzw$KhY(M6HX@OSZ*JS{ zOY>A8P~_HlI63vb!>>tEMb9-H1MPSB410yY%fse{pZ4f|EITn}e^k?;nYq>aC0 z4v^7k&{W+e{+_@MQ0rdw2R+~oo7ZqdIl#>vOCkiD^(FuFZRsEuw^_&`Pv%OZ=et0L zd&7|Mt8V7(o4Qv4_Zm}s*$T1`v3QE;3yNn6LagBvl<5Xi#3mL`(WgQ2EbYoQ{PSc| zHBx5{E2JpWphA{f#Tp)+XwqW{X-J;ZmoGQ>p3&m6+i8)5nb^n}`B88*acDK4>^wRK zOe`Tza^C>GNxt+8XlnAT&bvU$4_t~z^oa}P*=$Pj<~EfTL!Ym)(!A+&s^w~|s7}6$ zS?g6(79LJjq9d~89Q_hM?{sqHTa~tc<#Zj@D&~~Ap91Yaqd}vw++UX!OsBVAPHmOS zy`8(Oa+O!sups!1 zB_7~9shGg|HZ;Cn!YEGsBsQFCFrJV)S5PLI z8M)eQz1XRez;H~Ba`M^4CbH6A;PqP6mlz5sN;&_lVl3^q88vEcbeX5mhj@_LI=w_|I<+C&xKc|uiJ zj{@NSOBDgkontRj*TVMwxh@y8LVzzn+c>VfO?7$>PEzGoNFxEQcxHS#Yelvv6{; zqRVh`+wpuZ4qyw4I48-E3(bQaK;__h0_F%lT=5JObBB7`DaYHVrvhz%?IHxrHHkC# zQ;F}VlD(f?y}J*&pf1h~{P)>tiWmg%OQ=l&?9hty(FF7R^)LGru1})66f{}0USvxW zyzex6G?AYq!rMPPOX8^}^+6&aC9AN5WW+$RK*~Yg?~T-Q4&@Y}#Kmy8Fi_;i5vaAc z;43G7%pymegsYgDY+&Q$=0jR@~xkNCqT>c_?v!!5tXgBKUPOA?CA7Y57*kA}( z6bVT19@b41mb_Kx&$_pFY&r#hdc38m+9jxkO9VUypw5P7d}Aw72{!?=MZkOYLNK*Y z1cYx#5cKP`R7O-hw@;7Pssc)TQ(LQ4uwJF)&rNC@Q;o-F&5M}mA5&_bnWW&kFE%Hz zd}*DQ9%)b$n&GzQv3bN{Nh#wOig?;6RP0RRvKQ35YD(YLSL!RZUi_Y8zt>hNZVSW0 z=q;xbfm9Yy6oam3R*8Gp-fC=>e^qy1G5jyx-_|Dv_y{p(=@I{EeUi6dtoH)%3v|2n z=~Vi93f=ru9h9yu=oCi&pZ2@&$l9Tk^t;Kzu0p3`>RYQ-n&%^xM(c}!B?Ro`HxB<% zx?klZzw+`uD|e`J{l0B(a<%)mcEyvH+_zqzhxoYm=7(1AzJ2X+qxY`&fg4?^{jF0w z+pImm_rjccy{==&>F;v+hxL=~_>GRH^20sBc6sh|YQZjkbf)o$rdK1*aGaQ^hQ}h3 zz$`2R;E-Sm@ZVC+oVy%}b2 z2|F+bJTO)LXxy2y55`|tDt=Z?SJ~3MBy~?mAp@4*fo~Npua8yybef@tG)D}CrWbRB zKwjq2!eR^EJOf={@FbEQR4=AD6yG*Amn5YStfe<*jwR|GOH-<4L!8jc;%d^2B-R3T zo-K29uz7S8eTFTw)&3#?H6->eT~i7v%NSUme?EtxW(2m*9Ev|f@ZW)#;DBLrX;6$0 zSh4q*CJX4JE(WbGIE&-1+no-^oIUsFHr@a1x-YfsLX;`7MnxEUthug{eH$UCGmPUN z$FV{(AGo_IXTlD`CI?fQk@)6r?zDWNPTXm&CNiyBjWd*{%WniiOZPSzQrnxExG(vptV5BS{1A#SK#b888_G7~^(SddmH&tFi3^VN)d?2%* z31^eLr|mEUnEZ01;BD)Ykqv#gy?M01x1MKdB``A*j{vp>eUsm3#y;#-R|nLTa*OjL z1(&unSeb-{$gd;YJV5XwpCLqXVc!Nsy4e z*8hUfHC3=ai|HGV%w4No$aWxi4W8X$4MI14Zw2thXU{*4xRwe6kURIu#i9`$-C+d2 zPe0(vhYuPsh6cbbd_>LnO(FX1VNhCjlXNHjF-vYPGJ{!K>Rw!qdZ})#{N>wkE%6~E zg@G*^>h2we8iY-Nu@-9Z&oB|S{mksYIzD)HT#${*FE_W2Uv2K%SG;fe729k7iRppv z;H>z)5}%4N9g-L`hrM?W6=6^)AsK9v>954b5|M6YE(uYzLGe;lM8VhDF%;5`5IDYp zGPdjVvR=xwUY{E@FJ-ts2P2?`MUEpDn)A}#D$ya}{xv850LAGb6?rc|97Y&|FE0*9 z7>SRkPK@Di^3}2~_Kd%&=M_~F-v^LWFV*eYaLP+5_d#cZ-S13X|0VTKzxQF4 zKk!v|I9=tBHIlo={aJ#= zcpQ(->W1M*{*aO>ARV-E;CGK7+vp9y8}(L6$gDf7FF7|P>;kCZYt z{(UWPoZ%SPWQ=QWjKM0U#<=z;#wfc9q2!M-J;XI{h--O6l+vqVaoLZLslsYH4HJU$ z5;6H@*F4OvIDp=V=iX9Nw~w072W_FI-6rytc9HXX1OODziq^swUUP-lg2HQ@!<6YT zr%^{twwige7An^7bVNOk>-|rve^mXm8peVTocp?~pRt`D&pR}fc9p=cecmpmKCfD^ z0bILLyR`GVYkm|=AM*S(sFZ10)r^a|4C5^{bgZp^s(hyv@*CX;w* z$3QP>7(+7Xq^Cezxj~7=Y8stUi!=z^ht+H!2z$O;ThNC!?ZcYihc&+sYjgWRSmfQ> zzkbO7y5aD?%EOGB^iG?(?GWHXWRF1#dVpqchwcuCg`PSd{+-3lcJ7sRy8wW0tSjHV zEF+^Xj&fc*`2m@Z*nDG7WQVN670h`)V9~r}L>4~MM)M5di5}ztr`y)csI1)9DJPe9 z(uJFJj$5=qO_I(zCpTx`07(M*QC~^YY%klom%S}z46VPb=BqGr5`woTZPvX6SvUFN z;T9KWirxS>-OLXwMX!A)#U@94l4^PmB>t;vEa)w#5XH9?jVtqd^^JemF@z=ttOed3 zb!(*{@QvER`9nUTT5p1gDVeuv<8q1fl2??C^CXjO_Oi+cZZpq@8Tzv8Cx+=ct5);^ zpt1XqUB|#xNV7wR*>N)xHGU(LVj=M&APD$o@A&t`S#^571a9dI4Ay~fH#7%@G>kr% z7$K<@QTt6S)QX~X+DK<-nrB~c&FekSLKy@ShxGO1$_;ITsN}3s3R<_+7^(X=zDW^$3Tl~}KRivA|3nS<)y>v25kqOYAiA;W!vh4-8nCPhjR=F}3% z%!Cb4^k&zBANf@EP$W26L7|DwjOm_etR?qElWMvr;zR2_kyM)A6PuzFpA?o-!YqG4 zd=BJt^tygheE)`63C>dHy|A5pGiL%)lbXvC4f+_r9fP9`D~MDXRl8QK*eHaBy~4YD zb!DZ#VwS0P!!CbD0z(ORWxo_jLWyD#kqteJT$lYXNiHLTZ(K$B_y&_=Zy>m}{n z1^{HQzM=X4VCNgFik5V4RoRPqRX^NT_w|Cx)-z^KT{#wcRjp!nPE|Rp>8idnq&H>$ z9QeTfJ_dtb@y->le-QH2+m-fIQXxd9-;XEp6HVgkm-jYywpuBhh4OR$apuay?W0$_ z$L8qO%a@ynzmh)SPyZ`y!y(gzzRPf!?TINr`nJA$ z_UKWiRGot{vbfD}lyZW|zx?UoPPnDLS0^k&%j<=G8FoWjl+$_N78TFsHRy1lhT673 z1AvMec&~AHFlO8p!LiyCQDuu~?`q*y4ir@7q1SYVx}0uA$qyr*

W W " +" 2W 4W ,W HW 3W :V MW KWU.U 4VAV &V 5U *U 2V 6gGU KU 5W?W =U/V\"U/V IU7V LX ,WNW 5WNW 5WNW 5WNW 5WNW 5WNW 4XHX H[4U&X -X -" +"X -X -X -X -X -X ,X6]&`8X\"Z7Z#Z7Z#Z7Z#Z7Z#Z7Z 'Z8['X/X'X/X'X/X'X/X)Y8Y MX ,W:W 9V 0V 3U@U ?[ 1V 0V 3U@V GV 0V 3U?U 8h 1V 0V 2U@U " +" CV 0V 1U@U >V 7W *`L` I`L` I`L` I`L` I`L` JV =X,X >T 6] 9k\"lKl K_ #\\ 'Y8S MX 2VFV %VBV Nk IVAV=V$X 1V %V +V " +"6YHTHY -V EW 5Y>Y :X ?R5Z .Y ;VMX DX +Y DX IYW W 2W 4W ,W HW 3W :V MW KW;W De =W " +" -X *W:W V$X 1V &W +W 5XITIX +V EV 4X[ JX -XNW8WNX0a9X#Y3Y(X9Y JY3Y(X9Y NX LX W W 2W 4W ,W HW " +" 3W :V MW LX;W Df >W ,W +W8W >WLW @Y 2X +Z3Z!t\"X0X)X?X?X*Y3Y Kj 9V 9j AS 5X 8W:W HV /W #T)T KV " +" @T(T 6U?U &V 5T +V AhGU KU 5V=V =U0V!U0V JV7V WLW 7WLW 7WLW 7WLW 7WLW 7XNX 6XGX IY.R&X -X -X -X -X -X -X -X ,X2Z'a9X#Y3Y%Y3Y%Y3Y%Y3Y%Y3" +"Y )Y3Z)X/X'X/X'X/X'X/X'X:X Ki >W8V *XHZ FW ,ZW W " +" 2W 4W ,W HW 3W :V MW LW:W Dg ?W ,X ,W8W >WLW ?Y 3X +Y1Y\"v#X0X)X?X?X+Y1Y MYNVNY :V :" +"YNVNY BS 5X 8XU1V U1V KW7V NWLW 7WLW 7WLW 7WLW 7WLW 7WLW 6XGX JY,Q&X -X " +"-X -X -X -X -X -X ,X1Z(XNX:X$Y1Y'Y1Y'Y1Y'Y1Y'Y1Y P)P$Y3[)X/X'X/X'X/X'X/X'YVKX DX -X BX IX8X NX7W KP 1P =X Y *Z W 0W MW +ZAZ 0W >W W 2W 4W ,W HW 3W :V MW LW:W DSF[ @X -X " +" -X8W ?WJW ?Y 4X ,Y/Y%z%X0X)X?X?X,Y/Y YMVMY ;V ;YMVMY CS 5X 5P*Q JWU2V NU2V$_7V NXLX 9XLX 9XLX 9XLX 9XLX 8WLW 6XGX KY*P&X -X -X -X -X -X -X -X ,X0Z)XNX:X%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y\"R+R&Y3]*X/X'X/X'X/X'X/X&Y>Y Jp EW:Y " +" +R@Y 7Q 2W .XEVFY\"X5Y\"X5Y\"X5Y\"X5Y NV ;X/X 0V 5T 8c ^ AW4W ?Z >W6W KY " +" \"Y 0X 2VFV &VCW#[LSKZ KV?V@V\"W 0V 'W )W 1XNTNX &V FW 6Y:Y X *Z NW 0W MW ,Z?Z 1W >W W 2W 4W ,W H" +"W 3W :V MW LW:W DPAY ?Y .W -W6W @WJW >Y 5X ,X-X&_MXM_&X0X)X?X?X,Y/Y !YLVLY " +"W FV /X 'TCfFT2i CUGfBT 9U?U &V 7U 5] >iGU KU 6V;V >U2V NU2V$]5V NWJW 9WJW 9WJW 9WJW 9WJW 9WJW 8XFX KY /X -X -X -X -X -X -X -X ,X" +"/Y)XMX;X%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y#T-T'Y3]*X/X'X/X'X/X'X/X%X>X Ir GW=\\ GY 9S 3W /XDVDX$X2X$X2X$X" +"2X$X2X V ;X0X 0X 7T 8d X$X-WJW EX6X Y .X.Y)X -X -Y .X/X'X -X -XBZ EX -XLV:VLX0XMX;X&Y-Y+X7X NY-Y+X7X!X KX Z W FV .X (TDgFT3j CTFhDT 9U?U &V 8U 4\\ =iGU KU 6V" +";V >U3V MU3V#\\5V MWJW 9WJW 9WJW 9WJW 9WJW 9WJW 8XFX LY .X -X -X -X -X -X -X -X ,X.Y*XMX;X&Y-Y+Y-Y+Y-Y+Y-Y+Y-Y%V/V)Y3_+X/X'X/X'X/X'X/X%Y@Y Is HW?^ " +"?Z /Z /Z /Z /Z /Z /Z6Y NZ 0Z /Z /Z /Z 8Y 1Y 3Z /Z /Z /Z /Z 3ZCV 5WDX DXCVCW%X0W%X0W%X0W%X0W V :X1X 0X 7T 9f =k#~`\"h Cf " +"EW4W @\\ ?X8X LX !Y /X 2VFV 'VBV#XHSET KV?VAV!W 0V (W 'W .` \"V GW 5X8X W\"W.XJX" +" FX6X X -X.Y)X -X -X -X/X'X -X -XCZ DX -XLV:VLX0XLX^4WG_ 9` @WG^ 9^GW MWG\\ ;f Gm ^BV\"W:W 3X ?^ 0e AWG_ KV.X ?X Z 7X -X+X)\\HXH\\(X0X)X?X?X-X+X $YJVJY >V >YJVJY Ma =X 7V0V JW@W EV .Y *TEiET5k DTEiDT :VAV &V 9U 3_ ;W6W NiGU " +"KU 6V;V >U3V MU3V#_8V NXJX ;XJX ;XJX ;XJX ;XJX ;XJX :XEX LX -X -X -X -X -X -X -X -X ,X.Y*XLXa'b 7` 5` 5` 5` AW ,W ,W ,W DY EWG_ 9` 5` 5` 5` 5` (Z <`GV W6W MW6W MW6W MW6W#W1X NWG^ HW1X NWBVBW&W.W&WJP:PJW&W4PJW&W." +"W!V :X2X 0X 6S 8g >k#~`#j Fj GW4W @\\ >W8W LX X .X 2VFV 'VBV$XGSCR KV?VBV X 1V (W 'W ,\\ V GW 5X8X f CWIb =bIW MWI^ =j Im U4V LU4V\"`:V GX /WHW ;WHW ;WHW ;WHW ;WHW ;WHW :XEX MY -X -X -X -X -X -X -X -X ,X-Y+XKWf ;f ;f ;f ;f +Z >eJU NW6W MW6W MW6W MW6W\"W" +"2W MWIb IW2W NWAVAW(W,W(WJRU5V KU5V GXTKW)W4TKW)W+W\"V 9X3X 2X 5T :k ?i\"~`$m Jn IW4W A^ ?X:X MW " +" NY .X 2VFV 7~X2XFS VIV>X2YIY DYFY +Z JW .V NW 1Y3Y 1n DWLh Bm ChLW Gk Ll 6hLW MWKg HW ,W ,W;Y JW " +",WKfGg8WKg Cl FWLh ChLW MWK` @m Im Y =W6W JW-W&YJb }!WCWCW Hk Dx&{ W4W CWFW P JSCVAVDS :WEV $V W6W NiGU KU 6V" +";V BP>P /U5V KU5V EW=V FX 0XHX =XHX =XHX =XHX =XHX =XHX W:X MW NX -X 2VFV 7~X2WES WKX0XJX>X(Y)X,X7X!Y)X,X7X!Y LX VIV>X1YKY BXFX +Z IW .W " +" W 2Y1Y 2o EWMj Dn DjMW Hn Nl 7jMW MWLi IW ,W ,WW6W NiGU KU 6V;V BQ?Q 0U6V JU6V BU>V EX 0WFW =WFW =WFW =WFW =WFW =WFW X(Y)X.Y)X.Y)X.Y)X.Y)X%Z9Z*Y6WJX,X/X'X/X'X/X'X/X!XFX EX;Z LWDX ?o Do Do Do Do Do DoKn4n Cn Cn Cn Cn HW ,W ,W ,W %l HWLi En Cn Cn Cn Cn /Z Cs LW6W MW6" +"W MW6W MW6W!W4W LWMj LW4W W?V?V+W(V+WKXBXKV+W5XKV+W(V$W 8W4X 2X 5T ;n ?g!~_%p LZDZ JW4W A^ >W:W MW MX -X 2VFV 7~X2WES VJX0XIW>X(X" +"'X-X7X!X'X-X7X!Y LX VIV>X1YKY AXHX +Z HW -V W 3Y/Y 3p FWMk Fo EkMW Io Nl 8kMW MWMk JW ,W ,W=Y HW ,WMjJj:WMk Gp HWMk GkMW MWMb Bo Im \\>W0X=X LW5X u 6W :V MW EkJV Wj Fn CWMk\"\\6X =Z >W6W KW+W)[Ke\"}!WCWCW Jo Hz&{ W4W DWDW ;Y ;X /X'X.YBXBY+X0X)X?X?X/X'X#T HV IT " +":V ;T3T :V CV +o BX 6ZM`MZ GXFX CV *\\ 3SFW,S:V>V 0R@R KSBV@VDS 9e #V ?W \"V ?W6W NiGU KU 6V;V BR@R 1U6V JU6V BV?V EX 1XFX ?XFX ?XFX ?XFX" +" ?XFX ?XFW =XCX NX +X -X -X -X -X -X -X -X ,X+X,XIW>X(X'X/X'X/X'X/X'X/X'X%Z;Z)X5VHX-X/X'X/X'X/X'X/X XHX DX:Y LWEX >p Ep Ep Ep Ep Ep EpMp6o Do Do Do Do" +" HW ,W ,W ,W 'o IWMk Gp Ep Ep Ep Ep 0Z Ds KW6W MW6W MW6W MW6W!W5X LWMk MW5X V>V?W,V'W,VKZDYKW,V5YKW,V'W%W 8X5W 2X 4T ;o @g ~^%q NY@Y KW4W B`" +" ?XX -XJW@WJX0XIX?X(X'X-X7X!X'X-X8Y Y MX W/YMY @YJY +Y GW -V W 4X+X 4YE\\ FWNXG\\ H]EX F\\GXNW J\\F[ " +"GW ,\\GXNW MWNXG[ JW ,W ,W?Z GW ,WNXH[KXH[:WNXG[ H]H] IWNXG\\ I\\GXNW MWNXFQ C\\CW CW ,W6W!X6X NW?\\?W.X?X JW6W 1X 6W :V MW 9X=X\"[IZKW W=Y /W @m H]DV " +"CWNXG[\"\\6W =[ >W6W LW)W*ZJWKY\"}!WCWCW K\\H] J{&{ V3W DWDW :Y XCX NX +X -X -X -X -X -X -X -X ,X+X,XIX?" +"X(X'X/X'X/X'X/X'X/X'X$Z=Z(X6WHX-X/X'X/X'X/X'X/X YJY DX9Y MWEW =YE\\ EYE\\ EYE\\ EYE\\ EYE\\ EYE\\ EYE]N\\G[7]EX E\\F[ F\\F[ F\\F[ F\\F[ IW ,W ,W ,W (p IWNXG[ H]H" +"] G]H] G]H] G]H] G]H] 1Z E]H^ JW6W MW6W MW6W MW6W W6W KWNXG\\ MW6W NV>V>V,V&V,VJZFYIV,V6YIV,V&V%W 7W6X 3X LR:T ;q @e N~^&s!Y>Y LW4W B` >WXJX +Z GW -W !W 5X)X 5U>Z G_CZ I[>T FZC_ KZAZ HW -ZB_ " +"M^BZ KW ,W ,W@Z FW ,^CZMVCZ;^BZ IZBZ I_CZ IZC_ M^ 5YY .W AXJa IZW2W EWDW 9Y =X /X'X/YAXAY,X0X)X?X?X/X'X%X JV KX Z FU>Z FU>Z FU>Z FU>Z FU>Z FU>eBZ9[>T FZAZ HZAZ HZAZ HZAZ JW ,W ,W ,W )r J^BZ IZBZ GZBZ GZBZ GZBZ" +" GZBZ 1Z EZB[ JW6W MW6W MW6W MW6W W6W K_CZ MW6W V=V>V-V%V-VHZHYHV-V6YHV-V%V%W 7X7X 4X NU:T WX !Y 0Y BVDX Dk CXJc -X BX>X LX5Y MX -X Ee Le 3Z ?U=bKUCU6XDX IX9Y X +X+X+X -X /X +X/X" +"'X -X -XL[ Y J]?Y KY?] M] 4X8P CW ,W6W X8X MW?\\?W-XAX IW7X 3Y 5W :V MW =_C_(YBXLV NW?Z -W CXC\\ KY ,]@Y LW8X >] ?W6W LW)W,YHWHY MW=W JWCWCW MY>Y " +"L[B[ ;W >W2W FWBW 9Y >X 0X%X0X@X@X,X0X)X?X?X/X'X&Y JV KY =V >Y7Y =V CV .[HSFR BX 3t BWHW AV .WN\\ 9SFV)S;V?W 3UCU LSAV@VCS 7_ V BV LU ?W" +"6W MhGU KU 5W?W AUCU 4U8V HU8V ?UAV CX 2XDX AXDX AXDX AXDX AXDX AXDX @XBX NX +X -X -X -X -X -X -X -X ,X+X,XHX@X(X'X/X'X/X'X/X'X/X'X\"ZAZ&X8WFX-X/X'" +"X/X'X/X'X/X MXLX BX8X MWFW Y;Z:R GY=Y JY=Y JY=Y JY=Y KW ,W ,W ,W *]E[ J]@Y JY>Y IY>Y IY>Y IY>Y IY>Y 2Z FY>Y JW6W MW" +"6W MW6W MW6W W7X K]?Y NW7X V=V=U-V$U-VGZJYFU-V7YFU-V$U%W 7X8X &~X/X:T =t @c L~\\'v\"W:W LW4W CXNX ?X>X MV $x EX 2~X2WES :VDW" +"EV FZ :W #W 7XKTKX )V IV 4X4X >X !X 0Y BWDX Dm FXKf /Y AYBY KX5Y MX -X Gd ~X d 5Y ?V>dLUCU6WBW IX;Z Y +X+Y,X -X 0Y +X/X'X -X -XM[ ;X -XIWBWIX" +"0XGW@X)Y'Y.X8X!Y'Y.X9Y M] #X aEa)X@XNW NWA[ ,W DW?[ LX +[=X KW:X =] ?W6W MW'W-XGWGX MW=W JWCWCW MXZ W2W FWBW 9Z ?X" +" 0X%X0X@X@X,X0X(X@X@X/Y'Y(Y IV JY >V ?Y5Y >V CV .YFSDP BX 2q @XJX AV /WK[ :SFV)S;V@X 4VDV LSAV@VCS 6\\ MV CV KU ?W6W MhGU KU 4V?V @V" +"DV 5U9V GU9V >UBV BX 2WBW AWBW AWBW AWBW AWBW AXDX @XBX Y +X -X -X -X -X -X -X -X ,X+Y-XGW@X)Y'Y1Y'Y1Y'Y1Y'Y1Y'Y\"ZCZ&Y9WEY.X/X'X/X'X/X'X/X MYNY BX8Y N" +"WFW X NW $w DX $VBV#XFS :WFXEV H] ;W #W 9XITIX" +" +V JW 4X4X >X \"Y 3[ BWCX Dn GXLi 1X ?ZFZ JY7Z MX -X Je M~X Me 9Y >U?gMUCV7WBW IX>\\ NX *X*X,X -X 0X *X/X'X -X -XNZ 9X -XHVBVHX0XGXAX)X%X.X9Y!X%" +"X.X:Y La 'X _ @W6W MW'W.YGWFX NW=W JWCWCW NX:X NYW2W FWBW 8Z @X 0X%X0X@X@X,X0X(X@X@X" +"/X%X)Y HV IY ?V @Y3Y ?V CV /YES 6X 1\\H[ JcJc LV 0WI\\ =TFV)S;WAX 5WEW MTAVAWCS 3W 4~W.W KV ?W6W LgGU KU 4WAW @WEW 6U9V GU9V ?VBV BX 2" +"WBW AWBW AWBW AWBW AWBW AWBW AXAX X *X -X -X -X -X -X -X -X ,X*X-XGXAX)X%X1X%X1X%X1X%X1X%X!ZEZ%X9WCX.X/X'X/X'X/X'X/X LXNX AX7X NWFW !W ,W ,W ,W ,W ,W " +",]:X=Y .X9X LX9X LX9X LX9X LW ,W ,W ,W +Z=X K[x A` J~\\(y%W8W MW4W CXMW >W>W MV $x DX $VCV\"XFS 9XIXEV H_ X #Y ?g AVBX Do HXM" +"k 3Y >l HX7Z MX -X Me J~X Je =Y >V?hNUBU8XBX Ju MX *X*X,w Lq IX *~R'X -X -c 8X -XHVBVHX0XFWAX)X%X.X9Y!X%X.X;Z Ke ,X WNV MW" +"Ib +W EW;Y MW *Z;X KV:W =_ @W6W NW%W/XFWFX NW=W JWCWCW NW8X!Y:Y =W >| GW@W 8Y @X 0X%X1Y@X@Y-X0X(X@X@X/XImIX*Y GV HY @V AY1Y @V CV /XDS 6X 0YDY JdL" +"d LV 1WF[ >SFV'SW6W LgGU KU 3WCW ?XFX 7U:V FU:V >UBV AX 3XBX CXBX CXBX CXBX CXBX CXBX BXAw?X *w Lw Lw Lw " +"LX -X -X -X ,X*X-XFWAX)X%X1X%X1X%X1X%X1X%X ZGZ$X:WBX.X/X'X/X'X/X'X/X K` @X7X NWFW W ,W ,W ,W ,W ,W ,[8W=X -W7W LW7W LW7W LW7W LW ,W ,W ,W ,Y:X LZ;X M" +"Y:Y MY:Y MY:Y MY:Y MY:Y \"Y=\\ LW6W MW6W MW6W MW6W MW:W IZ9X NW:W NVV&V 4W:X %~X2TNVW \"W ;WFTFW -V JV 3X4X >X #Y ?f AWBX Dp IXNm 4X ` @W6W NW%W/WEWEW NW=W JW" +"CWCW X8X!X8X =W >| GW@W 7Y AX 0X%X1X?X?X-X0X(X@X@X/XImIX+Y FV GY AV BY/Y AV DX 1XCS 6X 0W@X KdLd LV 1VCZ ?SFV'S;WE[ 7XFX G~X .S@VBWAS @~W0W " +".P>W >W6W KfGU KU 3XEX >XFX 8U;V:W3U;VCZ9P>WCV:W/Y 3W@W CW@W CW@W CW@W CW@W CXBX CX@w?X *w Lw Lw Lw LX -X -X -X 5p9X-XFXBX)X%X1X%X1X%X1X%X1X%X N" +"ZIZ#X:VAX.X/X'X/X'X/X'X/X K` @X7X NWFW W ,W ,W ,W ,W ,W ,[8X?X -X7X NX7X NX7X NX7X MW ,W ,W ,W ,X9X LY9W MX8X MX8X MX8X MX8X MX8X \"X=] LW6W MW6W MW6" +"W MW6W MW:W IZ9X NW:W NVLuKU/VLuKU/VBaAU/V:YAU/V=X=U&V 4X;X %~X2RLW>T >{!z'~Z)}(W6W NW4W DXLX ?X@X MV KX ,X %VBV!YHS 8eEV" +" Ic ?W !W ;UETEU ,V KW 3X4X >X $Y >c ?WAX DWD^ JbG] 5X 9d DY9[ MX -X #d D~X Dd DY a AW6W NW%W0XEWEX W=W JWCWCW W6W!X8X =W >| HX@X 7Y BX 0X%X1X?X?X-X0" +"X(X@X@X/XImIX,Y EV FY BV CY-Y BV DX 1XCS 6X 1W>W KeNe LV 1VB[ ASFV'S;YI] 9YGY F~X .S@VDX@S @~W1V ,TEZ >W6W JeGU IX +U 2YIY T ?|\"}(~X)~(W6W NW4W DXKW >W@X MV KX ,X %VBV!ZIS 7cEV IYNZ8W 0W !W :RCTCR +V KW 3X4X >X %Y" +" =b >V@X DS=\\ K`C[ 6Y 8b BX9[ Nd A~X Ad HY W ,X8X8W=X8X X6X MY7X\"X7Y MX 0W )W ,W6W MXXMW AW6W NW%W0XEWDW W=W JWCWCW!X6X#X6X >W >| HW>W 6Y CX 0X%X1X?X?X-X0X'XAXAX.XImIX-Y DV EY CV DY+Y CV DX 2X" +"BS 6X 1Vh =W6W JeGU IX 4g :g :YFX DgEV:XhCV:X/X 3X?W EX?W EX?W EX?W EX?W EX@X EX?w?" +"X *w Lw Lw Lw LX -X -X -X 5p9X-XEXCX)X%X1X%X1X%X1X%X1X%X LZMZ!XX7X NWFY !V +V +V +V +V +V +Y6W@X ,W5W NW5W NW5W NW5W MW ,W ,W" +" ,W -X7X MX8X X6X X6X X6X X6X X6X $X=_ MW6W MW6W MW6W MW6W LWS >}%~R)~V(~P)W6W NW4W" +" DWJX ?XAW L~^ $X ,X %VCV N\\LS 6aDVAW0XLZ9W 0W !W :PATAP +V KV 2X4X >X &Z =e BW@X DP8[ L^?Z 7X :h EY;\\ \"d >~X ?e LY ;U@W>Y" +"AU:W>W Ks KX *X*X,w Lq IX6f+~R'X -X -b 7X -XGWFWGX0XDWCX)X%X.X@^ NX%X.s Bl 8X X IXDVCVDX)[ 4\\ -Z @W *V #W $W JX5W\"X -W5X W4W KW 0W5X MX7W" +" MW ,W ,WIZ =W ,X8X8W=X7W W4W MX5W\"W5X MX 0X *W ,W6W LWX >XMX BW6W W#W1WD" +"WDW W=W JWCWCW!W4W#X6X >W >| HW>W 7Y BX 0X%X1X?X?X-X0X'XAXAX.XImIX.Y CV DY DV EY)Y DV DX 2XBS 6X 2WY BSFV'S9bMV ;XFY D~X .S@h>S " +"@~W2i >g W EW>W EW>W EW>W EW>W EW>W EX?w?X *w Lw Lw Lw LX -X -X -X 5p9X-XDWCX)X%X1X%X1X%X1X%X1X%X " +"Ke X=W?X.X/X'X/X'X/X'X/X I\\ >X7X NWEY \"W ,W ,W ,W ,W ,W ,X5W@X -W4W W4W W4W W4W MW ,W ,W ,W -W6X MX7W W4W W4W W4W W4W W4W $W=VMW MW6W MW6W MW6W MW6W " +"LW=X HX5W NW=X MVLuKU/VLuKU/V?[>U/V=Y>U/V=X=U&V 3X=W 7X FW@T ?~&~T*~V)~R*W5V NW4W EXJX ?XBX L~^ $X ,X &VBV Mb 4]CVC]4XJZ:W" +" 0W !W +T KV KV 2X4X >X 'Z X Lu MX *X*X,w Lq IX6f+~R'X -X -c 8X -XFVFVFX0XDXDX)X%X.u MX%X.r" +" ?l :X X IXDVCVDX)\\ 4Z ,Y ?W *V #W $W JX5W\"W ,W5X W3W LW 0W5X MX7W MW ,W ,WJY ;W ,X8X8W=X7W W4W MX5W\"W5X MX 0X *W ,W6W LWW 6Y 0X 9V LX 5`3R 0T?[?T/W:[ KWId DbKW HW5X NW +X7W JV>W =WLX BW6W W#W1WDWDW W=W JWCWCW!W4W#W4W >W >| IX>X 9Y AX 0X%X1X?X?X-X0X'XAXAX.XImIX/Y B" +"V CY EV FY'Y EV DX 2WAS ?r CV:V =^ =V 2V=Y CSFV'S8`LV e :W6W GbGU IX 4g 8c 5XFX FgFV:YX GX>X GX>" +"X GX>X GX>X GX>X FX?w?X *w Lw Lw Lw LX -X -X -X 5p9X-XDXDX)X%X1X%X1X%X1X%X1X%X Jc NX>W>X.X/X'X/X'X/X'X/X HZ =X7X NWEZ #W ,W ,W ,W ,W ,W ,X4WAW ,W3W!W3" +"W!W3W!W3W NW ,W ,W ,W .X5W MX7W W4W W4W W4W W4W W4W $W>VLW MW6W MW6W MW6W MW6W KW>W GX5W MW>W LVLuKU/VLuKU/V>Z>U/V>Y=U/V=X=U&V 2W>X 8Y FW@T " +" ?~P(~V*~T(~Q)V4V NW4W EXJX >WBX L~^ $X ,X &VBV Ld 4WAVD`6XHZ;W 0W !W +T KV LW 2X4X >X 'Y ;i GV>X *Z M\\;Y 9X =p HZ?^ 'd " +" Id$Y 9UAWX GWEVJVEW#a >W>W 7Y 1Y 8V KY 9e8T 0T?Z>T0X:[ KWIf GdLW HW4W MW ,W6W JV?X >XKW BW6" +"W W#W2XDWDX!W=W JWCWCW!W4W#W4W >W >| IWX GX>w?X *w Lw Lw Lw LX -X -X -X 5p9X-XCWDX)X%X1X%X1X%", +// Start of second string. +"X1X%X1X%X Ia MX?W=X.X/X'X/X'X/X'X/X GX W GX5W MW>W LVLuKU/VLuKU/V?\\?U/V?YX 8X DWBT ?~Q)~W)~R&~(V4V NW4W EWHW >WBW K~^ $X ,X &VBV Kg \"" +"VEc8WFZ=W /W !W +T 4~W 5V 1X4X >X (Y -] IW>X )Y M[9X 9X >\\F\\ H[C` 'a Ca$Y 9UAV:WAU;WW )V $W 6i JX5X$X -X5X V2W LW 1W3W MW6W MW ,W ,WLY 9W ,W7W7W=W6W!X4X NX5X$X5X MW .[ .W ,W6W KW>" +"W FWEVJVEW#a >W?X 8Z 4\\ 8V K[ =iW2W IWX X *X -X -X -X -X -X -X -X ,X*X-XCXEX)X%X1X%X1X%X1X%X1X%X H_ LX@Wi >i >i >i" +" >i >i3WBX ,V2W!V2W!V2W!V2W NW ,W ,W ,W .W4W MW6W!X4X\"X4X\"X4X\"X4X\"X4X M~Y2X@VIW NW6W MW6W MW6W MW6W KW?X GX5X NW?X LVLuKU/VLuKU/V@^@U/V@Y;U/V=X=U&" +"V 2X?W 8X CWBT ?~R*~X)~Q%}(V4W W4W FXHX ?XDX K~^ $X ,X 'WCV Ii &VEe:XEZ>W /W !W +T 4~W 5V 1X4X >X )Y )[ KW=X (Y N[9Y ;Y " +"?Z@Z I]Gb '^ =^$X 9U@V:WAUXIW CW6W!W!W3WCWCW!W=W JWCWCW\"W2W%W3X ?W >W2W JW;X ~R+~Z*~P#{'V4W W4W FXHX ?XDX K~^ $X " +" ,X 'VBV Gi (VFg;WCZ?W /W !W +T 4~W 6W 1X4X >X *Y &Z LW=X (Y NZ7X ;X ?Z>Z ImNX '[ 8\\%Y 9UAW:WAUX XIW CW6W!W!W3WCWCW!W=W JWCWCW\"W2W%W2W ?W >W2W JW:W =Y >X 0Y'" +"X0X?X?X-X0X%XCXCX,X%X2~a GV H~a HV I~b HV DX 3W@S ?r DV8V V&V 1XAW 9" +"X @WDT ?~S+~Z)}!y'W4W W4W FWFW >WDW J~^ *r ?V &VBV Eh *VEXIXX +Y $Z NWXHX DW6W!WW2W KX:X ?Y =X /X'X0Y@X@Y-X0X%YDXDY,X%X2~a GV H~a HV I~b HV DX 3W@S ?r DV8V ;X DW;V DSFV'S >XFX " +" ;V .S@VFW=S (V \"W6W :UGU IX 0XFX -V;TLU MV0U!V;TLU6Y 0X:X KX:X KX:X KX:X KX:X KX:X JWV&V 1XBX :X ?WDT ?~S,~[({ x&W4W W4W FWFX ?XFX JV \"q >V &VBV Af -VEXGX=W@ZB" +"W .W !W +T 4~W 5f 8V 0X4X >X ,Y \"Y W;X 'X NZ7X X -XDVJVDX0XAXGX)X%X.i" +" AX%X.X>Z ,\\ ?X XGW DW6W!WW2W KW9X ?Y =X /X'X/X@X@X,X0X$YEXEY" +"+X%X2~a GV H~a HV I~b HV DX 3W@S 6X 3V8V ;X DXWEW :V .TAVEW?T (V \"W6W :UGU IX /WEW .V;TKU NV/U\"V;TKU7Y /X:X KX:X KX:" +"X KX:X KX:X KX:X KXWDS >~T-~\\(y" +" Mw&W4W W4W GXFX ?XFX JV #r >V 'WCV X -Y Y!W;X 'Y Y5X =X @Y8Y HgKX 'a Ca%X 8UAV8" +"VAU=W8W NX4X%X *X+Y,X -X 0X(X+X/X'X -X -XI[ ?X -XDWLWDX0X@WGX)X&Y.X 0X&Y.X=Y *[ @X XFX EW6W!WW2W KW8W @Y ] Jt It It It It It I~iBW ,|\"|\"|\"| NW ,W ,W ,W /W2W NW6W!W2W\"W2W\"W2W\"W2W\"W2W M~Y2WCVEW NW6W MW6W MW6W MW6W IWCX EW3W L" +"WCX IV=V=V.V$V.VFYKZFV.VFY7V.V$V&V 0XCW ;Y =WFT >~T-~\\'w Ku%W4W W4W GXEW >WFW IV #q =V 6~X JSN^ /VEWCW?W=ZDW .W !W :~W" +" 5f 9V /X4X >X .Y MX\"W:X &X Y5X >Y @X6X FcJX &d Id%X 8UAV8VAU>X8X X4X$X +X+X+X -X /X)X+X/X'X -X -XH[ @X -XCVLVCX0X@XHX(X'X-X /X'X-XXFX EW6W!WV-V%V-VGYIZHV-VGY7V-V%V%V /WDX ;X ~T-~\\'v Is" +"$W4W W4W GWDX ?XGW HV %r =V 6~X JSJ[ 0VEVAV?WX ?X6X D`IX $d Ne#X 8UAV8" +"VBU=x X4X$X +X+X+X -X /X)X+X/X'X -X -XG[ AX -XCVLVCX0X?WHX(X'X-X /X'X-X;Y *Y @X WDW EW6W!WV>V,V&V,VIYGZIV,VIY6V,V&V&W /XEW N~X'VGT =~T-~\\&u Ir#W4W NV4W HXDX ?XHX HV KX ,V 6~X JSHZ 2VDVAV?W;ZGW -W !W \"V " +"Lf :W .X6X =X 0Z LY#~ /X NX5X >X @X5Y AYFX !d >~X >d X 8UAV8VBU>z!X3X%X +X+X+X -X /X)X+X/X'X -X -XF[ BX -XCWNWCX0X?XIX(X'X-X /X'X-X:X )Y AX XDX FW6W!WV?W,V'W,VJYEZKW,VJY6W,V'W&W /XFX N~X'WHT =~T-~\\%s Gp\"W4W NV4V GXCW >WH" +"X HW LX ,V 6~X JSGY 3VDWAW@W:ZIW ,W !W \"V Lf :W .X6X =X 1Z JX#~ /X NX5X ?Y @X4X .X Md A~X Ad LX 8UAV8VBU>z!X3X%X +X+X+" +"X -X /X)X+X/X'X -X -XE[ CX -XBVNVBX0X>WIX(X'X-X /X'X-X9X *Y AX Q.X $T>Z?T0W8W HW5W\"WWCX FW6W!WXFX >V ,SBVBWCS &V \"W6W :U" +"GU *m 8XFX .VWIX(X'X/X'X/X'X/X'X/X'X KZMZ XHW6X-X/X'X/X'X/X'X/X GX XIW GW LX ;~X JSFX 3VDV?V@W9ZJW +V \"W !V V -X6X =X 2Z IX#" +"~ /X NX5X ?X ?X4X .X Jd D~X Dd IX 8UAV8VCV>z!X3X%Y ,X,Y+X -X /Y*X+X/X'X -X -XD[ DX -XBVNVBX0X>XJX(Y)X,X /Y)X,X9Y *X AX XBW FW6W!WXJX" +"(Y)X.Y)X.Y)X.Y)X.Y)X KZKZ!YJW6X,X/X'X/X'X/X'X/X GX |\"X3X$X ,X,X*X -X .X*X+X/X'X -X -XC[ EX" +" -XA\\AX0X=WJX'X)X,X .X)X,X8X *X AX XBX GW6W!WW 9X =\\KW >SEWWJX FW LX <~X JSEX 6WCV?V@W7ZMW *W #W !V !W -X6X =X 4Z GX#~ /X NX5X @X >X4X " +"/X De J~X Je DX 8U@V:WDV>|\"X3X$X ,X-Y*X -X .X*X+X/X'X -X -XB[ FX -XA\\AX0X=XKX'X*Y,X .X*Y,X8Y +X AX W WJW DW MX .VCV" +" :SDW 6VBV?V@W6b )W #W !V !V +X8X X4X /X Ad L~X Ld AX 8VAV:WDU=|\"X3X$Y -X-Y*X -X .Y+X+X/X'X -X -XA[ GX -XA\\AX0XWKVDVKW\"XLX 9WJW =Z #X :V MX AUEVKVDU/X:Y IW5W#WX@W GW6W!W=Y=W2WDWDW W=W JWCWCW\"X4W#W4W >W X4X 0X =d ~X" +" d LUAWX2X#X3X#X -X.Y)X -X -X+X+X/X'X -X -X@[ HX -X@Z@X0XW ,W7W7W=W6W W4W MX5W\"W5X MW BX FW ,W7X FWHW >WLVBVLW#YKX :WJW =Y !W :V MW @VHXJWHV-W:Y IW5W#WY>W1WDWDW W=W JWCWCW\"X4W#W4W >W W MW7X MW7X " +"MW7X MW7X EWJW AX5W GWJW AXCVCW%X0W%X0W%X0W%X0W\"V +WJX ?X 2WLT 9bKQKb)gLQMh Mi =g MW4W MV6W IX@X ?XLX CW MX 0VBV :SDW " +"7VAV?V@X5_ (W #W !V \"W +X8X XLV;VLX1Y?Y >X 9Z 2W %W )W EW7X JX5W\"X -W5X X )W 0X7Y MW6W MW ,W ,WFY ?W ,W7W7W=W6W W4W MX5W\"W5X MW AW FW ,W7X FXJX" +" =WMVBVMW#YJY ;WKX >Y W :V MW ?dId,W;Z IW5W#W=W DW4W!W )W6W DVKW >X>W HW6W W>Y>W1WDWDW W=W JWCWDX\"X4W#W4W >W ;V7W LX2X LY 4X *X1X%]JXJ]'X0X Hj L" +"Y-Y%Y IV JY LYKVKY MY5Y MYJVJY $X 2XBS 6X 2q 9X :V #\\ 7TDgFT /XFX EV )TFV>VJT #V \"W6W :UGU +XFX *V=TCU%V1V!V=TCU=X ,X1W$X1W$X1W" +"$X1W$X1W$X2X%X7X LY .X -X -X -X -X -X -X -X ,X.Y*X;XMX&Y-Y+Y-Y+Y-Y+Y-Y+Y-Y ZAZ$_3Y*X1X%X1X%X1X%X1X FX W3W$W7X MW7X MW7X MW7X MW7X MW7X MW7Z NX -X " +"-X -X -X +W ,W ,W ,W .W4W MW6W W4W W4W W4W W4W W4W 5Z IWMV=W MW7X MW7X MW7X MW7X EWKX AX5W GWKX @XDVDX$X2X$X2X$X2X$X2X\"V +XKW ?X 1WMT 7`JQKa" +"'fLQLf Kg W >WLW BX NY 1VBV :SDW 8V@V?V?W4] &V $W V \"V *Y:Y YGW>X0X$X4Y\"Y /X/Y(X -X ,Y-X+X/X'X -X -X>[ JX -X@Z@X0X;XMX%Y/Y*X ,Y/Y*X6Y -X AX ;Y3Y IXLX =WLV;VLW0X=Y ?X :Z 1W $V )W EW8Y JY7X\"X -X7Y X " +")W 0X7Y MW6W MW ,W ,WEY @W ,W7W7W=W6W X6X MY7X\"X7Y MW AW FW ,X8X EWJW Y NW :V MW >bGc,W;[ JW6X#W=W DX6X!W )W6W DVLX >W=X IW7" +"X W>Y>W1XEWEX W=W IWDWDW!Y6X#X6X >W ;W8W MX0X MY 4X *Y3Y$^LXL^&X0X Ff IY/Y#Y JV KY JYLVLY KY7Y KYKVKY #X 2XBS 6X 3t ;X :V ![ 8TCfFT .XFX FV )U" +"GV>WKT MW7X :UGU ,XFX *V=TBU&V2W!V=TBU=X -X0X&X0X&X0X&X0X&X0X&X0W%X7X KY /X -X -X -X -X -X -X -X ,X/Y)X;XMX%Y/Y)Y/Y)Y/Y)Y/Y)Y/Y Z?Z$" +"^4Y)Y3Y%Y3Y%Y3Y%Y3Y FX XEVFY\"X5Y\"X5Y\"X5Y\"X5Y!V *WLX @X /WNT 7`JQJ_&eKQKe Je :d KW4W MW8W HW>X ?XNX AX Y 1VCV 9SDW 9V?V?V?X4\\ " +" &W %W V \"V )X:X ;X 9Z CX 4X (Y KW7X AX W BW6W W )W6W DWMX ?X=X IX8X W?[?W0WEWEW NW=W IWDWDW!Y6W!W6W =W ;W8W MX0X NY 3X )Y5Y\"z%X0X C` FY/Y\"X JV " +"KX HYMVMY IX7X IYLVLY \"X 1XCS 6X 4v X ?XNX AY Y4P VBV 9SDW 9V?V?V?Y4Z %W %W V #W )X:X ;X :Z CY 4X (Y KX9Y AX ;X6X 1Y 1e /e @U@XB[JXW BX8X W )W6W CVNX >W;W IX8X X@[@X0XFWEW " +"NW=W IWDWEX!Z8X!X8X =W :W:W LX0X Y 2X (Y7Y Nv#X0X ?X AY1Y V IV JV FYNVNY GV5V GYMVMY !X 1XCS 6X 5x =X :V MZ 8T?ZBT *VDV FV 'T&T KX" +"8X :UGU ,VDV )VWNX @Y !Z6Q VBV KP>SEW 9V>WAW>X3Z &W %W V " +" #V 'XU?ZH^MZ\\ JX8X\"W?W AX9Y X *W6W CVNX ?X;X JX9Y NW@[@W/XFWFX NW=W IXEWEX!Z8X!X8W ;W ;W;X MX.X\"Y 1X 'Y9Y Lt\"X0X ?X @Y3Y MT HV IT Dj ET3T EYNVN" +"Y X 0XDS 6X 6ZM`LY >X :V LY 7T)T (UCU ET(T JX9Y :UGU ,UCU )V;m.V3V NV;mCY7P HX.X(X.X(X.X(X.X(X.X(X.X(X6X IY.R&X -X -X -X -" +"X -X -X -X ,X2Z'X9a$Z3Y&Z3Y&Z3Y&Z3Y&Z3Y!Z9Z&Z3Y&Y5Y#Y5Y#Y5Y#Y5Y EX `" +" >Y !Y8S MX +VBV KQ?SFX 9V=VAV=Y6] &V &W NV BX 1X 1V 'Y>Y :X X:W JY;Z NXB]BX.XGWGX MW=W H" +"XFWFX [:X NX:X ;W :WX HXX 9X =Z 1P2Z 3X GQ5Z GX=Y @X 9Y:Y KP8Z GX -X 4^ 1^ +X 5U?gM_9W,W%X7Z L[4U&X6]%X -X )[2X+X/X'X -X -X9[ X -X&X0X8`\"Z7Z'X )Z7Z'X3X%T2Y ?X 9Z9Z E` :" +"_9_3Y7Y BX >Z -W #W +W DX=\\ J\\=Y LY7P HY=\\ LY5R JW -Y?] MW6W MW ,W ,W@Y EW ,W7W7W=W6W MYX LX.X#Y 0X %Y=Z Gl MX0X ?X ?Z7Z JP FV GP @f AP/P Ah MX " +"/YFSDP BX 8ZFVEY @X :V JX 7V.U %SAS CU.U HZ\\=Y B^ 7r Gr Gr Gr Gr KV (_ BX )Y S 8RBSCR <] 2\\ GW4W KZBZ HX;W >_ <[ " +" $[=U MX ,VBV JUCSHY :V;WCW<[Z 0R5Z 2X GT9[ GY?Z AY 9[>[ KR;Z FX -X 1[ 1[ (X 5V>dL^9X,X&X9[ J[7W&X9_$X " +"-X (\\6Z+X/X'X -X -X8[!X -X&X0X8`![;[&X ([;[&X3Y&W7[ ?X 8Z;Z D` :^7^3X5Y CX ?Z ,W #W +W DY?] J]?Y KZ:R GY?] LZ8T JW -ZA^ MW6W MW ,W ,W?Y FW ,W7W7" +"W=W6W LY>Y J]?Y KY?] MW /T9X DX ,Y@] CWNW 9]>]'Y@Y =^ AY IW :V MW HYCXNW L\\>Y VAX >Y>Y LY ,W6W B] >X9X K[>[ MXDVMVDX,YIWIY LW=W GYHWHY N]>Y LY" +">Y :X :X@X LX,X%Y /X $ZAZ Ch KX0X ?X >[;[ ?V 6d >f LX /[HSFR BX 9Z3Y AX :V IX 7V1V #R@R BU0U G[>[ :UGU ,R@R 'V(U)V6W" +" LV(UU IX,X*X,X*X,X*X,X*X,X*X,X*W4X G[7W&X -X -X -X -X -X -X -X ,X9_%X8`![;[![;[![;[![;[![;[\"Z3Z(];[\"Z;Z NZ;Z NZ;Z NZ;Z CX Y JW6W LY>Y IY>Y IY>Y IY>Y IY>Y 2Z FY>Y HY@] KY@] KY@] KY@] B^ >]?Y A^ 6o Do Do Do " +"Do IV (_ CX (Y S (S ,[ 0[ GW4W J\\H\\ GW:W >^ :\\ %[@W MX ,VBV JXFSIZ :V:WEW:\\@e (V 'V MV BX 1X 2V $ZDZ 8X ?Z /U;] 2X GV=" +"\\ EZC[ @X 7[@[ JT?[ EX -X /Y 1Y &X 5V=bK\\7X,X&X<^ I]=Z&X=b#X -X ']:\\+X/X'X -X -X7[\"X -X&X0X7_ \\?\\%X '\\?\\%X2X&Z<\\ >X 7[?[ B^ 9^7^4Y5Y CX ?Y +W \"V +W " +" DZB_ J_CZ I[>T G[C_ K[=W JW ,\\GXNW MW6W MW ,W ,W>Y GW ,W7W7W=W6W KZBZ I_CZ J[C_ MW /W>Z DZ .ZB^ C` 8\\>\\&X>Y =\\ AY HW :V MW GZFYNY N]AZ N" +"WCX _ FX0X ?X =\\?\\ >V 5b W;[>T F[=W J[=W J[=W J[=W LW ,W ,W ,W *ZBZ IW6W KZBZ GZBZ " +"GZBZ GZBZ GZBZ 1Z F[BZ GZB^ KZB^ KZB^ KZB^ A\\ =_CZ ?\\ 3l Al Al Al Al HV (^ BX (X NS (S ,Z .Y FW4W In GX:X ?^ 9_ (]FZ MX " +",VBV J[ISL\\ :V9XGX9^Fi )W )W MV BX 1X 3W #[H[ Et Mx MZC_ 1X GZD^ C[G\\ @Y 7^F] IXF] DX -X ,V 1V #X 4V<^IY5X*X'y G_D^&{!y NX &`B`+X/X'X -X -X6[#" +"w LX&X0X7_ N^E^$X &^E^$X2Y'^C^ =X 7^E^ B^ 8]7]4Y3Y DX @~U&W \"W ,W C\\HYNW JWNXG\\ H]EX F\\GXNW J]D[ JW +kMW MW6W MW ,W ,W=Y HW ,W7W7W=W6W K]H] IWNX" +"G\\ I\\GXNW MW /[E\\ Be 9[GXNW B^ 7\\>\\'XP @W8W 3~W :_GaKP @UGU ,P>P 'V&U+V6V KV&" +"U;]GZ JX*X,X*X,X*X,X*X,X*X,Y,Y,X4y7_D^&y Ny Ny Ny NX -X -X -X ,{\"X7_ N^E^ L^E^ L^E^ L^E^ L^E^ MV/V(dE^ N^E^ L^E^ L^E^ L^E^ BX \\ Av 6W :V MW FkL]$u LXGX 9p Hp EW6W A[ ?X6X LpN\\#" +"hKh)s JW<] Lu LWNm Hp 6` Bl K~W'x MX 1iEi HX CX0X ?X ;u X :V HW 3X=X )X\\ /c 8c 8c 8c 8c CV '\\ ?T %W U *T *W ,V DW4W Gj EW8W " +">\\ 5~P In LX -VBV Is 9V7g6qJZ *V )V LV BX 1X 3V !l Dt Mx Mt /X Gr ?m ?X 4r Hm BX -X &P 1P LX 3V 3X*X'w Cv%x My NX #x(X/X'X" +" -X -X4[%w LX&X0X5] Ls\"X $s\"X1Y(w ;X 5s ?\\ 7\\5\\5Y1Y EX @~U&W !V ,W BjLW JWMj Dn DjMW Hr JW )hLW MW6W MW ,W ,W;Y JW ,W7W7W=W6W In GWMj EjMW MW /p" +" ?d 8iLW B^ 6Z<[)Y:Y >Z @v 6W :V MW EiK]$t JYLZ 7n Fo EW6W A[ ?X5W LWNfM\\\"gKg'q IW<] Ks KWMk Fn 5` Aj J~W'x MX 1iEi HX CX0X ?X :s ;V 2\\ 6" +"^ HX +n Lz MR,R =X :V HW 1ZEZ %ZDZ 0~W :WNfM\\ @UGU !V%U,V6i/V%U9n JX*X,X*X,X*X,X*X,X*X,X*X-X3y5v%y Ny Ny Ny NX -X -X -X ," +"x NX5] Ls Hs Hs Hs Hs IR+R(WMs Js Hs Hs Hs @X R $V NU *U *U *U DW4W Fh DW8X ?\\ 4~ Hl KX -VBV Hp 8V5e4nGZ +W +W LV BX" +" 1X 3V j Ct Mx Mr -X Gq =j >Y 3p Gl AX -X 2X 3W 5X(X(u ?s$v Ky NX \"v'X/X'X -X -X3[&w LX&X0X5] Kq!X #p X0X(v :X 4p =\\ 7\\5\\6Y/Y FX @~U&W !V ,W " +" AhKW JWLh Bm ChLW Gq JW (eJW MW6W MW ,W ,W:Y KW ,W7W7W=W6W Hl FWLh ChLW MW /o >d 7gKW A\\ 5ZZ @v 6W :V MW DgI\\$s He 5l Dn EW6W @Y " +">W4X MWMeM\\!eIe%o HW<] Jq JWLi Dk 2_ @h J~Y(x MX 1iEi HX CX0X ?X 9q :V 1Z 4\\ GX *m Lz LP*P X X ?v 6W :V MW CeG[$r Fc 2h Am EW6W @Y ?X3W MWMdL\\ cGc#m GW;\\ Hm HWKg Ah /] ?f I~Y(x MX 1iEi HX CX0X ?X 7m 8V 0" +"X 2Z FX (j Kz AX :V HW -g Lh ,~W :WMdL\\ @UGU \"V$U-V5i0V$U7i HX(X.X(X.X(X.X(X.X(X.X(X/X2y1o\"y Ny Ny Ny NX -X -X -X ,t" +" JX4\\ Im Bm Bm Bm Bm %VHm Dm Bm Bm Bm =X eJW GeJW" +" GeJW GeJW ?X ;WJe 9X MW &Z =U W ,W *R &Q BW4W B` AW6W >[ /y Dd GX -VCV Af 5V2a.gBZ ,W -W KV CX 0X 4V " +" Kd @t Mx Km *X Ek 6d ;X .h Bh >X .X 1X 1W 7X(X(q 7j Np Ey NX Mm\"X/X'X -X -X1[(w LX&X0X4\\ Gi LX Ni LX/X$n 7X 0i 9Z 5[5[6Y-Y GX @~U&W V -W " +" >cIW JWIb k EW6W @Y ?" +"W2W MWK`I[ NaEa i EW;\\ Fi FWIc >e ,\\ =b G~Y(x MX 1iEi HX CX0X ?X 5i 6V /V 0X EX &f Iz AX :V /P;W *c Gb )~W :WK`I[ @UGU " +" #V#U.V4i1V#U6f FX(X.X(X.X(X.X(X.X(X.X(X/X2y/j Ny Ny Ny Ny NX -X -X -X ,p FX4\\ Gi >i >i >i >i $VEi @i >i >i >i ;X i0g ;i >i >i >i HW ,W ,W ,W #d BW6W Ef ;f ;f ;f ;f JUJe ;cIW FcIW FcIW FcIW ?X ;WIb 7X MW %Y =T X -X )P %P AW4W ?Z" +" >W6X ?Z ,w B` EX .VBV <] 1V0]*b?[ -W -W KV CW /X 4V I` >t Mx Hg 'X Bf 2` :X +d =b ;X .W 0X 1X 9X&X)m 0d Kj ?y NX Jg " +"NX/X'X -X -X0[)w LX&X0X3[ Dc IX Kf LX/Y!g 4X .e 7Z 5Z3Z7Y+Y HX @~U&W V -W =`GW JWG^ 7b 9^GW Ad CW \"YDW MW6W MW ,W ,W7Y NW ,W7W7W=W6W B` @WG^ 9" +"^GW MW (c 2] 3_GW @Z 3X:X*Y4Y @X ?v 6W :V MW ?_AW$WKb @^ +` 9g CW6W ?W ?X2X NWJ^GY K]B^ Ke CW:[ Dd CWG_ 9` 'Y ;^ F~[)x MX 1iEi HX CX0X ?X 2c " +"3V .T .V DX $b Gz AX :V /R>X &[ ?Z %~W :WJ^GY ?UGU #V +V +V 1b EX&X0X&X0X&X0X&X0X&X0Y'X1X1y,d Ky Ny Ny Ny NX -X -X " +"-X ,j @X3[ Dc 8c 8c 8c 8c !VBc ;e :e :e :e 9X Y BS .V,W#Z ;V -V 7W ;W EX ;\\ 6] " +"+Z 5\\ 5Z WGXBU FX=X E` \"W >] @WDY 3Z 2X C[ >T :[ KV /TAY " +" EWGXBU =UGU BT 6V +V +V ,Y ?\\ +[ 0[ 0[ 0[ 0[ KT=[ 2[ 0[ 0[ 0[ 7Z ;Y .Y .Y .Y .Y .Y -" +"Y2\\\"Z /\\ 1\\ 1\\ 1\\ CZ 3Z /Z /Z /Z /Z FVCZ 1Y .Y .Y .Y ,W :WDX 2W LW 7R #S" +" >W /W 8W :V \"W 5X )X &Z CW NV .W :W %W" +" @W :W -X -W :V MW LW FW ?W >W NW 0W =W 3S GV /XGZ " +" DW HUGU AT %T 'R JT " +" #T (X :W NX LW 7S =V /V 7W :V \"W" +" 4X'Q &Y %Z DW NV .W :W %W @W :W -W ,W :V MW " +" LW FW ?W >W NW 0W =W 3S GV /j CW HUGU @T " +" %T 'P HT \"Q 'W 9W NW KW " +" 7S =W 1W 7V :W \"V 2X)R &X #Z " +" EW NW /W :W %W @W :W -W ,X ;V NX LW FW ?W >W NW 0W =W " +" 3S GV /j CW HUGU @U &U " +" U \"P 'W 9W NW KV 6S " +" W NW 0W =W 3S GV /h " +" AW HUGU ?T %T NT " +" )X 9W X KV 6S W NW 0W =W 3S GV .f @W HUGU ?U &" +"U U *W 8W W JV " +" 6S ;V 3V 6V :W \"V .[5[ *Y Z " +" Ha (W :a W NW 0W =W " +" 3S GV +a >W HUGU >T %T " +" NT +X 8W !X (VIV 6S :V 5V 5U" +" 9W \"U +\\;] )X MZ Ia (W :a =Y %W ?W :W " +" /W )[ ?V #[ KW FW ?W >W NW 0W =W 3S GV 'Z ;W " +" HUGU >U &U U ,W 7W !" +"W 'VIV 6S :V 6W 6V 4V *_C` " +" )Y LZ Ja :a (P7Y $W ?W :W 0X (b GV +b JW FW ?W >W " +" NW 0W =W 3S GV 7W HUGU >U &U " +" U -X 7W \"X 'VJW " +" 6S 9V 7V 5U 3U 'x (Z KZ Ka :a " +" (R:Z $W ?W :W 0X (b GV +b JW FW ?W >W NW 0W =W 3S " +" GV 7W #U &U U " +" -X 7W \"X &UJW 6S 9W 9W " +" Bu ([ IZ La :a (T>[ $X ?W :W 1X &a GV +a " +" IW FW ?W >W NW 0W =W 3S GV 7W $V " +" 'V !V .X 6W #X %VLW " +" 5S 2p -a " +" 8XE] %Y >W :W 3Z $_ GV +_ GW FW ?W >W NW 0W =W " +" 3S GV 7W /QGW 2QGW ,QG" +"W 0Z 6W %Z %a 5S " +" 0l +a 8p +_ >W :W ;a !] G" +"V +] EW FW ?W >W NW 0W =W 3S GV 7W /` " +" 1` +` 7a 5W -a #` " +" >e '` " +" 7o *^ =W :W ;` KY GV +Y AW FW ?W >W NW 0W =W " +" 3S GV 7W /` 1` +` " +" 7` 4W -` \"_ " +" 8\\ #_ \"} 3n )^ =W :W ;` 9V " +" BW FW ?W >W NW 0W =W 'V 7W /_ " +" 0_ *_ 6` 4W -` !] " +" -] " +" } 3l '] W NW 0W =W " +" 'V 7W /^ /^ )^ " +" 5_ 3W -_ N[ " +" ,[ M} 2j &\\ ;W :W ;^ 7V BW " +" FW ?W >W NW 0W =W 7W -Y *Y " +" $Y 2^ 2W -^ LX " +" *X J} " +" /d #Z 9W :W ;\\ 5V BW FW ?W >W NW 0W =W " +" 7W " +" /\\ 0W HT " +" I} *[ NW 6W :W ;Z 3V BW FW ?W >W" +" NW 0W =W 7W " +" /Z .W " +" =} " +" " +" D" }; + + // Define a 40x38 'danger' color logo (used by cimg::dialog()). + static const unsigned char logo40x38[4576] = { + 177,200,200,200,3,123,123,0,36,200,200,200,1,123,123,0,2,255,255,0,1,189,189,189,1,0,0,0,34,200,200,200, + 1,123,123,0,4,255,255,0,1,189,189,189,1,0,0,0,1,123,123,123,32,200,200,200,1,123,123,0,5,255,255,0,1,0,0, + 0,2,123,123,123,30,200,200,200,1,123,123,0,6,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,29,200,200,200, + 1,123,123,0,7,255,255,0,1,0,0,0,2,123,123,123,28,200,200,200,1,123,123,0,8,255,255,0,1,189,189,189,1,0,0,0, + 2,123,123,123,27,200,200,200,1,123,123,0,9,255,255,0,1,0,0,0,2,123,123,123,26,200,200,200,1,123,123,0,10,255, + 255,0,1,189,189,189,1,0,0,0,2,123,123,123,25,200,200,200,1,123,123,0,3,255,255,0,1,189,189,189,3,0,0,0,1,189, + 189,189,3,255,255,0,1,0,0,0,2,123,123,123,24,200,200,200,1,123,123,0,4,255,255,0,5,0,0,0,3,255,255,0,1,189, + 189,189,1,0,0,0,2,123,123,123,23,200,200,200,1,123,123,0,4,255,255,0,5,0,0,0,4,255,255,0,1,0,0,0,2,123,123,123, + 22,200,200,200,1,123,123,0,5,255,255,0,5,0,0,0,4,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,21,200,200,200, + 1,123,123,0,5,255,255,0,5,0,0,0,5,255,255,0,1,0,0,0,2,123,123,123,20,200,200,200,1,123,123,0,6,255,255,0,5,0,0, + 0,5,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,19,200,200,200,1,123,123,0,6,255,255,0,1,123,123,0,3,0,0,0,1, + 123,123,0,6,255,255,0,1,0,0,0,2,123,123,123,18,200,200,200,1,123,123,0,7,255,255,0,1,189,189,189,3,0,0,0,1,189, + 189,189,6,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,17,200,200,200,1,123,123,0,8,255,255,0,3,0,0,0,8,255,255, + 0,1,0,0,0,2,123,123,123,16,200,200,200,1,123,123,0,9,255,255,0,1,123,123,0,1,0,0,0,1,123,123,0,8,255,255,0,1,189, + 189,189,1,0,0,0,2,123,123,123,15,200,200,200,1,123,123,0,9,255,255,0,1,189,189,189,1,0,0,0,1,189,189,189,9,255, + 255,0,1,0,0,0,2,123,123,123,14,200,200,200,1,123,123,0,11,255,255,0,1,0,0,0,10,255,255,0,1,189,189,189,1,0,0,0,2, + 123,123,123,13,200,200,200,1,123,123,0,23,255,255,0,1,0,0,0,2,123,123,123,12,200,200,200,1,123,123,0,11,255,255,0, + 1,189,189,189,2,0,0,0,1,189,189,189,9,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,11,200,200,200,1,123,123,0,11, + 255,255,0,4,0,0,0,10,255,255,0,1,0,0,0,2,123,123,123,10,200,200,200,1,123,123,0,12,255,255,0,4,0,0,0,10,255,255,0, + 1,189,189,189,1,0,0,0,2,123,123,123,9,200,200,200,1,123,123,0,12,255,255,0,1,189,189,189,2,0,0,0,1,189,189,189,11, + 255,255,0,1,0,0,0,2,123,123,123,9,200,200,200,1,123,123,0,27,255,255,0,1,0,0,0,3,123,123,123,8,200,200,200,1,123, + 123,0,26,255,255,0,1,189,189,189,1,0,0,0,3,123,123,123,9,200,200,200,1,123,123,0,24,255,255,0,1,189,189,189,1,0,0, + 0,4,123,123,123,10,200,200,200,1,123,123,0,24,0,0,0,5,123,123,123,12,200,200,200,27,123,123,123,14,200,200,200,25, + 123,123,123,86,200,200,200,91,49,124,118,124,71,32,124,95,49,56,114,52,82,121,0 }; + + //! Get/set default output stream for the \CImg library messages. + /** + \param file Desired output stream. Set to \c 0 to get the currently used output stream only. + \return Currently used output stream. + **/ + inline std::FILE* output(std::FILE *file) { + cimg::mutex(1); + static std::FILE *res = cimg::_stderr(); + if (file) res = file; + cimg::mutex(1,0); + return res; + } + + // Return number of available CPU cores. + inline unsigned int nb_cpus() { + unsigned int res = 1; +#if cimg_OS==2 + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + res = (unsigned int)sysinfo.dwNumberOfProcessors; +#elif cimg_OS == 1 + res = (unsigned int)sysconf(_SC_NPROCESSORS_ONLN); +#endif + return res?res:1U; + } + + // Lock/unlock mutex for CImg multi-thread programming. + inline int mutex(const unsigned int n, const int lock_mode) { + switch (lock_mode) { + case 0 : cimg::Mutex_attr().unlock(n); return 0; + case 1 : cimg::Mutex_attr().lock(n); return 0; + default : return cimg::Mutex_attr().trylock(n); + } + } + + //! Display a warning message on the default output stream. + /** + \param format C-string containing the format of the message, as with std::printf(). + \note If configuration macro \c cimg_strict_warnings is set, this function throws a + \c CImgWarningException instead. + \warning As the first argument is a format string, it is highly recommended to write + \code + cimg::warn("%s",warning_message); + \endcode + instead of + \code + cimg::warn(warning_message); + \endcode + if \c warning_message can be arbitrary, to prevent nasty memory access. + **/ + inline void warn(const char *const format, ...) { + if (cimg::exception_mode()>=1) { + char *const message = new char[16384]; + std::va_list ap; + va_start(ap,format); + cimg_vsnprintf(message,16384,format,ap); + va_end(ap); +#ifdef cimg_strict_warnings + throw CImgWarningException(message); +#else + std::fprintf(cimg::output(),"\n%s[CImg] *** Warning ***%s%s\n",cimg::t_red,cimg::t_normal,message); +#endif + delete[] message; + } + } + + // Execute an external system command. + /** + \param command C-string containing the command line to execute. + \param module_name Module name. + \return Status value of the executed command, whose meaning is OS-dependent. + \note This function is similar to std::system() + but it does not open an extra console windows + on Windows-based systems. + **/ + inline int system(const char *const command, const char *const module_name=0) { + cimg::unused(module_name); +#ifdef cimg_no_system_calls + return -1; +#else +#if cimg_OS==1 + const unsigned int l = (unsigned int)std::strlen(command); + if (l) { + char *const ncommand = new char[l + 16]; + std::strncpy(ncommand,command,l); + std::strcpy(ncommand + l," 2> /dev/null"); // Make command silent. + const int out_val = std::system(ncommand); + delete[] ncommand; + return out_val; + } else return -1; +#elif cimg_OS==2 + PROCESS_INFORMATION pi; + STARTUPINFO si; + std::memset(&pi,0,sizeof(PROCESS_INFORMATION)); + std::memset(&si,0,sizeof(STARTUPINFO)); + GetStartupInfo(&si); + si.cb = sizeof(si); + si.wShowWindow = SW_HIDE; + si.dwFlags |= SW_HIDE | STARTF_USESHOWWINDOW; + const BOOL res = CreateProcess((LPCTSTR)module_name,(LPTSTR)command,0,0,FALSE,0,0,0,&si,&pi); + if (res) { + WaitForSingleObject(pi.hProcess,INFINITE); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return 0; + } else return std::system(command); +#else + return std::system(command); +#endif +#endif + } + + //! Return a reference to a temporary variable of type T. + template + inline T& temporary(const T&) { + static T temp; + return temp; + } + + //! Exchange values of variables \c a and \c b. + template + inline void swap(T& a, T& b) { T t = a; a = b; b = t; } + + //! Exchange values of variables (\c a1,\c a2) and (\c b1,\c b2). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2) { + cimg::swap(a1,b1); cimg::swap(a2,b2); + } + + //! Exchange values of variables (\c a1,\c a2,\c a3) and (\c b1,\c b2,\c b3). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3) { + cimg::swap(a1,b1,a2,b2); cimg::swap(a3,b3); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a4) and (\c b1,\c b2,...,\c b4). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4) { + cimg::swap(a1,b1,a2,b2,a3,b3); cimg::swap(a4,b4); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a5) and (\c b1,\c b2,...,\c b5). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4); cimg::swap(a5,b5); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a6) and (\c b1,\c b2,...,\c b6). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5); cimg::swap(a6,b6); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a7) and (\c b1,\c b2,...,\c b7). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6); cimg::swap(a7,b7); + } + + //! Exchange values of variables (\c a1,\c a2,...,\c a8) and (\c b1,\c b2,...,\c b8). + template + inline void swap(T1& a1, T1& b1, T2& a2, T2& b2, T3& a3, T3& b3, T4& a4, T4& b4, T5& a5, T5& b5, T6& a6, T6& b6, + T7& a7, T7& b7, T8& a8, T8& b8) { + cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7); cimg::swap(a8,b8); + } + + //! Return the endianness of the current architecture. + /** + \return \c false for Little Endian or \c true for Big Endian. + **/ + inline bool endianness() { + const int x = 1; + return ((unsigned char*)&x)[0]?false:true; + } + + //! Reverse endianness of all elements in a memory buffer. + /** + \param[in,out] buffer Memory buffer whose endianness must be reversed. + \param size Number of buffer elements to reverse. + **/ + template + inline void invert_endianness(T* const buffer, const cimg_ulong size) { + if (size) switch (sizeof(T)) { + case 1 : break; + case 2 : { for (unsigned short *ptr = (unsigned short*)buffer + size; ptr>(unsigned short*)buffer; ) { + const unsigned short val = *(--ptr); + *ptr = (unsigned short)((val>>8)|((val<<8))); + } + } break; + case 4 : { for (unsigned int *ptr = (unsigned int*)buffer + size; ptr>(unsigned int*)buffer; ) { + const unsigned int val = *(--ptr); + *ptr = (val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24); + } + } break; + default : { for (T* ptr = buffer + size; ptr>buffer; ) { + unsigned char *pb = (unsigned char*)(--ptr), *pe = pb + sizeof(T); + for (int i = 0; i<(int)sizeof(T)/2; ++i) swap(*(pb++),*(--pe)); + } + } + } + } + + //! Reverse endianness of a single variable. + /** + \param[in,out] a Variable to reverse. + \return Reference to reversed variable. + **/ + template + inline T& invert_endianness(T& a) { + invert_endianness(&a,1); + return a; + } + + // Conversion functions to get more precision when trying to store unsigned ints values as floats. + inline unsigned int float2uint(const float f) { + int tmp = 0; + std::memcpy(&tmp,&f,sizeof(float)); + if (tmp>=0) return (unsigned int)f; + unsigned int u; + // use memcpy instead of assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&u,&f,sizeof(float)); + return ((u)<<1)>>1; // set sign bit to 0. + } + + inline float uint2float(const unsigned int u) { + if (u<(1U<<19)) return (float)u; // Consider safe storage of unsigned int as floats until 19bits (i.e 524287). + float f; + const unsigned int v = u|(1U<<(8*sizeof(unsigned int)-1)); // set sign bit to 1. + // use memcpy instead of simple assignment to avoid undesired optimizations by C++-compiler. + std::memcpy(&f,&v,sizeof(float)); + return f; + } + + //! Return the value of a system timer, with a millisecond precision. + /** + \note The timer does not necessarily starts from \c 0. + **/ + inline cimg_ulong time() { +#if cimg_OS==1 + struct timeval st_time; + gettimeofday(&st_time,0); + return (cimg_ulong)(st_time.tv_usec/1000 + st_time.tv_sec*1000); +#elif cimg_OS==2 + SYSTEMTIME st_time; + GetLocalTime(&st_time); + return (cimg_ulong)(st_time.wMilliseconds + 1000*(st_time.wSecond + 60*(st_time.wMinute + 60*st_time.wHour))); +#else + return 0; +#endif + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_ulong tictoc(const bool is_tic); + + //! Start tic/toc timer for time measurement between code instructions. + /** + \return Current value of the timer (same value as time()). + **/ + inline cimg_ulong tic() { + return cimg::tictoc(true); + } + + //! End tic/toc timer and displays elapsed time from last call to tic(). + /** + \return Time elapsed (in ms) since last call to tic(). + **/ + inline cimg_ulong toc() { + return cimg::tictoc(false); + } + + //! Sleep for a given numbers of milliseconds. + /** + \param milliseconds Number of milliseconds to wait for. + \note This function frees the CPU ressources during the sleeping time. + It can be used to temporize your program properly, without wasting CPU time. + **/ + inline void sleep(const unsigned int milliseconds) { +#if cimg_OS==1 + struct timespec tv; + tv.tv_sec = milliseconds/1000; + tv.tv_nsec = (milliseconds%1000)*1000000; + nanosleep(&tv,0); +#elif cimg_OS==2 + Sleep(milliseconds); +#else + cimg::unused(milliseconds); +#endif + } + + inline unsigned int _wait(const unsigned int milliseconds, cimg_ulong& timer) { + if (!timer) timer = cimg::time(); + const cimg_ulong current_time = cimg::time(); + if (current_time>=timer + milliseconds) { timer = current_time; return 0; } + const unsigned int time_diff = (unsigned int)(timer + milliseconds - current_time); + timer = current_time + time_diff; + cimg::sleep(time_diff); + return time_diff; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \return Number of milliseconds elapsed since the last call to wait(). + \note Same as sleep() with a waiting time computed with regard to the last call + of wait(). It may be used to temporize your program properly, without wasting CPU time. + **/ + inline cimg_long wait(const unsigned int milliseconds) { + cimg::mutex(3); + static cimg_ulong timer = 0; + if (!timer) timer = cimg::time(); + cimg::mutex(3,0); + return _wait(milliseconds,timer); + } + + // Random number generators. + // CImg may use its own Random Number Generator (RNG) if configuration macro 'cimg_use_rng' is set. + // Use it for instance when you have to deal with concurrent threads trying to call std::srand() + // at the same time! +#ifdef cimg_use_rng + +#include + + // Use a custom RNG. + inline unsigned int _rand(const unsigned int seed=0, const bool set_seed=false) { + static cimg_ulong next = 0xB16B00B5; + cimg::mutex(4); + if (set_seed) next = (cimg_ulong)seed; + next = next*1103515245 + 12345U; + cimg::mutex(4,0); + return (unsigned int)(next&0xFFFFFFU); + } + + inline void srand() { + const unsigned int t = (unsigned int)cimg::time(); +#if cimg_OS==1 + cimg::_rand(t + (unsigned int)getpid(),true); +#elif cimg_OS==2 + cimg::_rand(t + (unsigned int)_getpid(),true); +#else + cimg::_rand(t,true); +#endif + } + + inline void srand(const unsigned int seed) { + _rand(seed,true); + } + + inline double rand(const double val_min, const double val_max) { + const double val = cimg::_rand()/16777215.; + return val_min + (val_max - val_min)*val; + } + +#else + + // Use the system RNG. + inline void srand() { + const unsigned int t = (unsigned int)cimg::time(); +#if cimg_OS==1 || defined(__BORLANDC__) + std::srand(t + (unsigned int)getpid()); +#elif cimg_OS==2 + std::srand(t + (unsigned int)_getpid()); +#else + std::srand(t); +#endif + } + + inline void srand(const unsigned int seed) { + std::srand(seed); + } + + //! Return a random variable uniformely distributed between [val_min,val_max]. + /** + **/ + inline double rand(const double val_min, const double val_max) { + const double val = (double)std::rand()/RAND_MAX; + return val_min + (val_max - val_min)*val; + } +#endif + + //! Return a random variable uniformely distributed between [0,val_max]. + /** + **/ + inline double rand(const double val_max=1) { + return cimg::rand(0,val_max); + } + + //! Return a random variable following a gaussian distribution and a standard deviation of 1. + /** + **/ + inline double grand() { + double x1, w; + do { + const double x2 = cimg::rand(-1,1); + x1 = cimg::rand(-1,1); + w = x1*x1 + x2*x2; + } while (w<=0 || w>=1.0); + return x1*std::sqrt((-2*std::log(w))/w); + } + + //! Return a random variable following a Poisson distribution of parameter z. + /** + **/ + inline unsigned int prand(const double z) { + if (z<=1.0e-10) return 0; + if (z>100) return (unsigned int)((std::sqrt(z) * cimg::grand()) + z); + unsigned int k = 0; + const double y = std::exp(-z); + for (double s = 1.0; s>=y; ++k) s*=cimg::rand(); + return k - 1; + } + + //! Cut (i.e. clamp) value in specified interval. + template + inline T cut(const T& val, const t& val_min, const t& val_max) { + return valval_max?(T)val_max:val; + } + + //! Bitwise-rotate value on the left. + template + inline T rol(const T& a, const unsigned int n=1) { + return n?(T)((a<>((sizeof(T)<<3) - n))):a; + } + + inline float rol(const float a, const unsigned int n=1) { + return (float)rol((int)a,n); + } + + inline double rol(const double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + + inline double rol(const long double a, const unsigned int n=1) { + return (double)rol((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half rol(const half a, const unsigned int n=1) { + return (half)rol((int)a,n); + } +#endif + + //! Bitwise-rotate value on the right. + template + inline T ror(const T& a, const unsigned int n=1) { + return n?(T)((a>>n)|(a<<((sizeof(T)<<3) - n))):a; + } + + inline float ror(const float a, const unsigned int n=1) { + return (float)ror((int)a,n); + } + + inline double ror(const double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + + inline double ror(const long double a, const unsigned int n=1) { + return (double)ror((cimg_long)a,n); + } + +#ifdef cimg_use_half + inline half ror(const half a, const unsigned int n=1) { + return (half)ror((int)a,n); + } +#endif + + //! Return absolute value of a value. + template + inline T abs(const T& a) { + return a>=0?a:-a; + } + inline bool abs(const bool a) { + return a; + } + inline int abs(const unsigned char a) { + return (int)a; + } + inline int abs(const unsigned short a) { + return (int)a; + } + inline int abs(const unsigned int a) { + return (int)a; + } + inline int abs(const int a) { + return std::abs(a); + } + inline cimg_int64 abs(const cimg_uint64 a) { + return (cimg_int64)a; + } + inline double abs(const double a) { + return std::fabs(a); + } + inline float abs(const float a) { + return (float)std::fabs((double)a); + } + + //! Return square of a value. + template + inline T sqr(const T& val) { + return val*val; + } + + //! Return 1 + log_10(x) of a value \c x. + inline int xln(const int x) { + return x>0?(int)(1 + std::log10((double)x)):1; + } + + //! Return the minimum between two values. + // (kept for compatibility reasons). + template + inline t min(const t& a, const t& b) { + return std::min(a,b); + } + + //! Return the minimum between three values. + template + inline t min(const t& a, const t& b, const t& c) { + return std::min(std::min(a,b),c); + } + + //! Return the minimum between four values. + template + inline t min(const t& a, const t& b, const t& c, const t& d) { + return std::min(std::min(a,b),std::min(c,d)); + } + + //! Return the maximum between two values. + // (kept for compatibility reasons). + template + inline t max(const t& a, const t& b) { + return std::max(a,b); + } + + //! Return the maximum between three values. + template + inline t max(const t& a, const t& b, const t& c) { + return std::max(std::max(a,b),c); + } + + //! Return the maximum between four values. + template + inline t max(const t& a, const t& b, const t& c, const t& d) { + return std::max(std::max(a,b),std::max(c,d)); + } + + //! Return the sign of a value. + template + inline T sign(const T& x) { + return (T)(x<0?-1:x>0); + } + + //! Return the nearest power of 2 higher than given value. + template + inline cimg_ulong nearest_pow2(const T& x) { + cimg_ulong i = 1; + while (x>i) i<<=1; + return i; + } + + //! Return the sinc of a given value. + inline double sinc(const double x) { + return x?std::sin(x)/x:1; + } + + //! Return the modulo of a value. + /** + \param x Input value. + \param m Modulo value. + \note This modulo function accepts negative and floating-points modulo numbers, as well as variables of any type. + **/ + template + inline T mod(const T& x, const T& m) { + const double dx = (double)x, dm = (double)m; + return (T)(dx - dm * std::floor(dx / dm)); + } + inline int mod(const bool x, const bool m) { + return m?(x?1:0):0; + } + inline int mod(const unsigned char x, const unsigned char m) { + return x%m; + } + inline int mod(const char x, const char m) { +#if defined(CHAR_MAX) && CHAR_MAX==255 + return x%m; +#else + return x>=0?x%m:(x%m?m + x%m:0); +#endif + } + inline int mod(const unsigned short x, const unsigned short m) { + return x%m; + } + inline int mod(const short x, const short m) { + return x>=0?x%m:(x%m?m + x%m:0); + } + inline int mod(const unsigned int x, const unsigned int m) { + return (int)(x%m); + } + inline int mod(const int x, const int m) { + return x>=0?x%m:(x%m?m + x%m:0); + } + inline cimg_int64 mod(const cimg_uint64 x, const cimg_uint64 m) { + return x%m; + } + inline cimg_int64 mod(const cimg_int64 x, const cimg_int64 m) { + return x>=0?x%m:(x%m?m + x%m:0); + } + + //! Return the min-mod of two values. + /** + \note minmod(\p a,\p b) is defined to be: + - minmod(\p a,\p b) = min(\p a,\p b), if \p a and \p b have the same sign. + - minmod(\p a,\p b) = 0, if \p a and \p b have different signs. + **/ + template + inline T minmod(const T& a, const T& b) { + return a*b<=0?0:(a>0?(a + inline T round(const T& x) { + return (T)std::floor((_cimg_Tfloat)x + 0.5f); + } + + //! Return rounded value. + /** + \param x Value to be rounded. + \param y Rounding precision. + \param rounding_type Type of rounding operation (\c 0 = nearest, \c -1 = backward, \c 1 = forward). + \return Rounded value, having the same type as input value \c x. + **/ + template + inline T round(const T& x, const double y, const int rounding_type=0) { + if (y<=0) return x; + if (y==1) switch (rounding_type) { + case 0 : return round(x); + case 1 : return (T)std::ceil((_cimg_Tfloat)x); + default : return (T)std::floor((_cimg_Tfloat)x); + } + const double sx = (double)x/y, floor = std::floor(sx), delta = sx - floor; + return (T)(y*(rounding_type<0?floor:rounding_type>0?std::ceil(sx):delta<0.5?floor:std::ceil(sx))); + } + + //! Return x^(1/3). + template + inline double cbrt(const T& x) { +#if cimg_use_cpp11==1 + return std::cbrt(x); +#else + return x>=0?std::pow((double)x,1.0/3):-std::pow(-(double)x,1.0/3); +#endif + } + + // Code to compute fast median from 2,3,5,7,9,13,25 and 49 values. + // (contribution by RawTherapee: http://rawtherapee.com/). + template + inline T median(T val0, T val1) { + return (val0 + val1)/2; + } + + template + inline T median(T val0, T val1, T val2) { + return std::max(std::min(val0,val1),std::min(val2,std::max(val0,val1))); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = std::max(val0,tmp); val1 = std::min(val1,val4); tmp = std::min(val1,val2); val2 = std::max(val1,val2); + val1 = tmp; tmp = std::min(val2,val3); + return std::max(val1,tmp); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6) { + T tmp = std::min(val0,val5); + val5 = std::max(val0,val5); val0 = tmp; tmp = std::min(val0,val3); val3 = std::max(val0,val3); val0 = tmp; + tmp = std::min(val1,val6); val6 = std::max(val1,val6); val1 = tmp; tmp = std::min(val2,val4); + val4 = std::max(val2,val4); val2 = tmp; val1 = std::max(val0,val1); tmp = std::min(val3,val5); + val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); + val3 = std::max(tmp,val3); val3 = std::min(val3,val6); tmp = std::min(val4,val5); val4 = std::max(val1,tmp); + tmp = std::min(val1,tmp); val3 = std::max(tmp,val3); + return std::min(val3,val4); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8) { + T tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val7 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); + val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val6,val7); + val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val1,val2); + val2 = std::max(val1,val2); val1 = tmp; tmp = std::min(val4,val5); + val5 = std::max(val4,val5); val4 = tmp; tmp = std::min(val7,val8); + val8 = std::max(val7,val8); val3 = std::max(val0,val3); val5 = std::min(val5,val8); + val7 = std::max(val4,tmp); tmp = std::min(val4,tmp); val6 = std::max(val3,val6); + val4 = std::max(val1,tmp); val2 = std::min(val2,val5); val4 = std::min(val4,val7); + tmp = std::min(val4,val2); val2 = std::max(val4,val2); val4 = std::max(val6,tmp); + return std::min(val4,val2); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, T val7, T val8, T val9, T val10, T val11, + T val12) { + T tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = tmp; tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; + tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; tmp = std::min(val5,val8); + val8 = std::max(val5,val8); val5 = tmp; tmp = std::min(val0,val12); val12 = std::max(val0,val12); + val0 = tmp; tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val2,val3); val3 = std::max(val2,val3); val2 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val8,val11); + val11 = std::max(val8,val11); val8 = tmp; tmp = std::min(val7,val12); val12 = std::max(val7,val12); val7 = tmp; + tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val10,val11); val11 = std::max(val10,val11); val10 = tmp; tmp = std::min(val1,val4); + val4 = std::max(val1,val4); val1 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val8); val8 = std::max(val7,val8); val7 = tmp; val11 = std::min(val11,val12); + tmp = std::min(val4,val9); val9 = std::max(val4,val9); val4 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); val3 = tmp; + tmp = std::min(val5,val6); val6 = std::max(val5,val6); val5 = tmp; val8 = std::min(val8,val9); + val10 = std::min(val10,val11); tmp = std::min(val1,val7); val7 = std::max(val1,val7); val1 = tmp; + tmp = std::min(val2,val6); val6 = std::max(val2,val6); val2 = tmp; val3 = std::max(val1,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; val8 = std::min(val8,val10); + val5 = std::max(val0,val5); val5 = std::max(val2,val5); tmp = std::min(val6,val8); val8 = std::max(val6,val8); + val5 = std::max(val3,val5); val7 = std::min(val7,val8); val6 = std::max(val4,tmp); tmp = std::min(val4,tmp); + val5 = std::max(tmp,val5); val6 = std::min(val6,val7); + return std::max(val5,val6); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, + T val5, T val6, T val7, T val8, T val9, + T val10, T val11, T val12, T val13, T val14, + T val15, T val16, T val17, T val18, T val19, + T val20, T val21, T val22, T val23, T val24) { + T tmp = std::min(val0,val1); + val1 = std::max(val0,val1); val0 = tmp; tmp = std::min(val3,val4); val4 = std::max(val3,val4); + val3 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); val2 = std::min(tmp,val3); + val3 = std::max(tmp,val3); tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; + tmp = std::min(val5,val7); val7 = std::max(val5,val7); val5 = std::min(tmp,val6); val6 = std::max(tmp,val6); + tmp = std::min(val9,val10); val10 = std::max(val9,val10); val9 = tmp; tmp = std::min(val8,val10); + val10 = std::max(val8,val10); val8 = std::min(tmp,val9); val9 = std::max(tmp,val9); + tmp = std::min(val12,val13); val13 = std::max(val12,val13); val12 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val15,val16); val16 = std::max(val15,val16); val15 = tmp; tmp = std::min(val14,val16); + val16 = std::max(val14,val16); val14 = std::min(tmp,val15); val15 = std::max(tmp,val15); + tmp = std::min(val18,val19); val19 = std::max(val18,val19); val18 = tmp; tmp = std::min(val17,val19); + val19 = std::max(val17,val19); val17 = std::min(tmp,val18); val18 = std::max(tmp,val18); + tmp = std::min(val21,val22); val22 = std::max(val21,val22); val21 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = std::min(tmp,val21); val21 = std::max(tmp,val21); + tmp = std::min(val23,val24); val24 = std::max(val23,val24); val23 = tmp; tmp = std::min(val2,val5); + val5 = std::max(val2,val5); val2 = tmp; tmp = std::min(val3,val6); val6 = std::max(val3,val6); val3 = tmp; + tmp = std::min(val0,val6); val6 = std::max(val0,val6); val0 = std::min(tmp,val3); val3 = std::max(tmp,val3); + tmp = std::min(val4,val7); val7 = std::max(val4,val7); val4 = tmp; tmp = std::min(val1,val7); + val7 = std::max(val1,val7); val1 = std::min(tmp,val4); val4 = std::max(tmp,val4); tmp = std::min(val11,val14); + val14 = std::max(val11,val14); val11 = tmp; tmp = std::min(val8,val14); val14 = std::max(val8,val14); + val8 = std::min(tmp,val11); val11 = std::max(tmp,val11); tmp = std::min(val12,val15); + val15 = std::max(val12,val15); val12 = tmp; tmp = std::min(val9,val15); val15 = std::max(val9,val15); + val9 = std::min(tmp,val12); val12 = std::max(tmp,val12); tmp = std::min(val13,val16); + val16 = std::max(val13,val16); val13 = tmp; tmp = std::min(val10,val16); val16 = std::max(val10,val16); + val10 = std::min(tmp,val13); val13 = std::max(tmp,val13); tmp = std::min(val20,val23); + val23 = std::max(val20,val23); val20 = tmp; tmp = std::min(val17,val23); val23 = std::max(val17,val23); + val17 = std::min(tmp,val20); val20 = std::max(tmp,val20); tmp = std::min(val21,val24); + val24 = std::max(val21,val24); val21 = tmp; tmp = std::min(val18,val24); val24 = std::max(val18,val24); + val18 = std::min(tmp,val21); val21 = std::max(tmp,val21); tmp = std::min(val19,val22); + val22 = std::max(val19,val22); val19 = tmp; val17 = std::max(val8,val17); tmp = std::min(val9,val18); + val18 = std::max(val9,val18); val9 = tmp; tmp = std::min(val0,val18); val18 = std::max(val0,val18); + val9 = std::max(tmp,val9); tmp = std::min(val10,val19); val19 = std::max(val10,val19); val10 = tmp; + tmp = std::min(val1,val19); val19 = std::max(val1,val19); val1 = std::min(tmp,val10); + val10 = std::max(tmp,val10); tmp = std::min(val11,val20); val20 = std::max(val11,val20); val11 = tmp; + tmp = std::min(val2,val20); val20 = std::max(val2,val20); val11 = std::max(tmp,val11); + tmp = std::min(val12,val21); val21 = std::max(val12,val21); val12 = tmp; tmp = std::min(val3,val21); + val21 = std::max(val3,val21); val3 = std::min(tmp,val12); val12 = std::max(tmp,val12); + tmp = std::min(val13,val22); val22 = std::max(val13,val22); val4 = std::min(val4,val22); + val13 = std::max(val4,tmp); tmp = std::min(val4,tmp); val4 = tmp; tmp = std::min(val14,val23); + val23 = std::max(val14,val23); val14 = tmp; tmp = std::min(val5,val23); val23 = std::max(val5,val23); + val5 = std::min(tmp,val14); val14 = std::max(tmp,val14); tmp = std::min(val15,val24); + val24 = std::max(val15,val24); val15 = tmp; val6 = std::min(val6,val24); tmp = std::min(val6,val15); + val15 = std::max(val6,val15); val6 = tmp; tmp = std::min(val7,val16); val7 = std::min(tmp,val19); + tmp = std::min(val13,val21); val15 = std::min(val15,val23); tmp = std::min(val7,tmp); + val7 = std::min(tmp,val15); val9 = std::max(val1,val9); val11 = std::max(val3,val11); + val17 = std::max(val5,val17); val17 = std::max(val11,val17); val17 = std::max(val9,val17); + tmp = std::min(val4,val10); val10 = std::max(val4,val10); val4 = tmp; tmp = std::min(val6,val12); + val12 = std::max(val6,val12); val6 = tmp; tmp = std::min(val7,val14); val14 = std::max(val7,val14); + val7 = tmp; tmp = std::min(val4,val6); val6 = std::max(val4,val6); val7 = std::max(tmp,val7); + tmp = std::min(val12,val14); val14 = std::max(val12,val14); val12 = tmp; val10 = std::min(val10,val14); + tmp = std::min(val6,val7); val7 = std::max(val6,val7); val6 = tmp; tmp = std::min(val10,val12); + val12 = std::max(val10,val12); val10 = std::max(val6,tmp); tmp = std::min(val6,tmp); + val17 = std::max(tmp,val17); tmp = std::min(val12,val17); val17 = std::max(val12,val17); val12 = tmp; + val7 = std::min(val7,val17); tmp = std::min(val7,val10); val10 = std::max(val7,val10); val7 = tmp; + tmp = std::min(val12,val18); val18 = std::max(val12,val18); val12 = std::max(val7,tmp); + val10 = std::min(val10,val18); tmp = std::min(val12,val20); val20 = std::max(val12,val20); val12 = tmp; + tmp = std::min(val10,val20); + return std::max(tmp,val12); + } + + template + inline T median(T val0, T val1, T val2, T val3, T val4, T val5, T val6, + T val7, T val8, T val9, T val10, T val11, T val12, T val13, + T val14, T val15, T val16, T val17, T val18, T val19, T val20, + T val21, T val22, T val23, T val24, T val25, T val26, T val27, + T val28, T val29, T val30, T val31, T val32, T val33, T val34, + T val35, T val36, T val37, T val38, T val39, T val40, T val41, + T val42, T val43, T val44, T val45, T val46, T val47, T val48) { + T tmp = std::min(val0,val32); + val32 = std::max(val0,val32); val0 = tmp; tmp = std::min(val1,val33); val33 = std::max(val1,val33); val1 = tmp; + tmp = std::min(val2,val34); val34 = std::max(val2,val34); val2 = tmp; tmp = std::min(val3,val35); + val35 = std::max(val3,val35); val3 = tmp; tmp = std::min(val4,val36); val36 = std::max(val4,val36); val4 = tmp; + tmp = std::min(val5,val37); val37 = std::max(val5,val37); val5 = tmp; tmp = std::min(val6,val38); + val38 = std::max(val6,val38); val6 = tmp; tmp = std::min(val7,val39); val39 = std::max(val7,val39); val7 = tmp; + tmp = std::min(val8,val40); val40 = std::max(val8,val40); val8 = tmp; tmp = std::min(val9,val41); + val41 = std::max(val9,val41); val9 = tmp; tmp = std::min(val10,val42); val42 = std::max(val10,val42); + val10 = tmp; tmp = std::min(val11,val43); val43 = std::max(val11,val43); val11 = tmp; + tmp = std::min(val12,val44); val44 = std::max(val12,val44); val12 = tmp; tmp = std::min(val13,val45); + val45 = std::max(val13,val45); val13 = tmp; tmp = std::min(val14,val46); val46 = std::max(val14,val46); + val14 = tmp; tmp = std::min(val15,val47); val47 = std::max(val15,val47); val15 = tmp; + tmp = std::min(val16,val48); val48 = std::max(val16,val48); val16 = tmp; tmp = std::min(val0,val16); + val16 = std::max(val0,val16); val0 = tmp; tmp = std::min(val1,val17); val17 = std::max(val1,val17); + val1 = tmp; tmp = std::min(val2,val18); val18 = std::max(val2,val18); val2 = tmp; tmp = std::min(val3,val19); + val19 = std::max(val3,val19); val3 = tmp; tmp = std::min(val4,val20); val20 = std::max(val4,val20); val4 = tmp; + tmp = std::min(val5,val21); val21 = std::max(val5,val21); val5 = tmp; tmp = std::min(val6,val22); + val22 = std::max(val6,val22); val6 = tmp; tmp = std::min(val7,val23); val23 = std::max(val7,val23); val7 = tmp; + tmp = std::min(val8,val24); val24 = std::max(val8,val24); val8 = tmp; tmp = std::min(val9,val25); + val25 = std::max(val9,val25); val9 = tmp; tmp = std::min(val10,val26); val26 = std::max(val10,val26); + val10 = tmp; tmp = std::min(val11,val27); val27 = std::max(val11,val27); val11 = tmp; + tmp = std::min(val12,val28); val28 = std::max(val12,val28); val12 = tmp; tmp = std::min(val13,val29); + val29 = std::max(val13,val29); val13 = tmp; tmp = std::min(val14,val30); val30 = std::max(val14,val30); + val14 = tmp; tmp = std::min(val15,val31); val31 = std::max(val15,val31); val15 = tmp; + tmp = std::min(val32,val48); val48 = std::max(val32,val48); val32 = tmp; tmp = std::min(val16,val32); + val32 = std::max(val16,val32); val16 = tmp; tmp = std::min(val17,val33); val33 = std::max(val17,val33); + val17 = tmp; tmp = std::min(val18,val34); val34 = std::max(val18,val34); val18 = tmp; + tmp = std::min(val19,val35); val35 = std::max(val19,val35); val19 = tmp; tmp = std::min(val20,val36); + val36 = std::max(val20,val36); val20 = tmp; tmp = std::min(val21,val37); val37 = std::max(val21,val37); + val21 = tmp; tmp = std::min(val22,val38); val38 = std::max(val22,val38); val22 = tmp; + tmp = std::min(val23,val39); val39 = std::max(val23,val39); val23 = tmp; tmp = std::min(val24,val40); + val40 = std::max(val24,val40); val24 = tmp; tmp = std::min(val25,val41); val41 = std::max(val25,val41); + val25 = tmp; tmp = std::min(val26,val42); val42 = std::max(val26,val42); val26 = tmp; + tmp = std::min(val27,val43); val43 = std::max(val27,val43); val27 = tmp; tmp = std::min(val28,val44); + val44 = std::max(val28,val44); val28 = tmp; tmp = std::min(val29,val45); val45 = std::max(val29,val45); + val29 = tmp; tmp = std::min(val30,val46); val46 = std::max(val30,val46); val30 = tmp; + tmp = std::min(val31,val47); val47 = std::max(val31,val47); val31 = tmp; tmp = std::min(val0,val8); + val8 = std::max(val0,val8); val0 = tmp; tmp = std::min(val1,val9); val9 = std::max(val1,val9); val1 = tmp; + tmp = std::min(val2,val10); val10 = std::max(val2,val10); val2 = tmp; tmp = std::min(val3,val11); + val11 = std::max(val3,val11); val3 = tmp; tmp = std::min(val4,val12); val12 = std::max(val4,val12); val4 = tmp; + tmp = std::min(val5,val13); val13 = std::max(val5,val13); val5 = tmp; tmp = std::min(val6,val14); + val14 = std::max(val6,val14); val6 = tmp; tmp = std::min(val7,val15); val15 = std::max(val7,val15); val7 = tmp; + tmp = std::min(val16,val24); val24 = std::max(val16,val24); val16 = tmp; tmp = std::min(val17,val25); + val25 = std::max(val17,val25); val17 = tmp; tmp = std::min(val18,val26); val26 = std::max(val18,val26); + val18 = tmp; tmp = std::min(val19,val27); val27 = std::max(val19,val27); val19 = tmp; + tmp = std::min(val20,val28); val28 = std::max(val20,val28); val20 = tmp; tmp = std::min(val21,val29); + val29 = std::max(val21,val29); val21 = tmp; tmp = std::min(val22,val30); val30 = std::max(val22,val30); + val22 = tmp; tmp = std::min(val23,val31); val31 = std::max(val23,val31); val23 = tmp; + tmp = std::min(val32,val40); val40 = std::max(val32,val40); val32 = tmp; tmp = std::min(val33,val41); + val41 = std::max(val33,val41); val33 = tmp; tmp = std::min(val34,val42); val42 = std::max(val34,val42); + val34 = tmp; tmp = std::min(val35,val43); val43 = std::max(val35,val43); val35 = tmp; + tmp = std::min(val36,val44); val44 = std::max(val36,val44); val36 = tmp; tmp = std::min(val37,val45); + val45 = std::max(val37,val45); val37 = tmp; tmp = std::min(val38,val46); val46 = std::max(val38,val46); + val38 = tmp; tmp = std::min(val39,val47); val47 = std::max(val39,val47); val39 = tmp; + tmp = std::min(val8,val32); val32 = std::max(val8,val32); val8 = tmp; tmp = std::min(val9,val33); + val33 = std::max(val9,val33); val9 = tmp; tmp = std::min(val10,val34); val34 = std::max(val10,val34); + val10 = tmp; tmp = std::min(val11,val35); val35 = std::max(val11,val35); val11 = tmp; + tmp = std::min(val12,val36); val36 = std::max(val12,val36); val12 = tmp; tmp = std::min(val13,val37); + val37 = std::max(val13,val37); val13 = tmp; tmp = std::min(val14,val38); val38 = std::max(val14,val38); + val14 = tmp; tmp = std::min(val15,val39); val39 = std::max(val15,val39); val15 = tmp; + tmp = std::min(val24,val48); val48 = std::max(val24,val48); val24 = tmp; tmp = std::min(val8,val16); + val16 = std::max(val8,val16); val8 = tmp; tmp = std::min(val9,val17); val17 = std::max(val9,val17); + val9 = tmp; tmp = std::min(val10,val18); val18 = std::max(val10,val18); val10 = tmp; + tmp = std::min(val11,val19); val19 = std::max(val11,val19); val11 = tmp; tmp = std::min(val12,val20); + val20 = std::max(val12,val20); val12 = tmp; tmp = std::min(val13,val21); val21 = std::max(val13,val21); + val13 = tmp; tmp = std::min(val14,val22); val22 = std::max(val14,val22); val14 = tmp; + tmp = std::min(val15,val23); val23 = std::max(val15,val23); val15 = tmp; tmp = std::min(val24,val32); + val32 = std::max(val24,val32); val24 = tmp; tmp = std::min(val25,val33); val33 = std::max(val25,val33); + val25 = tmp; tmp = std::min(val26,val34); val34 = std::max(val26,val34); val26 = tmp; + tmp = std::min(val27,val35); val35 = std::max(val27,val35); val27 = tmp; tmp = std::min(val28,val36); + val36 = std::max(val28,val36); val28 = tmp; tmp = std::min(val29,val37); val37 = std::max(val29,val37); + val29 = tmp; tmp = std::min(val30,val38); val38 = std::max(val30,val38); val30 = tmp; + tmp = std::min(val31,val39); val39 = std::max(val31,val39); val31 = tmp; tmp = std::min(val40,val48); + val48 = std::max(val40,val48); val40 = tmp; tmp = std::min(val0,val4); val4 = std::max(val0,val4); + val0 = tmp; tmp = std::min(val1,val5); val5 = std::max(val1,val5); val1 = tmp; tmp = std::min(val2,val6); + val6 = std::max(val2,val6); val2 = tmp; tmp = std::min(val3,val7); val7 = std::max(val3,val7); val3 = tmp; + tmp = std::min(val8,val12); val12 = std::max(val8,val12); val8 = tmp; tmp = std::min(val9,val13); + val13 = std::max(val9,val13); val9 = tmp; tmp = std::min(val10,val14); val14 = std::max(val10,val14); + val10 = tmp; tmp = std::min(val11,val15); val15 = std::max(val11,val15); val11 = tmp; + tmp = std::min(val16,val20); val20 = std::max(val16,val20); val16 = tmp; tmp = std::min(val17,val21); + val21 = std::max(val17,val21); val17 = tmp; tmp = std::min(val18,val22); val22 = std::max(val18,val22); + val18 = tmp; tmp = std::min(val19,val23); val23 = std::max(val19,val23); val19 = tmp; + tmp = std::min(val24,val28); val28 = std::max(val24,val28); val24 = tmp; tmp = std::min(val25,val29); + val29 = std::max(val25,val29); val25 = tmp; tmp = std::min(val26,val30); val30 = std::max(val26,val30); + val26 = tmp; tmp = std::min(val27,val31); val31 = std::max(val27,val31); val27 = tmp; + tmp = std::min(val32,val36); val36 = std::max(val32,val36); val32 = tmp; tmp = std::min(val33,val37); + val37 = std::max(val33,val37); val33 = tmp; tmp = std::min(val34,val38); val38 = std::max(val34,val38); + val34 = tmp; tmp = std::min(val35,val39); val39 = std::max(val35,val39); val35 = tmp; + tmp = std::min(val40,val44); val44 = std::max(val40,val44); val40 = tmp; tmp = std::min(val41,val45); + val45 = std::max(val41,val45); val41 = tmp; tmp = std::min(val42,val46); val46 = std::max(val42,val46); + val42 = tmp; tmp = std::min(val43,val47); val47 = std::max(val43,val47); val43 = tmp; + tmp = std::min(val4,val32); val32 = std::max(val4,val32); val4 = tmp; tmp = std::min(val5,val33); + val33 = std::max(val5,val33); val5 = tmp; tmp = std::min(val6,val34); val34 = std::max(val6,val34); + val6 = tmp; tmp = std::min(val7,val35); val35 = std::max(val7,val35); val7 = tmp; + tmp = std::min(val12,val40); val40 = std::max(val12,val40); val12 = tmp; tmp = std::min(val13,val41); + val41 = std::max(val13,val41); val13 = tmp; tmp = std::min(val14,val42); val42 = std::max(val14,val42); + val14 = tmp; tmp = std::min(val15,val43); val43 = std::max(val15,val43); val15 = tmp; + tmp = std::min(val20,val48); val48 = std::max(val20,val48); val20 = tmp; tmp = std::min(val4,val16); + val16 = std::max(val4,val16); val4 = tmp; tmp = std::min(val5,val17); val17 = std::max(val5,val17); + val5 = tmp; tmp = std::min(val6,val18); val18 = std::max(val6,val18); val6 = tmp; + tmp = std::min(val7,val19); val19 = std::max(val7,val19); val7 = tmp; tmp = std::min(val12,val24); + val24 = std::max(val12,val24); val12 = tmp; tmp = std::min(val13,val25); val25 = std::max(val13,val25); + val13 = tmp; tmp = std::min(val14,val26); val26 = std::max(val14,val26); val14 = tmp; + tmp = std::min(val15,val27); val27 = std::max(val15,val27); val15 = tmp; tmp = std::min(val20,val32); + val32 = std::max(val20,val32); val20 = tmp; tmp = std::min(val21,val33); val33 = std::max(val21,val33); + val21 = tmp; tmp = std::min(val22,val34); val34 = std::max(val22,val34); val22 = tmp; + tmp = std::min(val23,val35); val35 = std::max(val23,val35); val23 = tmp; tmp = std::min(val28,val40); + val40 = std::max(val28,val40); val28 = tmp; tmp = std::min(val29,val41); val41 = std::max(val29,val41); + val29 = tmp; tmp = std::min(val30,val42); val42 = std::max(val30,val42); val30 = tmp; + tmp = std::min(val31,val43); val43 = std::max(val31,val43); val31 = tmp; tmp = std::min(val36,val48); + val48 = std::max(val36,val48); val36 = tmp; tmp = std::min(val4,val8); val8 = std::max(val4,val8); + val4 = tmp; tmp = std::min(val5,val9); val9 = std::max(val5,val9); val5 = tmp; tmp = std::min(val6,val10); + val10 = std::max(val6,val10); val6 = tmp; tmp = std::min(val7,val11); val11 = std::max(val7,val11); val7 = tmp; + tmp = std::min(val12,val16); val16 = std::max(val12,val16); val12 = tmp; tmp = std::min(val13,val17); + val17 = std::max(val13,val17); val13 = tmp; tmp = std::min(val14,val18); val18 = std::max(val14,val18); + val14 = tmp; tmp = std::min(val15,val19); val19 = std::max(val15,val19); val15 = tmp; + tmp = std::min(val20,val24); val24 = std::max(val20,val24); val20 = tmp; tmp = std::min(val21,val25); + val25 = std::max(val21,val25); val21 = tmp; tmp = std::min(val22,val26); val26 = std::max(val22,val26); + val22 = tmp; tmp = std::min(val23,val27); val27 = std::max(val23,val27); val23 = tmp; + tmp = std::min(val28,val32); val32 = std::max(val28,val32); val28 = tmp; tmp = std::min(val29,val33); + val33 = std::max(val29,val33); val29 = tmp; tmp = std::min(val30,val34); val34 = std::max(val30,val34); + val30 = tmp; tmp = std::min(val31,val35); val35 = std::max(val31,val35); val31 = tmp; + tmp = std::min(val36,val40); val40 = std::max(val36,val40); val36 = tmp; tmp = std::min(val37,val41); + val41 = std::max(val37,val41); val37 = tmp; tmp = std::min(val38,val42); val42 = std::max(val38,val42); + val38 = tmp; tmp = std::min(val39,val43); val43 = std::max(val39,val43); val39 = tmp; + tmp = std::min(val44,val48); val48 = std::max(val44,val48); val44 = tmp; tmp = std::min(val0,val2); + val2 = std::max(val0,val2); val0 = tmp; tmp = std::min(val1,val3); val3 = std::max(val1,val3); val1 = tmp; + tmp = std::min(val4,val6); val6 = std::max(val4,val6); val4 = tmp; tmp = std::min(val5,val7); + val7 = std::max(val5,val7); val5 = tmp; tmp = std::min(val8,val10); val10 = std::max(val8,val10); val8 = tmp; + tmp = std::min(val9,val11); val11 = std::max(val9,val11); val9 = tmp; tmp = std::min(val12,val14); + val14 = std::max(val12,val14); val12 = tmp; tmp = std::min(val13,val15); val15 = std::max(val13,val15); + val13 = tmp; tmp = std::min(val16,val18); val18 = std::max(val16,val18); val16 = tmp; + tmp = std::min(val17,val19); val19 = std::max(val17,val19); val17 = tmp; tmp = std::min(val20,val22); + val22 = std::max(val20,val22); val20 = tmp; tmp = std::min(val21,val23); val23 = std::max(val21,val23); + val21 = tmp; tmp = std::min(val24,val26); val26 = std::max(val24,val26); val24 = tmp; + tmp = std::min(val25,val27); val27 = std::max(val25,val27); val25 = tmp; tmp = std::min(val28,val30); + val30 = std::max(val28,val30); val28 = tmp; tmp = std::min(val29,val31); val31 = std::max(val29,val31); + val29 = tmp; tmp = std::min(val32,val34); val34 = std::max(val32,val34); val32 = tmp; + tmp = std::min(val33,val35); val35 = std::max(val33,val35); val33 = tmp; tmp = std::min(val36,val38); + val38 = std::max(val36,val38); val36 = tmp; tmp = std::min(val37,val39); val39 = std::max(val37,val39); + val37 = tmp; tmp = std::min(val40,val42); val42 = std::max(val40,val42); val40 = tmp; + tmp = std::min(val41,val43); val43 = std::max(val41,val43); val41 = tmp; tmp = std::min(val44,val46); + val46 = std::max(val44,val46); val44 = tmp; tmp = std::min(val45,val47); val47 = std::max(val45,val47); + val45 = tmp; tmp = std::min(val2,val32); val32 = std::max(val2,val32); val2 = tmp; tmp = std::min(val3,val33); + val33 = std::max(val3,val33); val3 = tmp; tmp = std::min(val6,val36); val36 = std::max(val6,val36); val6 = tmp; + tmp = std::min(val7,val37); val37 = std::max(val7,val37); val7 = tmp; tmp = std::min(val10,val40); + val40 = std::max(val10,val40); val10 = tmp; tmp = std::min(val11,val41); val41 = std::max(val11,val41); + val11 = tmp; tmp = std::min(val14,val44); val44 = std::max(val14,val44); val14 = tmp; + tmp = std::min(val15,val45); val45 = std::max(val15,val45); val15 = tmp; tmp = std::min(val18,val48); + val48 = std::max(val18,val48); val18 = tmp; tmp = std::min(val2,val16); val16 = std::max(val2,val16); + val2 = tmp; tmp = std::min(val3,val17); val17 = std::max(val3,val17); val3 = tmp; + tmp = std::min(val6,val20); val20 = std::max(val6,val20); val6 = tmp; tmp = std::min(val7,val21); + val21 = std::max(val7,val21); val7 = tmp; tmp = std::min(val10,val24); val24 = std::max(val10,val24); + val10 = tmp; tmp = std::min(val11,val25); val25 = std::max(val11,val25); val11 = tmp; + tmp = std::min(val14,val28); val28 = std::max(val14,val28); val14 = tmp; tmp = std::min(val15,val29); + val29 = std::max(val15,val29); val15 = tmp; tmp = std::min(val18,val32); val32 = std::max(val18,val32); + val18 = tmp; tmp = std::min(val19,val33); val33 = std::max(val19,val33); val19 = tmp; + tmp = std::min(val22,val36); val36 = std::max(val22,val36); val22 = tmp; tmp = std::min(val23,val37); + val37 = std::max(val23,val37); val23 = tmp; tmp = std::min(val26,val40); val40 = std::max(val26,val40); + val26 = tmp; tmp = std::min(val27,val41); val41 = std::max(val27,val41); val27 = tmp; + tmp = std::min(val30,val44); val44 = std::max(val30,val44); val30 = tmp; tmp = std::min(val31,val45); + val45 = std::max(val31,val45); val31 = tmp; tmp = std::min(val34,val48); val48 = std::max(val34,val48); + val34 = tmp; tmp = std::min(val2,val8); val8 = std::max(val2,val8); val2 = tmp; tmp = std::min(val3,val9); + val9 = std::max(val3,val9); val3 = tmp; tmp = std::min(val6,val12); val12 = std::max(val6,val12); val6 = tmp; + tmp = std::min(val7,val13); val13 = std::max(val7,val13); val7 = tmp; tmp = std::min(val10,val16); + val16 = std::max(val10,val16); val10 = tmp; tmp = std::min(val11,val17); val17 = std::max(val11,val17); + val11 = tmp; tmp = std::min(val14,val20); val20 = std::max(val14,val20); val14 = tmp; + tmp = std::min(val15,val21); val21 = std::max(val15,val21); val15 = tmp; tmp = std::min(val18,val24); + val24 = std::max(val18,val24); val18 = tmp; tmp = std::min(val19,val25); val25 = std::max(val19,val25); + val19 = tmp; tmp = std::min(val22,val28); val28 = std::max(val22,val28); val22 = tmp; + tmp = std::min(val23,val29); val29 = std::max(val23,val29); val23 = tmp; tmp = std::min(val26,val32); + val32 = std::max(val26,val32); val26 = tmp; tmp = std::min(val27,val33); val33 = std::max(val27,val33); + val27 = tmp; tmp = std::min(val30,val36); val36 = std::max(val30,val36); val30 = tmp; + tmp = std::min(val31,val37); val37 = std::max(val31,val37); val31 = tmp; tmp = std::min(val34,val40); + val40 = std::max(val34,val40); val34 = tmp; tmp = std::min(val35,val41); val41 = std::max(val35,val41); + val35 = tmp; tmp = std::min(val38,val44); val44 = std::max(val38,val44); val38 = tmp; + tmp = std::min(val39,val45); val45 = std::max(val39,val45); val39 = tmp; tmp = std::min(val42,val48); + val48 = std::max(val42,val48); val42 = tmp; tmp = std::min(val2,val4); val4 = std::max(val2,val4); + val2 = tmp; tmp = std::min(val3,val5); val5 = std::max(val3,val5); val3 = tmp; tmp = std::min(val6,val8); + val8 = std::max(val6,val8); val6 = tmp; tmp = std::min(val7,val9); val9 = std::max(val7,val9); val7 = tmp; + tmp = std::min(val10,val12); val12 = std::max(val10,val12); val10 = tmp; tmp = std::min(val11,val13); + val13 = std::max(val11,val13); val11 = tmp; tmp = std::min(val14,val16); val16 = std::max(val14,val16); + val14 = tmp; tmp = std::min(val15,val17); val17 = std::max(val15,val17); val15 = tmp; + tmp = std::min(val18,val20); val20 = std::max(val18,val20); val18 = tmp; tmp = std::min(val19,val21); + val21 = std::max(val19,val21); val19 = tmp; tmp = std::min(val22,val24); val24 = std::max(val22,val24); + val22 = tmp; tmp = std::min(val23,val25); val25 = std::max(val23,val25); val23 = tmp; + tmp = std::min(val26,val28); val28 = std::max(val26,val28); val26 = tmp; tmp = std::min(val27,val29); + val29 = std::max(val27,val29); val27 = tmp; tmp = std::min(val30,val32); val32 = std::max(val30,val32); + val30 = tmp; tmp = std::min(val31,val33); val33 = std::max(val31,val33); val31 = tmp; + tmp = std::min(val34,val36); val36 = std::max(val34,val36); val34 = tmp; tmp = std::min(val35,val37); + val37 = std::max(val35,val37); val35 = tmp; tmp = std::min(val38,val40); val40 = std::max(val38,val40); + val38 = tmp; tmp = std::min(val39,val41); val41 = std::max(val39,val41); val39 = tmp; + tmp = std::min(val42,val44); val44 = std::max(val42,val44); val42 = tmp; tmp = std::min(val43,val45); + val45 = std::max(val43,val45); val43 = tmp; tmp = std::min(val46,val48); val48 = std::max(val46,val48); + val46 = tmp; val1 = std::max(val0,val1); val3 = std::max(val2,val3); val5 = std::max(val4,val5); + val7 = std::max(val6,val7); val9 = std::max(val8,val9); val11 = std::max(val10,val11); + val13 = std::max(val12,val13); val15 = std::max(val14,val15); val17 = std::max(val16,val17); + val19 = std::max(val18,val19); val21 = std::max(val20,val21); val23 = std::max(val22,val23); + val24 = std::min(val24,val25); val26 = std::min(val26,val27); val28 = std::min(val28,val29); + val30 = std::min(val30,val31); val32 = std::min(val32,val33); val34 = std::min(val34,val35); + val36 = std::min(val36,val37); val38 = std::min(val38,val39); val40 = std::min(val40,val41); + val42 = std::min(val42,val43); val44 = std::min(val44,val45); val46 = std::min(val46,val47); + val32 = std::max(val1,val32); val34 = std::max(val3,val34); val36 = std::max(val5,val36); + val38 = std::max(val7,val38); val9 = std::min(val9,val40); val11 = std::min(val11,val42); + val13 = std::min(val13,val44); val15 = std::min(val15,val46); val17 = std::min(val17,val48); + val24 = std::max(val9,val24); val26 = std::max(val11,val26); val28 = std::max(val13,val28); + val30 = std::max(val15,val30); val17 = std::min(val17,val32); val19 = std::min(val19,val34); + val21 = std::min(val21,val36); val23 = std::min(val23,val38); val24 = std::max(val17,val24); + val26 = std::max(val19,val26); val21 = std::min(val21,val28); val23 = std::min(val23,val30); + val24 = std::max(val21,val24); val23 = std::min(val23,val26); + return std::max(val23,val24); + } + + //! Return sqrt(x^2 + y^2). + template + inline T hypot(const T x, const T y) { + return std::sqrt(x*x + y*y); + } + + template + inline T hypot(const T x, const T y, const T z) { + return std::sqrt(x*x + y*y + z*z); + } + + template + inline T _hypot(const T x, const T y) { // Slower but more precise version + T nx = cimg::abs(x), ny = cimg::abs(y), t; + if (nx0) { t/=nx; return nx*std::sqrt(1 + t*t); } + return 0; + } + + //! Return the factorial of n + inline double factorial(const int n) { + if (n<0) return cimg::type::nan(); + if (n<2) return 1; + double res = 2; + for (int i = 3; i<=n; ++i) res*=i; + return res; + } + + //! Return the number of permutations of k objects in a set of n objects. + inline double permutations(const int k, const int n, const bool with_order) { + if (n<0 || k<0) return cimg::type::nan(); + if (k>n) return 0; + double res = 1; + for (int i = n; i>=n - k + 1; --i) res*=i; + return with_order?res:res/cimg::factorial(k); + } + + inline double _fibonacci(int exp) { + double + base = (1 + std::sqrt(5.0))/2, + result = 1/std::sqrt(5.0); + while (exp) { + if (exp&1) result*=base; + exp>>=1; + base*=base; + } + return result; + } + + //! Calculate fibonacci number. + // (Precise up to n = 78, less precise for n>78). + inline double fibonacci(const int n) { + if (n<0) return cimg::type::nan(); + if (n<3) return 1; + if (n<11) { + cimg_uint64 fn1 = 1, fn2 = 1, fn = 0; + for (int i = 3; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + if (n<75) // precise up to n = 74, faster than the integer calculation above for n>10 + return (double)((cimg_uint64)(_fibonacci(n) + 0.5)); + + if (n<94) { // precise up to n = 78, less precise for n>78 up to n = 93, overflows for n>93 + cimg_uint64 + fn1 = (cimg_uint64)1304969544928657U, + fn2 = (cimg_uint64)806515533049393U, + fn = 0; + for (int i = 75; i<=n; ++i) { fn = fn1 + fn2; fn2 = fn1; fn1 = fn; } + return (double)fn; + } + return _fibonacci(n); // Not precise, but better than the wrong overflowing calculation + } + + //! Convert ascii character to lower case. + inline char lowercase(const char x) { + return (char)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + inline double lowercase(const double x) { + return (double)((x<'A'||x>'Z')?x:x - 'A' + 'a'); + } + + //! Convert C-string to lower case. + inline void lowercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = lowercase(*ptr); + } + + //! Convert ascii character to upper case. + inline char uppercase(const char x) { + return (char)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + inline double uppercase(const double x) { + return (double)((x<'a'||x>'z')?x:x - 'a' + 'A'); + } + + //! Convert C-string to upper case. + inline void uppercase(char *const str) { + if (str) for (char *ptr = str; *ptr; ++ptr) *ptr = uppercase(*ptr); + } + + //! Read value in a C-string. + /** + \param str C-string containing the float value to read. + \return Read value. + \note Same as std::atof() extended to manage the retrieval of fractions from C-strings, + as in "1/2". + **/ + inline double atof(const char *const str) { + double x = 0, y = 1; + return str && cimg_sscanf(str,"%lf/%lf",&x,&y)>0?x/y:0; + } + + //! Compare the first \p l characters of two C-strings, ignoring the case. + /** + \param str1 C-string. + \param str2 C-string. + \param l Number of characters to compare. + \return \c 0 if the two strings are equal, something else otherwise. + \note This function has to be defined since it is not provided by all C++-compilers (not ANSI). + **/ + inline int strncasecmp(const char *const str1, const char *const str2, const int l) { + if (!l) return 0; + if (!str1) return str2?-1:0; + const char *nstr1 = str1, *nstr2 = str2; + int k, diff = 0; for (k = 0; kp && str[q]==delimiter; ) { --q; if (!is_iterative) break; } + } + const int n = q - p + 1; + if (n!=l) { std::memmove(str,str + p,(unsigned int)n); str[n] = 0; return true; } + return false; + } + + //! Replace reserved characters (for Windows filename) by another character. + /** + \param[in,out] str C-string to work with (modified at output). + \param[in] c Replacement character. + **/ + inline void strwindows_reserved(char *const str, const char c='_') { + for (char *s = str; *s; ++s) { + const char i = *s; + if (i=='<' || i=='>' || i==':' || i=='\"' || i=='/' || i=='\\' || i=='|' || i=='?' || i=='*') *s = c; + } + } + + //! Replace escape sequences in C-strings by their binary ascii values. + /** + \param[in,out] str C-string to work with (modified at output). + **/ + inline void strunescape(char *const str) { +#define cimg_strunescape(ci,co) case ci : *nd = co; ++ns; break; + unsigned int val = 0; + for (char *ns = str, *nd = str; *ns || (bool)(*nd=0); ++nd) if (*ns=='\\') switch (*(++ns)) { + cimg_strunescape('a','\a'); + cimg_strunescape('b','\b'); + cimg_strunescape('e',0x1B); + cimg_strunescape('f','\f'); + cimg_strunescape('n','\n'); + cimg_strunescape('r','\r'); + cimg_strunescape('t','\t'); + cimg_strunescape('v','\v'); + cimg_strunescape('\\','\\'); + cimg_strunescape('\'','\''); + cimg_strunescape('\"','\"'); + cimg_strunescape('\?','\?'); + case 0 : *nd = 0; break; + case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : + cimg_sscanf(ns,"%o",&val); while (*ns>='0' && *ns<='7') ++ns; + *nd = (char)val; break; + case 'x' : + cimg_sscanf(++ns,"%x",&val); + while ((*ns>='0' && *ns<='9') || (*ns>='a' && *ns<='f') || (*ns>='A' && *ns<='F')) ++ns; + *nd = (char)val; break; + default : *nd = *(ns++); + } else *nd = *(ns++); + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size); + + // Return string that identifies the running OS. + inline const char *stros() { +#if defined(linux) || defined(__linux) || defined(__linux__) + static const char *const str = "Linux"; +#elif defined(sun) || defined(__sun) + static const char *const str = "Sun OS"; +#elif defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined (__DragonFly__) + static const char *const str = "BSD"; +#elif defined(sgi) || defined(__sgi) + static const char *const str = "Irix"; +#elif defined(__MACOSX__) || defined(__APPLE__) + static const char *const str = "Mac OS"; +#elif defined(unix) || defined(__unix) || defined(__unix__) + static const char *const str = "Generic Unix"; +#elif defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ + defined(WIN64) || defined(_WIN64) || defined(__WIN64__) + static const char *const str = "Windows"; +#else + const char + *const _str1 = std::getenv("OSTYPE"), + *const _str2 = _str1?_str1:std::getenv("OS"), + *const str = _str2?_str2:"Unknown OS"; +#endif + return str; + } + + //! Return the basename of a filename. + inline const char* basename(const char *const s, const char separator=cimg_file_separator) { + const char *p = 0, *np = s; + while (np>=s && (p=np)) np = std::strchr(np,separator) + 1; + return p; + } + + // Return a random filename. + inline const char* filenamerand() { + cimg::mutex(6); + static char randomid[9]; + cimg::srand(); + 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)))); + } + cimg::mutex(6,0); + return randomid; + } + + // Convert filename as a Windows-style filename (short path name). + inline void winformat_string(char *const str) { + if (str && *str) { +#if cimg_OS==2 + char *const nstr = new char[MAX_PATH]; + if (GetShortPathNameA(str,nstr,MAX_PATH)) std::strcpy(str,nstr); + delete[] nstr; +#endif + } + } + + // Open a file (with wide character support on Windows). + inline std::FILE *win_fopen(const char *const path, const char *const mode); + + //! Open a file. + /** + \param path Path of the filename to open. + \param mode C-string describing the opening mode. + \return Opened file. + \note Same as std::fopen() but throw a \c CImgIOException when + the specified file cannot be opened, instead of returning \c 0. + **/ + inline std::FILE *fopen(const char *const path, const char *const mode) { + if (!path) + throw CImgArgumentException("cimg::fopen(): Specified file path is (null)."); + if (!mode) + throw CImgArgumentException("cimg::fopen(): File '%s', specified mode is (null).", + path); + std::FILE *res = 0; + if (*path=='-' && (!path[1] || path[1]=='.')) { + 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); + if (!res) throw CImgIOException("cimg::fopen(): Failed to open file '%s' with mode '%s'.", + path,mode); + return res; + } + + //! Close a file. + /** + \param file File to close. + \return \c 0 if file has been closed properly, something else otherwise. + \note Same as std::fclose() but display a warning message if + the file has not been closed properly. + **/ + inline int fclose(std::FILE *file) { + if (!file) warn("cimg::fclose(): Specified file is (null)."); + if (!file || file==cimg::_stdin() || file==cimg::_stdout()) return 0; + const int errn = std::fclose(file); + if (errn!=0) warn("cimg::fclose(): Error code %d returned during file closing.", + errn); + return errn; + } + + //! Version of 'fseek()' that supports >=64bits offsets everywhere (for Windows). + inline int fseek(FILE *stream, cimg_long offset, int origin) { +#if cimg_OS==2 + return _fseeki64(stream,(__int64)offset,origin); +#else + return std::fseek(stream,offset,origin); +#endif + } + + //! Version of 'ftell()' that supports >=64bits offsets everywhere (for Windows). + inline cimg_long ftell(FILE *stream) { +#if cimg_OS==2 + return (cimg_long)_ftelli64(stream); +#else + return (cimg_long)std::ftell(stream); +#endif + } + + //! Check if a path is a directory. + /** + \param path Specified path to test. + **/ + inline bool is_directory(const char *const path) { + if (!path || !*path) return false; +#if cimg_OS==1 + struct stat st_buf; + return (!stat(path,&st_buf) && S_ISDIR(st_buf.st_mode)); +#elif cimg_OS==2 + const unsigned int res = (unsigned int)GetFileAttributesA(path); + return res==INVALID_FILE_ATTRIBUTES?false:(res&16); +#else + return false; +#endif + } + + //! Check if a path is a file. + /** + \param path Specified path to test. + **/ + inline bool is_file(const char *const path) { + if (!path || !*path) return false; + std::FILE *const file = std_fopen(path,"rb"); + if (!file) return false; + std::fclose(file); + return !is_directory(path); + } + + //! Get last write time of a given file or directory. + /** + \param path Specified path to get attributes from. + \param attr Type of requested time attribute. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second } + \return -1 if requested attribute could not be read. + **/ + inline int fdate(const char *const path, const unsigned int attr) { + int res = -1; + if (!path || !*path || attr>6) return -1; + cimg::mutex(6); +#if cimg_OS==2 + HANDLE file = CreateFileA(path,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); + if (file!=INVALID_HANDLE_VALUE) { + FILETIME _ft; + SYSTEMTIME ft; + if (GetFileTime(file,0,0,&_ft) && FileTimeToSystemTime(&_ft,&ft)) + res = (int)(attr==0?ft.wYear:attr==1?ft.wMonth:attr==2?ft.wDay:attr==3?ft.wDayOfWeek: + attr==4?ft.wHour:attr==5?ft.wMinute:ft.wSecond); + CloseHandle(file); + } +#elif cimg_OS==1 + struct stat st_buf; + if (!stat(path,&st_buf)) { + const time_t _ft = st_buf.st_mtime; + const struct tm& ft = *std::localtime(&_ft); + res = (int)(attr==0?ft.tm_year + 1900:attr==1?ft.tm_mon + 1:attr==2?ft.tm_mday:attr==3?ft.tm_wday: + attr==4?ft.tm_hour:attr==5?ft.tm_min:ft.tm_sec); + } +#endif + cimg::mutex(6,0); + return res; + } + + //! Get current local time. + /** + \param attr Type of requested time attribute. + Can be { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second } + **/ + inline int date(const unsigned int attr) { + int res; + cimg::mutex(6); +#if cimg_OS==2 + SYSTEMTIME st; + GetLocalTime(&st); + res = (int)(attr==0?st.wYear:attr==1?st.wMonth:attr==2?st.wDay:attr==3?st.wDayOfWeek: + attr==4?st.wHour:attr==5?st.wMinute:st.wSecond); +#else + time_t _st; + std::time(&_st); + struct tm *st = std::localtime(&_st); + res = (int)(attr==0?st->tm_year + 1900:attr==1?st->tm_mon + 1:attr==2?st->tm_mday:attr==3?st->tm_wday: + attr==4?st->tm_hour:attr==5?st->tm_min:st->tm_sec); +#endif + cimg::mutex(6,0); + return res; + } + + // Get/set path to store temporary files. + inline const char* temporary_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the Program Files/ directory (Windows only). +#if cimg_OS==2 + inline const char* programfiles_path(const char *const user_path=0, const bool reinit_path=false); +#endif + + // Get/set path to the ImageMagick's \c convert binary. + inline const char* imagemagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the GraphicsMagick's \c gm binary. + inline const char* graphicsmagick_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the XMedcon's \c medcon binary. + inline const char* medcon_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the FFMPEG's \c ffmpeg binary. + inline const char *ffmpeg_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gzip binary. + inline const char *gzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c gunzip binary. + inline const char *gunzip_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c dcraw binary. + inline const char *dcraw_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c wget binary. + inline const char *wget_path(const char *const user_path=0, const bool reinit_path=false); + + // Get/set path to the \c curl binary. + inline const char *curl_path(const char *const user_path=0, const bool reinit_path=false); + + //! Split filename into two C-strings \c body and \c extension. + /** + filename and body must not overlap! + **/ + inline const char *split_filename(const char *const filename, char *const body=0) { + if (!filename) { if (body) *body = 0; return 0; } + const char *p = 0; for (const char *np = filename; np>=filename && (p=np); np = std::strchr(np,'.') + 1) {} + if (p==filename) { + if (body) std::strcpy(body,filename); + return filename + std::strlen(filename); + } + const unsigned int l = (unsigned int)(p - filename - 1); + if (body) { if (l) std::memcpy(body,filename,l); body[l] = 0; } + return p; + } + + //! Generate a numbered version of a filename. + inline char* number_filename(const char *const filename, const int number, + const unsigned int digits, char *const str) { + if (!filename) { if (str) *str = 0; return 0; } + char *const format = new char[1024], *const body = new char[1024]; + const char *const ext = cimg::split_filename(filename,body); + if (*ext) cimg_snprintf(format,1024,"%%s_%%.%ud.%%s",digits); + else cimg_snprintf(format,1024,"%%s_%%.%ud",digits); + cimg_sprintf(str,format,body,number,ext); + delete[] format; delete[] body; + return str; + } + + //! Read data from file. + /** + \param[out] ptr Pointer to memory buffer that will contain the binary data read from file. + \param nmemb Number of elements to read. + \param stream File to read data from. + \return Number of read elements. + \note Same as std::fread() but may display warning message if all elements could not be read. + **/ + template + inline size_t fread(T *const ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fread(): Invalid reading request of %u %s%s from file %p to buffer %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",stream,ptr); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_read = nmemb, al_read = 0, l_to_read = 0, l_al_read = 0; + do { + l_to_read = (to_read*sizeof(T))0); + if (to_read>0) + warn("cimg::fread(): Only %lu/%lu elements could be read from file.", + (unsigned long)al_read,(unsigned long)nmemb); + return al_read; + } + + //! Write data to file. + /** + \param ptr Pointer to memory buffer containing the binary data to write on file. + \param nmemb Number of elements to write. + \param[out] stream File to write data on. + \return Number of written elements. + \note Similar to std::fwrite but may display warning messages if all elements could not be written. + **/ + template + inline size_t fwrite(const T *ptr, const size_t nmemb, std::FILE *stream) { + if (!ptr || !stream) + throw CImgArgumentException("cimg::fwrite(): Invalid writing request of %u %s%s from buffer %p to file %p.", + nmemb,cimg::type::string(),nmemb>1?"s":"",ptr,stream); + if (!nmemb) return 0; + const size_t wlimitT = 63*1024*1024, wlimit = wlimitT/sizeof(T); + size_t to_write = nmemb, al_write = 0, l_to_write = 0, l_al_write = 0; + do { + l_to_write = (to_write*sizeof(T))0); + if (to_write>0) + warn("cimg::fwrite(): Only %lu/%lu elements could be written in file.", + (unsigned long)al_write,(unsigned long)nmemb); + return al_write; + } + + //! Create an empty file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + **/ + inline void fempty(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::fempty(): Specified filename is (null)."); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (!file) cimg::fclose(nfile); + } + + // Try to guess format from an image file. + inline const char *ftype(std::FILE *const file, const char *const filename); + + // Load file from network as a local temporary file. + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout=0, const bool try_fallback=false, + const char *const referer=0); + + //! Return options specified on the command line. + inline const char* option(const char *const name, const int argc, const char *const *const argv, + const char *const defaut, const char *const usage, const bool reset_static) { + static bool first = true, visu = false; + if (reset_static) { first = true; return 0; } + const char *res = 0; + if (first) { + first = false; + visu = cimg::option("-h",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("-help",argc,argv,(char*)0,(char*)0,false)!=0; + visu |= cimg::option("--help",argc,argv,(char*)0,(char*)0,false)!=0; + } + if (!name && visu) { + if (usage) { + std::fprintf(cimg::output(),"\n %s%s%s",cimg::t_red,cimg::basename(argv[0]),cimg::t_normal); + std::fprintf(cimg::output(),": %s",usage); + std::fprintf(cimg::output()," (%s, %s)\n\n",cimg_date,cimg_time); + } + if (defaut) std::fprintf(cimg::output(),"%s\n",defaut); + } + if (name) { + if (argc>0) { + int k = 0; + while (k Operating System: %s%-13s%s %s('cimg_OS'=%d)%s\n", + cimg::t_bold, + cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknow"), + cimg::t_normal,cimg::t_green, + cimg_OS, + cimg::t_normal); + + std::fprintf(cimg::output()," > CPU endianness: %s%s Endian%s\n", + cimg::t_bold, + cimg::endianness()?"Big":"Little", + cimg::t_normal); + + std::fprintf(cimg::output()," > Verbosity mode: %s%-13s%s %s('cimg_verbosity'=%d)%s\n", + cimg::t_bold, + cimg_verbosity==0?"Quiet": + cimg_verbosity==1?"Console": + cimg_verbosity==2?"Dialog": + cimg_verbosity==3?"Console+Warnings":"Dialog+Warnings", + cimg::t_normal,cimg::t_green, + cimg_verbosity, + cimg::t_normal); + + std::fprintf(cimg::output()," > Stricts warnings: %s%-13s%s %s('cimg_strict_warnings' %s)%s\n", + cimg::t_bold, +#ifdef cimg_strict_warnings + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Support for C++11: %s%-13s%s %s('cimg_use_cpp11'=%d)%s\n", + cimg::t_bold, + cimg_use_cpp11?"Yes":"No", + cimg::t_normal,cimg::t_green, + (int)cimg_use_cpp11, + cimg::t_normal); + + std::fprintf(cimg::output()," > Using VT100 messages: %s%-13s%s %s('cimg_use_vt100' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_vt100 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Display type: %s%-13s%s %s('cimg_display'=%d)%s\n", + cimg::t_bold, + cimg_display==0?"No display":cimg_display==1?"X11":cimg_display==2?"Windows GDI":"Unknown", + cimg::t_normal,cimg::t_green, + (int)cimg_display, + cimg::t_normal); + +#if cimg_display==1 + std::fprintf(cimg::output()," > Using XShm for X11: %s%-13s%s %s('cimg_use_xshm' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xshm + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using XRand for X11: %s%-13s%s %s('cimg_use_xrandr' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_xrandr + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); +#endif + std::fprintf(cimg::output()," > Using OpenMP: %s%-13s%s %s('cimg_use_openmp' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_openmp + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using PNG library: %s%-13s%s %s('cimg_use_png' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_png + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + std::fprintf(cimg::output()," > Using JPEG library: %s%-13s%s %s('cimg_use_jpeg' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_jpeg + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using TIFF library: %s%-13s%s %s('cimg_use_tiff' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_tiff + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using Magick++ library: %s%-13s%s %s('cimg_use_magick' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_magick + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using FFTW3 library: %s%-13s%s %s('cimg_use_fftw3' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_fftw3 + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + std::fprintf(cimg::output()," > Using LAPACK library: %s%-13s%s %s('cimg_use_lapack' %s)%s\n", + cimg::t_bold, +#ifdef cimg_use_lapack + "Yes",cimg::t_normal,cimg::t_green,"defined", +#else + "No",cimg::t_normal,cimg::t_green,"undefined", +#endif + cimg::t_normal); + + char *const tmp = new char[1024]; + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::imagemagick_path()); + std::fprintf(cimg::output()," > Path of ImageMagick: %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::graphicsmagick_path()); + std::fprintf(cimg::output()," > Path of GraphicsMagick: %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::medcon_path()); + std::fprintf(cimg::output()," > Path of 'medcon': %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + cimg_snprintf(tmp,1024,"\"%.1020s\"",cimg::temporary_path()); + std::fprintf(cimg::output()," > Temporary path: %s%-13s%s\n", + cimg::t_bold, + tmp, + cimg::t_normal); + + std::fprintf(cimg::output(),"\n"); + delete[] tmp; + } + + // Declare LAPACK function signatures if LAPACK support is enabled. +#ifdef cimg_use_lapack + template + inline void getrf(int &N, T *lapA, int *IPIV, int &INFO) { + dgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + inline void getrf(int &N, float *lapA, int *IPIV, int &INFO) { + sgetrf_(&N,&N,lapA,&N,IPIV,&INFO); + } + + template + inline void getri(int &N, T *lapA, int *IPIV, T* WORK, int &LWORK, int &INFO) { + dgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + inline void getri(int &N, float *lapA, int *IPIV, float* WORK, int &LWORK, int &INFO) { + sgetri_(&N,lapA,&N,IPIV,WORK,&LWORK,&INFO); + } + + template + inline void gesvd(char &JOB, int &M, int &N, T *lapA, int &MN, + T *lapS, T *lapU, T *lapV, T *WORK, int &LWORK, int &INFO) { + dgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + inline void gesvd(char &JOB, int &M, int &N, float *lapA, int &MN, + float *lapS, float *lapU, float *lapV, float *WORK, int &LWORK, int &INFO) { + sgesvd_(&JOB,&JOB,&M,&N,lapA,&MN,lapS,lapU,&M,lapV,&N,WORK,&LWORK,&INFO); + } + + template + inline void getrs(char &TRANS, int &N, T *lapA, int *IPIV, T *lapB, int &INFO) { + int one = 1; + dgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + inline void getrs(char &TRANS, int &N, float *lapA, int *IPIV, float *lapB, int &INFO) { + int one = 1; + sgetrs_(&TRANS,&N,&one,lapA,&N,IPIV,lapB,&N,&INFO); + } + + template + inline void syev(char &JOB, char &UPLO, int &N, T *lapA, T *lapW, T *WORK, int &LWORK, int &INFO) { + dsyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + inline void syev(char &JOB, char &UPLO, int &N, float *lapA, float *lapW, float *WORK, int &LWORK, int &INFO) { + ssyev_(&JOB,&UPLO,&N,lapA,&N,lapW,WORK,&LWORK,&INFO); + } + + template + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, T* lapA, int &LDA, + T* lapB, int &LDB, T* WORK, int &LWORK, int &INFO){ + dgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + + inline void sgels(char & TRANS, int &M, int &N, int &NRHS, float* lapA, int &LDA, + float* lapB, int &LDB, float* WORK, int &LWORK, int &INFO){ + sgels_(&TRANS, &M, &N, &NRHS, lapA, &LDA, lapB, &LDB, WORK, &LWORK, &INFO); + } + +#endif + + // End of the 'cimg' namespace + } + + /*------------------------------------------------ + # + # + # Definition of mathematical operators and + # external functions. + # + # + -------------------------------------------------*/ + +#define _cimg_create_ext_operators(typ) \ + template \ + inline CImg::type> operator+(const typ val, const CImg& img) { \ + return img + val; \ + } \ + template \ + inline CImg::type> operator-(const typ val, const CImg& img) { \ + typedef typename cimg::superset::type Tt; \ + return CImg(img._width,img._height,img._depth,img._spectrum,val)-=img; \ + } \ + template \ + inline CImg::type> operator*(const typ val, const CImg& img) { \ + return img*val; \ + } \ + template \ + inline CImg::type> operator/(const typ val, const CImg& img) { \ + return val*img.get_invert(); \ + } \ + template \ + inline CImg::type> operator&(const typ val, const CImg& img) { \ + return img & val; \ + } \ + template \ + inline CImg::type> operator|(const typ val, const CImg& img) { \ + return img | val; \ + } \ + template \ + inline CImg::type> operator^(const typ val, const CImg& img) { \ + return img ^ val; \ + } \ + template \ + inline bool operator==(const typ val, const CImg& img) { \ + return img == val; \ + } \ + template \ + inline bool operator!=(const typ val, const CImg& img) { \ + return img != val; \ + } + + _cimg_create_ext_operators(bool) + _cimg_create_ext_operators(unsigned char) + _cimg_create_ext_operators(char) + _cimg_create_ext_operators(signed char) + _cimg_create_ext_operators(unsigned short) + _cimg_create_ext_operators(short) + _cimg_create_ext_operators(unsigned int) + _cimg_create_ext_operators(int) + _cimg_create_ext_operators(cimg_uint64) + _cimg_create_ext_operators(cimg_int64) + _cimg_create_ext_operators(float) + _cimg_create_ext_operators(double) + _cimg_create_ext_operators(long double) + + template + inline CImg<_cimg_Tfloat> operator+(const char *const expression, const CImg& img) { + return img + expression; + } + + template + inline CImg<_cimg_Tfloat> operator-(const char *const expression, const CImg& img) { + return CImg<_cimg_Tfloat>(img,false).fill(expression,true)-=img; + } + + template + inline CImg<_cimg_Tfloat> operator*(const char *const expression, const CImg& img) { + return img*expression; + } + + template + inline CImg<_cimg_Tfloat> operator/(const char *const expression, const CImg& img) { + return expression*img.get_invert(); + } + + template + inline CImg operator&(const char *const expression, const CImg& img) { + return img & expression; + } + + template + inline CImg operator|(const char *const expression, const CImg& img) { + return img | expression; + } + + template + inline CImg operator^(const char *const expression, const CImg& img) { + return img ^ expression; + } + + template + inline bool operator==(const char *const expression, const CImg& img) { + return img==expression; + } + + template + inline bool operator!=(const char *const expression, const CImg& img) { + return img!=expression; + } + + template + inline CImg<_cimg_Tfloat> sqr(const CImg& instance) { + return instance.get_sqr(); + } + + template + inline CImg<_cimg_Tfloat> sqrt(const CImg& instance) { + return instance.get_sqrt(); + } + + template + inline CImg<_cimg_Tfloat> exp(const CImg& instance) { + return instance.get_exp(); + } + + template + inline CImg<_cimg_Tfloat> log(const CImg& instance) { + return instance.get_log(); + } + + template + inline CImg<_cimg_Tfloat> log2(const CImg& instance) { + return instance.get_log2(); + } + + template + inline CImg<_cimg_Tfloat> log10(const CImg& instance) { + return instance.get_log10(); + } + + template + inline CImg<_cimg_Tfloat> abs(const CImg& instance) { + return instance.get_abs(); + } + + template + inline CImg<_cimg_Tfloat> sign(const CImg& instance) { + return instance.get_sign(); + } + + template + inline CImg<_cimg_Tfloat> cos(const CImg& instance) { + return instance.get_cos(); + } + + template + inline CImg<_cimg_Tfloat> sin(const CImg& instance) { + return instance.get_sin(); + } + + template + inline CImg<_cimg_Tfloat> sinc(const CImg& instance) { + return instance.get_sinc(); + } + + template + inline CImg<_cimg_Tfloat> tan(const CImg& instance) { + return instance.get_tan(); + } + + template + inline CImg<_cimg_Tfloat> acos(const CImg& instance) { + return instance.get_acos(); + } + + template + inline CImg<_cimg_Tfloat> asin(const CImg& instance) { + return instance.get_asin(); + } + + template + inline CImg<_cimg_Tfloat> atan(const CImg& instance) { + return instance.get_atan(); + } + + template + inline CImg<_cimg_Tfloat> cosh(const CImg& instance) { + return instance.get_cosh(); + } + + template + inline CImg<_cimg_Tfloat> sinh(const CImg& instance) { + return instance.get_sinh(); + } + + template + inline CImg<_cimg_Tfloat> tanh(const CImg& instance) { + return instance.get_tanh(); + } + + template + inline CImg transpose(const CImg& instance) { + return instance.get_transpose(); + } + + template + inline CImg<_cimg_Tfloat> invert(const CImg& instance) { + return instance.get_invert(); + } + + template + inline CImg<_cimg_Tfloat> pseudoinvert(const CImg& instance) { + return instance.get_pseudoinvert(); + } + + /*----------------------------------- + # + # Define the CImgDisplay structure + # + ----------------------------------*/ + //! Allow the creation of windows, display images on them and manage user events (keyboard, mouse and windows events). + /** + CImgDisplay methods rely on a low-level graphic library to perform: it can be either \b X-Window + (X11, for Unix-based systems) or \b GDI32 (for Windows-based systems). + If both libraries are missing, CImgDisplay will not be able to display images on screen, and will enter + a minimal mode where warning messages will be outputed each time the program is trying to call one of the + CImgDisplay method. + + The configuration variable \c cimg_display tells about the graphic library used. + It is set automatically by \CImg when one of these graphic libraries has been detected. + But, you can override its value if necessary. Valid choices are: + - 0: Disable display capabilities. + - 1: Use \b X-Window (X11) library. + - 2: Use \b GDI32 library. + + Remember to link your program against \b X11 or \b GDI32 libraries if you use CImgDisplay. + **/ + struct CImgDisplay { + cimg_ulong _timer, _fps_frames, _fps_timer; + unsigned int _width, _height, _normalization; + float _fps_fps, _min, _max; + bool _is_fullscreen; + char *_title; + unsigned int _window_width, _window_height, _button, *_keys, *_released_keys; + int _window_x, _window_y, _mouse_x, _mouse_y, _wheel; + bool _is_closed, _is_resized, _is_moved, _is_event, + _is_keyESC, _is_keyF1, _is_keyF2, _is_keyF3, _is_keyF4, _is_keyF5, _is_keyF6, _is_keyF7, + _is_keyF8, _is_keyF9, _is_keyF10, _is_keyF11, _is_keyF12, _is_keyPAUSE, _is_key1, _is_key2, + _is_key3, _is_key4, _is_key5, _is_key6, _is_key7, _is_key8, _is_key9, _is_key0, + _is_keyBACKSPACE, _is_keyINSERT, _is_keyHOME, _is_keyPAGEUP, _is_keyTAB, _is_keyQ, _is_keyW, _is_keyE, + _is_keyR, _is_keyT, _is_keyY, _is_keyU, _is_keyI, _is_keyO, _is_keyP, _is_keyDELETE, + _is_keyEND, _is_keyPAGEDOWN, _is_keyCAPSLOCK, _is_keyA, _is_keyS, _is_keyD, _is_keyF, _is_keyG, + _is_keyH, _is_keyJ, _is_keyK, _is_keyL, _is_keyENTER, _is_keySHIFTLEFT, _is_keyZ, _is_keyX, + _is_keyC, _is_keyV, _is_keyB, _is_keyN, _is_keyM, _is_keySHIFTRIGHT, _is_keyARROWUP, _is_keyCTRLLEFT, + _is_keyAPPLEFT, _is_keyALT, _is_keySPACE, _is_keyALTGR, _is_keyAPPRIGHT, _is_keyMENU, _is_keyCTRLRIGHT, + _is_keyARROWLEFT, _is_keyARROWDOWN, _is_keyARROWRIGHT, _is_keyPAD0, _is_keyPAD1, _is_keyPAD2, _is_keyPAD3, + _is_keyPAD4, _is_keyPAD5, _is_keyPAD6, _is_keyPAD7, _is_keyPAD8, _is_keyPAD9, _is_keyPADADD, _is_keyPADSUB, + _is_keyPADMUL, _is_keyPADDIV; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- + +#ifdef cimgdisplay_plugin +#include cimgdisplay_plugin +#endif +#ifdef cimgdisplay_plugin1 +#include cimgdisplay_plugin1 +#endif +#ifdef cimgdisplay_plugin2 +#include cimgdisplay_plugin2 +#endif +#ifdef cimgdisplay_plugin3 +#include cimgdisplay_plugin3 +#endif +#ifdef cimgdisplay_plugin4 +#include cimgdisplay_plugin4 +#endif +#ifdef cimgdisplay_plugin5 +#include cimgdisplay_plugin5 +#endif +#ifdef cimgdisplay_plugin6 +#include cimgdisplay_plugin6 +#endif +#ifdef cimgdisplay_plugin7 +#include cimgdisplay_plugin7 +#endif +#ifdef cimgdisplay_plugin8 +#include cimgdisplay_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + \note If the associated window is visible on the screen, it is closed by the call to the destructor. + **/ + ~CImgDisplay() { + assign(); + delete[] _keys; + delete[] _released_keys; + } + + //! Construct an empty display. + /** + \note Constructing an empty CImgDisplay instance does not make a window appearing on the screen, until + display of valid data is performed. + \par Example + \code + CImgDisplay disp; // Does actually nothing. + ... + disp.display(img); // Construct new window and display image in it. + \endcode + **/ + CImgDisplay(): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(); + } + + //! Construct a display with specified dimensions. + /** \param width Window width. + \param height Window height. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note A black background is initially displayed on the associated window. + **/ + CImgDisplay(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(width,height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image. + /** \param img Image used as a model to create the window. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note The pixels of the input image are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(img,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list. + /** \param list The images list to display. + \param title Window title. + \param normalization Normalization type + (0=none, 1=always, 2=once, 3=pixel type-dependent, see normalization()). + \param is_fullscreen Tells if fullscreen mode is enabled. + \param is_closed Tells if associated window is initially visible or not. + \note All images of the list, appended along the X-axis, are initially displayed on the associated window. + **/ + template + explicit CImgDisplay(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(list,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of an existing one. + /** + \param disp Display instance to copy. + \note The pixel buffer of the input window is initially displayed on the associated window. + **/ + CImgDisplay(const CImgDisplay& disp): + _width(0),_height(0),_normalization(0), + _min(0),_max(0), + _is_fullscreen(false), + _title(0), + _window_width(0),_window_height(0),_button(0), + _keys(new unsigned int[128]),_released_keys(new unsigned int[128]), + _window_x(0),_window_y(0),_mouse_x(-1),_mouse_y(-1),_wheel(0), + _is_closed(true),_is_resized(false),_is_moved(false),_is_event(false) { + assign(disp); + } + + //! Take a screenshot. + /** + \param[out] img Output screenshot. Can be empty on input + **/ + template + static void screenshot(CImg& img) { + return screenshot(0,0,cimg::type::max(),cimg::type::max(),img); + } + +#if cimg_display==0 + + static void _no_display_exception() { + throw CImgDisplayException("CImgDisplay(): No display available."); + } + + //! Destructor - Empty constructor \inplace. + /** + \note Replace the current instance by an empty display. + **/ + CImgDisplay& assign() { + return flush(); + } + + //! Construct a display with specified dimensions \inplace. + /** + **/ + CImgDisplay& assign(const unsigned int width, const unsigned int height, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + cimg::unused(width,height,title,normalization,is_fullscreen,is_closed); + _no_display_exception(); + return assign(); + } + + //! Construct a display from an image \inplace. + /** + **/ + template + CImgDisplay& assign(const CImg& img, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(img._width,img._height,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display from an image list \inplace. + /** + **/ + template + CImgDisplay& assign(const CImgList& list, + const char *const title=0, const unsigned int normalization=3, + const bool is_fullscreen=false, const bool is_closed=false) { + _no_display_exception(); + return assign(list._width,list._width,title,normalization,is_fullscreen,is_closed); + } + + //! Construct a display as a copy of another one \inplace. + /** + **/ + CImgDisplay& assign(const CImgDisplay &disp) { + _no_display_exception(); + return assign(disp._width,disp._height); + } + +#endif + + //! Return a reference to an empty display. + /** + \note Can be useful for writing function prototypes where one of the argument (of type CImgDisplay&) + must have a default value. + \par Example + \code + void foo(CImgDisplay& disp=CImgDisplay::empty()); + \endcode + **/ + static CImgDisplay& empty() { + static CImgDisplay _empty; + return _empty.assign(); + } + + //! Return a reference to an empty display \const. + static const CImgDisplay& const_empty() { + static const CImgDisplay _empty; + return _empty; + } + +#define cimg_fitscreen(dx,dy,dz) CImgDisplay::_fitscreen(dx,dy,dz,128,-85,false), \ + CImgDisplay::_fitscreen(dx,dy,dz,128,-85,true) + static unsigned int _fitscreen(const unsigned int dx, const unsigned int dy, const unsigned int dz, + const int dmin, const int dmax,const bool return_y) { + const unsigned int _nw = dx + (dz>1?dz:0), _nh = dy + (dz>1?dz:0); + unsigned int nw = _nw?_nw:1, nh = _nh?_nh:1; + const unsigned int + sw = (unsigned int)CImgDisplay::screen_width(), + sh = (unsigned int)CImgDisplay::screen_height(), + mw = dmin<0?(unsigned int)(sw*-dmin/100):(unsigned int)dmin, + mh = dmin<0?(unsigned int)(sh*-dmin/100):(unsigned int)dmin, + Mw = dmax<0?(unsigned int)(sw*-dmax/100):(unsigned int)dmax, + Mh = dmax<0?(unsigned int)(sh*-dmax/100):(unsigned int)dmax; + if (nwMw) { nh = nh*Mw/nw; nh+=(nh==0); nw = Mw; } + if (nh>Mh) { nw = nw*Mh/nh; nw+=(nw==0); nh = Mh; } + if (nwdisp = img is equivalent to disp.display(img). + **/ + template + CImgDisplay& operator=(const CImg& img) { + return display(img); + } + + //! Display list of images on associated window. + /** + \note disp = list is equivalent to disp.display(list). + **/ + template + CImgDisplay& operator=(const CImgList& list) { + return display(list); + } + + //! Construct a display as a copy of another one \inplace. + /** + \note Equivalent to assign(const CImgDisplay&). + **/ + CImgDisplay& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return \c false if display is empty, \c true otherwise. + /** + \note if (disp) { ... } is equivalent to if (!disp.is_empty()) { ... }. + **/ + operator bool() const { + return !is_empty(); + } + + //@} + //------------------------------------------ + // + //! \name Instance Checking + //@{ + //------------------------------------------ + + //! Return \c true if display is empty, \c false otherwise. + /** + **/ + bool is_empty() const { + return !(_width && _height); + } + + //! Return \c true if display is closed (i.e. not visible on the screen), \c false otherwise. + /** + \note + - When a user physically closes the associated window, the display is set to closed. + - A closed display is not destroyed. Its associated window can be show again on the screen using show(). + **/ + bool is_closed() const { + return _is_closed; + } + + //! Return \c true if associated window has been resized on the screen, \c false otherwise. + /** + **/ + bool is_resized() const { + return _is_resized; + } + + //! Return \c true if associated window has been moved on the screen, \c false otherwise. + /** + **/ + bool is_moved() const { + return _is_moved; + } + + //! Return \c true if any event has occured on the associated window, \c false otherwise. + /** + **/ + bool is_event() const { + return _is_event; + } + + //! Return \c true if current display is in fullscreen mode, \c false otherwise. + /** + **/ + bool is_fullscreen() const { + return _is_fullscreen; + } + + //! Return \c true if any key is being pressed on the associated window, \c false otherwise. + /** + \note The methods below do the same only for specific keys. + **/ + bool is_key() const { + return _is_keyESC || _is_keyF1 || _is_keyF2 || _is_keyF3 || + _is_keyF4 || _is_keyF5 || _is_keyF6 || _is_keyF7 || + _is_keyF8 || _is_keyF9 || _is_keyF10 || _is_keyF11 || + _is_keyF12 || _is_keyPAUSE || _is_key1 || _is_key2 || + _is_key3 || _is_key4 || _is_key5 || _is_key6 || + _is_key7 || _is_key8 || _is_key9 || _is_key0 || + _is_keyBACKSPACE || _is_keyINSERT || _is_keyHOME || + _is_keyPAGEUP || _is_keyTAB || _is_keyQ || _is_keyW || + _is_keyE || _is_keyR || _is_keyT || _is_keyY || + _is_keyU || _is_keyI || _is_keyO || _is_keyP || + _is_keyDELETE || _is_keyEND || _is_keyPAGEDOWN || + _is_keyCAPSLOCK || _is_keyA || _is_keyS || _is_keyD || + _is_keyF || _is_keyG || _is_keyH || _is_keyJ || + _is_keyK || _is_keyL || _is_keyENTER || + _is_keySHIFTLEFT || _is_keyZ || _is_keyX || _is_keyC || + _is_keyV || _is_keyB || _is_keyN || _is_keyM || + _is_keySHIFTRIGHT || _is_keyARROWUP || _is_keyCTRLLEFT || + _is_keyAPPLEFT || _is_keyALT || _is_keySPACE || _is_keyALTGR || + _is_keyAPPRIGHT || _is_keyMENU || _is_keyCTRLRIGHT || + _is_keyARROWLEFT || _is_keyARROWDOWN || _is_keyARROWRIGHT || + _is_keyPAD0 || _is_keyPAD1 || _is_keyPAD2 || + _is_keyPAD3 || _is_keyPAD4 || _is_keyPAD5 || + _is_keyPAD6 || _is_keyPAD7 || _is_keyPAD8 || + _is_keyPAD9 || _is_keyPADADD || _is_keyPADSUB || + _is_keyPADMUL || _is_keyPADDIV; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode Keycode to test. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.key(cimg::keyTAB)) { ... } // Equivalent to 'if (disp.is_keyTAB())'. + disp.wait(); + } + \endcode + **/ + bool is_key(const unsigned int keycode) const { +#define _cimg_iskey_test(k) if (keycode==cimg::key##k) return _is_key##k; + _cimg_iskey_test(ESC); _cimg_iskey_test(F1); _cimg_iskey_test(F2); _cimg_iskey_test(F3); + _cimg_iskey_test(F4); _cimg_iskey_test(F5); _cimg_iskey_test(F6); _cimg_iskey_test(F7); + _cimg_iskey_test(F8); _cimg_iskey_test(F9); _cimg_iskey_test(F10); _cimg_iskey_test(F11); + _cimg_iskey_test(F12); _cimg_iskey_test(PAUSE); _cimg_iskey_test(1); _cimg_iskey_test(2); + _cimg_iskey_test(3); _cimg_iskey_test(4); _cimg_iskey_test(5); _cimg_iskey_test(6); + _cimg_iskey_test(7); _cimg_iskey_test(8); _cimg_iskey_test(9); _cimg_iskey_test(0); + _cimg_iskey_test(BACKSPACE); _cimg_iskey_test(INSERT); _cimg_iskey_test(HOME); + _cimg_iskey_test(PAGEUP); _cimg_iskey_test(TAB); _cimg_iskey_test(Q); _cimg_iskey_test(W); + _cimg_iskey_test(E); _cimg_iskey_test(R); _cimg_iskey_test(T); _cimg_iskey_test(Y); + _cimg_iskey_test(U); _cimg_iskey_test(I); _cimg_iskey_test(O); _cimg_iskey_test(P); + _cimg_iskey_test(DELETE); _cimg_iskey_test(END); _cimg_iskey_test(PAGEDOWN); + _cimg_iskey_test(CAPSLOCK); _cimg_iskey_test(A); _cimg_iskey_test(S); _cimg_iskey_test(D); + _cimg_iskey_test(F); _cimg_iskey_test(G); _cimg_iskey_test(H); _cimg_iskey_test(J); + _cimg_iskey_test(K); _cimg_iskey_test(L); _cimg_iskey_test(ENTER); + _cimg_iskey_test(SHIFTLEFT); _cimg_iskey_test(Z); _cimg_iskey_test(X); _cimg_iskey_test(C); + _cimg_iskey_test(V); _cimg_iskey_test(B); _cimg_iskey_test(N); _cimg_iskey_test(M); + _cimg_iskey_test(SHIFTRIGHT); _cimg_iskey_test(ARROWUP); _cimg_iskey_test(CTRLLEFT); + _cimg_iskey_test(APPLEFT); _cimg_iskey_test(ALT); _cimg_iskey_test(SPACE); _cimg_iskey_test(ALTGR); + _cimg_iskey_test(APPRIGHT); _cimg_iskey_test(MENU); _cimg_iskey_test(CTRLRIGHT); + _cimg_iskey_test(ARROWLEFT); _cimg_iskey_test(ARROWDOWN); _cimg_iskey_test(ARROWRIGHT); + _cimg_iskey_test(PAD0); _cimg_iskey_test(PAD1); _cimg_iskey_test(PAD2); + _cimg_iskey_test(PAD3); _cimg_iskey_test(PAD4); _cimg_iskey_test(PAD5); + _cimg_iskey_test(PAD6); _cimg_iskey_test(PAD7); _cimg_iskey_test(PAD8); + _cimg_iskey_test(PAD9); _cimg_iskey_test(PADADD); _cimg_iskey_test(PADSUB); + _cimg_iskey_test(PADMUL); _cimg_iskey_test(PADDIV); + return false; + } + + //! Return \c true if key specified by given keycode is being pressed on the associated window, \c false otherwise. + /** + \param keycode C-string containing the keycode label of the key to test. + \note Use it when the key you want to test can be dynamically set by the user. + \par Example + \code + CImgDisplay disp(400,400); + const char *const keycode = "TAB"; + while (!disp.is_closed()) { + if (disp.is_key(keycode)) { ... } // Equivalent to 'if (disp.is_keyTAB())'. + disp.wait(); + } + \endcode + **/ + bool& is_key(const char *const keycode) { + static bool f = false; + f = false; +#define _cimg_iskey_test2(k) if (!cimg::strcasecmp(keycode,#k)) return _is_key##k; + _cimg_iskey_test2(ESC); _cimg_iskey_test2(F1); _cimg_iskey_test2(F2); _cimg_iskey_test2(F3); + _cimg_iskey_test2(F4); _cimg_iskey_test2(F5); _cimg_iskey_test2(F6); _cimg_iskey_test2(F7); + _cimg_iskey_test2(F8); _cimg_iskey_test2(F9); _cimg_iskey_test2(F10); _cimg_iskey_test2(F11); + _cimg_iskey_test2(F12); _cimg_iskey_test2(PAUSE); _cimg_iskey_test2(1); _cimg_iskey_test2(2); + _cimg_iskey_test2(3); _cimg_iskey_test2(4); _cimg_iskey_test2(5); _cimg_iskey_test2(6); + _cimg_iskey_test2(7); _cimg_iskey_test2(8); _cimg_iskey_test2(9); _cimg_iskey_test2(0); + _cimg_iskey_test2(BACKSPACE); _cimg_iskey_test2(INSERT); _cimg_iskey_test2(HOME); + _cimg_iskey_test2(PAGEUP); _cimg_iskey_test2(TAB); _cimg_iskey_test2(Q); _cimg_iskey_test2(W); + _cimg_iskey_test2(E); _cimg_iskey_test2(R); _cimg_iskey_test2(T); _cimg_iskey_test2(Y); + _cimg_iskey_test2(U); _cimg_iskey_test2(I); _cimg_iskey_test2(O); _cimg_iskey_test2(P); + _cimg_iskey_test2(DELETE); _cimg_iskey_test2(END); _cimg_iskey_test2(PAGEDOWN); + _cimg_iskey_test2(CAPSLOCK); _cimg_iskey_test2(A); _cimg_iskey_test2(S); _cimg_iskey_test2(D); + _cimg_iskey_test2(F); _cimg_iskey_test2(G); _cimg_iskey_test2(H); _cimg_iskey_test2(J); + _cimg_iskey_test2(K); _cimg_iskey_test2(L); _cimg_iskey_test2(ENTER); + _cimg_iskey_test2(SHIFTLEFT); _cimg_iskey_test2(Z); _cimg_iskey_test2(X); _cimg_iskey_test2(C); + _cimg_iskey_test2(V); _cimg_iskey_test2(B); _cimg_iskey_test2(N); _cimg_iskey_test2(M); + _cimg_iskey_test2(SHIFTRIGHT); _cimg_iskey_test2(ARROWUP); _cimg_iskey_test2(CTRLLEFT); + _cimg_iskey_test2(APPLEFT); _cimg_iskey_test2(ALT); _cimg_iskey_test2(SPACE); _cimg_iskey_test2(ALTGR); + _cimg_iskey_test2(APPRIGHT); _cimg_iskey_test2(MENU); _cimg_iskey_test2(CTRLRIGHT); + _cimg_iskey_test2(ARROWLEFT); _cimg_iskey_test2(ARROWDOWN); _cimg_iskey_test2(ARROWRIGHT); + _cimg_iskey_test2(PAD0); _cimg_iskey_test2(PAD1); _cimg_iskey_test2(PAD2); + _cimg_iskey_test2(PAD3); _cimg_iskey_test2(PAD4); _cimg_iskey_test2(PAD5); + _cimg_iskey_test2(PAD6); _cimg_iskey_test2(PAD7); _cimg_iskey_test2(PAD8); + _cimg_iskey_test2(PAD9); _cimg_iskey_test2(PADADD); _cimg_iskey_test2(PADSUB); + _cimg_iskey_test2(PADMUL); _cimg_iskey_test2(PADDIV); + return f; + } + + //! Return \c true if specified key sequence has been typed on the associated window, \c false otherwise. + /** + \param keycodes_sequence Buffer of keycodes to test. + \param length Number of keys in the \c keycodes_sequence buffer. + \param remove_sequence Tells if the key sequence must be removed from the key history, if found. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + CImgDisplay disp(400,400); + const unsigned int key_seq[] = { cimg::keyCTRLLEFT, cimg::keyD }; + while (!disp.is_closed()) { + if (disp.is_key_sequence(key_seq,2)) { ... } // Test for the 'CTRL+D' keyboard event. + disp.wait(); + } + \endcode + **/ + bool is_key_sequence(const unsigned int *const keycodes_sequence, const unsigned int length, + const bool remove_sequence=false) { + if (keycodes_sequence && length) { + const unsigned int + *const ps_end = keycodes_sequence + length - 1, + *const pk_end = (unsigned int*)_keys + 1 + 128 - length, + k = *ps_end; + for (unsigned int *pk = (unsigned int*)_keys; pk[0,255]. + If the range of values of the data to display is different, a normalization may be required for displaying + the data in a correct way. The normalization type can be one of: + - \c 0: Value normalization is disabled. It is then assumed that all input data to be displayed by the + CImgDisplay instance have values in range [0,255]. + - \c 1: Value normalization is always performed (this is the default behavior). + Before displaying an input image, its values will be (virtually) stretched + in range [0,255], so that the contrast of the displayed pixels will be maximum. + Use this mode for images whose minimum and maximum values are not prescribed to known values + (e.g. float-valued images). + Note that when normalized versions of images are computed for display purposes, the actual values of these + images are not modified. + - \c 2: Value normalization is performed once (on the first image display), then the same normalization + coefficients are kept for next displayed frames. + - \c 3: Value normalization depends on the pixel type of the data to display. For integer pixel types, + the normalization is done regarding the minimum/maximum values of the type (no normalization occurs then + for unsigned char). + For float-valued pixel types, the normalization is done regarding the minimum/maximum value of the image + data instead. + **/ + unsigned int normalization() const { + return _normalization; + } + + //! Return title of the associated window as a C-string. + /** + \note Window title may be not visible, depending on the used window manager or if the current display is + in fullscreen mode. + **/ + const char *title() const { + return _title?_title:""; + } + + //! Return width of the associated window. + /** + \note The width of the display (i.e. the width of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual width of the associated window. + **/ + int window_width() const { + return (int)_window_width; + } + + //! Return height of the associated window. + /** + \note The height of the display (i.e. the height of the pixel data buffer associated to the CImgDisplay instance) + may be different from the actual height of the associated window. + **/ + int window_height() const { + return (int)_window_height; + } + + //! Return X-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_x() const { + return _window_x; + } + + //! Return Y-coordinate of the associated window. + /** + \note The returned coordinate corresponds to the location of the upper-left corner of the associated window. + **/ + int window_y() const { + return _window_y; + } + + //! Return X-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,width()-1]. + **/ + int mouse_x() const { + return _mouse_x; + } + + //! Return Y-coordinate of the mouse pointer. + /** + \note + - If the mouse pointer is outside window area, \c -1 is returned. + - Otherwise, the returned value is in the range [0,height()-1]. + **/ + int mouse_y() const { + return _mouse_y; + } + + //! Return current state of the mouse buttons. + /** + \note Three mouse buttons can be managed. If one button is pressed, its corresponding bit in the returned + value is set: + - bit \c 0 (value \c 0x1): State of the left mouse button. + - bit \c 1 (value \c 0x2): State of the right mouse button. + - bit \c 2 (value \c 0x4): State of the middle mouse button. + + Several bits can be activated if more than one button are pressed at the same time. + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.button()&1) { // Left button clicked. + ... + } + if (disp.button()&2) { // Right button clicked. + ... + } + if (disp.button()&4) { // Middle button clicked. + ... + } + disp.wait(); + } + \endcode + **/ + unsigned int button() const { + return _button; + } + + //! Return current state of the mouse wheel. + /** + \note + - The returned value can be positive or negative depending on whether the mouse wheel has been scrolled + forward or backward. + - Scrolling the wheel forward add \c 1 to the wheel value. + - Scrolling the wheel backward substract \c 1 to the wheel value. + - The returned value cumulates the number of forward of backward scrolls since the creation of the display, + or since the last reset of the wheel value (using set_wheel()). It is strongly recommended to quickly reset + the wheel counter when an action has been performed regarding the current wheel value. + Otherwise, the returned wheel value may be for instance \c 0 despite the fact that many scrolls have been done + (as many in forward as in backward directions). + \par Example + \code + CImgDisplay disp(400,400); + while (!disp.is_closed()) { + if (disp.wheel()) { + int counter = disp.wheel(); // Read the state of the mouse wheel. + ... // Do what you want with 'counter'. + disp.set_wheel(); // Reset the wheel value to 0. + } + disp.wait(); + } + \endcode + **/ + int wheel() const { + return _wheel; + } + + //! Return one entry from the pressed keys history. + /** + \param pos Indice to read from the pressed keys history (indice \c 0 corresponds to latest entry). + \return Keycode of a pressed key or \c 0 for a released key. + \note + - Each CImgDisplay stores a history of the pressed keys in a buffer of size \c 128. When a new key is pressed, + its keycode is stored in the pressed keys history. When a key is released, \c 0 is put instead. + This means that up to the 64 last pressed keys may be read from the pressed keys history. + When a new value is stored, the pressed keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int key(const unsigned int pos=0) const { + return pos<128?_keys[pos]:0; + } + + //! Return one entry from the released keys history. + /** + \param pos Indice to read from the released keys history (indice \c 0 corresponds to latest entry). + \return Keycode of a released key or \c 0 for a pressed key. + \note + - Each CImgDisplay stores a history of the released keys in a buffer of size \c 128. When a new key is released, + its keycode is stored in the pressed keys history. When a key is pressed, \c 0 is put instead. + This means that up to the 64 last released keys may be read from the released keys history. + When a new value is stored, the released keys history is shifted so that the latest entry is always + stored at position \c 0. + - Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + unsigned int released_key(const unsigned int pos=0) const { + return pos<128?_released_keys[pos]:0; + } + + //! Return keycode corresponding to the specified string. + /** + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + \par Example + \code + const unsigned int keyTAB = CImgDisplay::keycode("TAB"); // Return cimg::keyTAB. + \endcode + **/ + static unsigned int keycode(const char *const keycode) { +#define _cimg_keycode(k) if (!cimg::strcasecmp(keycode,#k)) return cimg::key##k; + _cimg_keycode(ESC); _cimg_keycode(F1); _cimg_keycode(F2); _cimg_keycode(F3); + _cimg_keycode(F4); _cimg_keycode(F5); _cimg_keycode(F6); _cimg_keycode(F7); + _cimg_keycode(F8); _cimg_keycode(F9); _cimg_keycode(F10); _cimg_keycode(F11); + _cimg_keycode(F12); _cimg_keycode(PAUSE); _cimg_keycode(1); _cimg_keycode(2); + _cimg_keycode(3); _cimg_keycode(4); _cimg_keycode(5); _cimg_keycode(6); + _cimg_keycode(7); _cimg_keycode(8); _cimg_keycode(9); _cimg_keycode(0); + _cimg_keycode(BACKSPACE); _cimg_keycode(INSERT); _cimg_keycode(HOME); + _cimg_keycode(PAGEUP); _cimg_keycode(TAB); _cimg_keycode(Q); _cimg_keycode(W); + _cimg_keycode(E); _cimg_keycode(R); _cimg_keycode(T); _cimg_keycode(Y); + _cimg_keycode(U); _cimg_keycode(I); _cimg_keycode(O); _cimg_keycode(P); + _cimg_keycode(DELETE); _cimg_keycode(END); _cimg_keycode(PAGEDOWN); + _cimg_keycode(CAPSLOCK); _cimg_keycode(A); _cimg_keycode(S); _cimg_keycode(D); + _cimg_keycode(F); _cimg_keycode(G); _cimg_keycode(H); _cimg_keycode(J); + _cimg_keycode(K); _cimg_keycode(L); _cimg_keycode(ENTER); + _cimg_keycode(SHIFTLEFT); _cimg_keycode(Z); _cimg_keycode(X); _cimg_keycode(C); + _cimg_keycode(V); _cimg_keycode(B); _cimg_keycode(N); _cimg_keycode(M); + _cimg_keycode(SHIFTRIGHT); _cimg_keycode(ARROWUP); _cimg_keycode(CTRLLEFT); + _cimg_keycode(APPLEFT); _cimg_keycode(ALT); _cimg_keycode(SPACE); _cimg_keycode(ALTGR); + _cimg_keycode(APPRIGHT); _cimg_keycode(MENU); _cimg_keycode(CTRLRIGHT); + _cimg_keycode(ARROWLEFT); _cimg_keycode(ARROWDOWN); _cimg_keycode(ARROWRIGHT); + _cimg_keycode(PAD0); _cimg_keycode(PAD1); _cimg_keycode(PAD2); + _cimg_keycode(PAD3); _cimg_keycode(PAD4); _cimg_keycode(PAD5); + _cimg_keycode(PAD6); _cimg_keycode(PAD7); _cimg_keycode(PAD8); + _cimg_keycode(PAD9); _cimg_keycode(PADADD); _cimg_keycode(PADSUB); + _cimg_keycode(PADMUL); _cimg_keycode(PADDIV); + return 0; + } + + //! Return the current refresh rate, in frames per second. + /** + \note Returns a significant value when the current instance is used to display successive frames. + It measures the delay between successive calls to frames_per_second(). + **/ + float frames_per_second() { + if (!_fps_timer) _fps_timer = cimg::time(); + const float delta = (cimg::time() - _fps_timer)/1000.0f; + ++_fps_frames; + if (delta>=1) { + _fps_fps = _fps_frames/delta; + _fps_frames = 0; + _fps_timer = cimg::time(); + } + return _fps_fps; + } + + //@} + //--------------------------------------- + // + //! \name Window Manipulation + //@{ + //--------------------------------------- + +#if cimg_display==0 + + //! Display image on associated window. + /** + \param img Input image to display. + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImg& img) { + return assign(img); + } + +#endif + + //! Display list of images on associated window. + /** + \param list List of images to display. + \param axis Axis used to append the images along, for the visualization (can be \c x, \c y, \c z or \c c). + \param align Relative position of aligned images when displaying lists with images of different sizes + (\c 0 for upper-left, \c 0.5 for centering and \c 1 for lower-right). + \note This method returns immediately. + **/ + template + CImgDisplay& display(const CImgList& list, const char axis='x', const float align=0) { + if (list._width==1) { + const CImg& img = list[0]; + if (img._depth==1 && (img._spectrum==1 || img._spectrum>=3) && _normalization!=1) return display(img); + } + CImgList::ucharT> visu(list._width); + unsigned int dims = 0; + cimglist_for(list,l) { + const CImg& img = list._data[l]; + img.__get_select(*this,_normalization,(img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2).move_to(visu[l]); + dims = std::max(dims,visu[l]._spectrum); + } + cimglist_for(list,l) if (visu[l]._spectrumimg.width() become equal, as well as height() and + img.height(). + - The associated window is also resized to specified dimensions. + **/ + template + CImgDisplay& resize(const CImg& img, const bool force_redraw=true) { + return resize(img._width,img._height,force_redraw); + } + + //! Resize display to the size of another CImgDisplay instance. + /** + \param disp Input display to take size from. + \param force_redraw Tells if the previous window content must be resized and updated as well. + \note + - Calling this method ensures that width() and disp.width() become equal, as well as height() and + disp.height(). + - The associated window is also resized to specified dimensions. + **/ + CImgDisplay& resize(const CImgDisplay& disp, const bool force_redraw=true) { + return resize(disp.width(),disp.height(),force_redraw); + } + + // [internal] Render pixel buffer with size (wd,hd) from source buffer of size (ws,hs). + template + static void _render_resize(const T *ptrs, const unsigned int ws, const unsigned int hs, + t *ptrd, const unsigned int wd, const unsigned int hd) { + unsigned int *const offx = new unsigned int[wd], *const offy = new unsigned int[hd + 1], *poffx, *poffy; + float s, curr, old; + s = (float)ws/wd; + poffx = offx; curr = 0; for (unsigned int x = 0; xstd::printf(). + \warning As the first argument is a format string, it is highly recommended to write + \code + disp.set_title("%s",window_title); + \endcode + instead of + \code + disp.set_title(window_title); + \endcode + if \c window_title can be arbitrary, to prevent nasty memory access. + **/ + CImgDisplay& set_title(const char *const format, ...) { + return assign(0,0,format); + } + +#endif + + //! Enable or disable fullscreen mode. + /** + \param is_fullscreen Tells is the fullscreen mode must be activated or not. + \param force_redraw Tells if the previous window content must be displayed as well. + \note + - When the fullscreen mode is enabled, the associated window fills the entire screen but the size of the + current display is not modified. + - The screen resolution may be switched to fit the associated window size and ensure it appears the largest + as possible. + For X-Window (X11) users, the configuration flag \c cimg_use_xrandr has to be set to allow the screen + resolution change (requires the X11 extensions to be enabled). + **/ + CImgDisplay& set_fullscreen(const bool is_fullscreen, const bool force_redraw=true) { + if (is_empty() || _is_fullscreen==is_fullscreen) return *this; + return toggle_fullscreen(force_redraw); + } + +#if cimg_display==0 + + //! Toggle fullscreen mode. + /** + \param force_redraw Tells if the previous window content must be displayed as well. + \note Enable fullscreen mode if it was not enabled, and disable it otherwise. + **/ + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + return assign(_width,_height,0,3,force_redraw); + } + + //! Show mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& show_mouse() { + return assign(); + } + + //! Hide mouse pointer. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& hide_mouse() { + return assign(); + } + + //! Move mouse pointer to a specified location. + /** + \note Depending on the window manager behavior, this method may not succeed + (no exceptions are thrown nevertheless). + **/ + CImgDisplay& set_mouse(const int pos_x, const int pos_y) { + return assign(pos_x,pos_y); + } + +#endif + + //! Simulate a mouse button release event. + /** + \note All mouse buttons are considered released at the same time. + **/ + CImgDisplay& set_button() { + _button = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a mouse button press or release event. + /** + \param button Buttons event code, where each button is associated to a single bit. + \param is_pressed Tells if the mouse button is considered as pressed or released. + **/ + CImgDisplay& set_button(const unsigned int button, const bool is_pressed=true) { + const unsigned int buttoncode = button==1U?1U:button==2U?2U:button==3U?4U:0U; + if (is_pressed) _button |= buttoncode; else _button &= ~buttoncode; + _is_event = buttoncode?true:false; + if (buttoncode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all mouse wheel events. + /** + \note Make wheel() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_wheel() { + _wheel = 0; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a wheel event. + /** + \param amplitude Amplitude of the wheel scrolling to simulate. + \note Make wheel() to return \c amplitude, if called afterwards. + **/ + CImgDisplay& set_wheel(const int amplitude) { + _wheel+=amplitude; + _is_event = amplitude?true:false; + if (amplitude) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all key events. + /** + \note Make key() to return \c 0, if called afterwards. + **/ + CImgDisplay& set_key() { + std::memset((void*)_keys,0,128*sizeof(unsigned int)); + std::memset((void*)_released_keys,0,128*sizeof(unsigned int)); + _is_keyESC = _is_keyF1 = _is_keyF2 = _is_keyF3 = _is_keyF4 = _is_keyF5 = _is_keyF6 = _is_keyF7 = _is_keyF8 = + _is_keyF9 = _is_keyF10 = _is_keyF11 = _is_keyF12 = _is_keyPAUSE = _is_key1 = _is_key2 = _is_key3 = _is_key4 = + _is_key5 = _is_key6 = _is_key7 = _is_key8 = _is_key9 = _is_key0 = _is_keyBACKSPACE = _is_keyINSERT = + _is_keyHOME = _is_keyPAGEUP = _is_keyTAB = _is_keyQ = _is_keyW = _is_keyE = _is_keyR = _is_keyT = _is_keyY = + _is_keyU = _is_keyI = _is_keyO = _is_keyP = _is_keyDELETE = _is_keyEND = _is_keyPAGEDOWN = _is_keyCAPSLOCK = + _is_keyA = _is_keyS = _is_keyD = _is_keyF = _is_keyG = _is_keyH = _is_keyJ = _is_keyK = _is_keyL = + _is_keyENTER = _is_keySHIFTLEFT = _is_keyZ = _is_keyX = _is_keyC = _is_keyV = _is_keyB = _is_keyN = + _is_keyM = _is_keySHIFTRIGHT = _is_keyARROWUP = _is_keyCTRLLEFT = _is_keyAPPLEFT = _is_keyALT = _is_keySPACE = + _is_keyALTGR = _is_keyAPPRIGHT = _is_keyMENU = _is_keyCTRLRIGHT = _is_keyARROWLEFT = _is_keyARROWDOWN = + _is_keyARROWRIGHT = _is_keyPAD0 = _is_keyPAD1 = _is_keyPAD2 = _is_keyPAD3 = _is_keyPAD4 = _is_keyPAD5 = + _is_keyPAD6 = _is_keyPAD7 = _is_keyPAD8 = _is_keyPAD9 = _is_keyPADADD = _is_keyPADSUB = _is_keyPADMUL = + _is_keyPADDIV = false; + _is_event = true; +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + return *this; + } + + //! Simulate a keyboard press/release event. + /** + \param keycode Keycode of the associated key. + \param is_pressed Tells if the key is considered as pressed or released. + \note Keycode constants are defined in the cimg namespace and are architecture-dependent. Use them to ensure + your code stay portable (see cimg::keyESC). + **/ + CImgDisplay& set_key(const unsigned int keycode, const bool is_pressed=true) { +#define _cimg_set_key(k) if (keycode==cimg::key##k) _is_key##k = is_pressed; + _cimg_set_key(ESC); _cimg_set_key(F1); _cimg_set_key(F2); _cimg_set_key(F3); + _cimg_set_key(F4); _cimg_set_key(F5); _cimg_set_key(F6); _cimg_set_key(F7); + _cimg_set_key(F8); _cimg_set_key(F9); _cimg_set_key(F10); _cimg_set_key(F11); + _cimg_set_key(F12); _cimg_set_key(PAUSE); _cimg_set_key(1); _cimg_set_key(2); + _cimg_set_key(3); _cimg_set_key(4); _cimg_set_key(5); _cimg_set_key(6); + _cimg_set_key(7); _cimg_set_key(8); _cimg_set_key(9); _cimg_set_key(0); + _cimg_set_key(BACKSPACE); _cimg_set_key(INSERT); _cimg_set_key(HOME); + _cimg_set_key(PAGEUP); _cimg_set_key(TAB); _cimg_set_key(Q); _cimg_set_key(W); + _cimg_set_key(E); _cimg_set_key(R); _cimg_set_key(T); _cimg_set_key(Y); + _cimg_set_key(U); _cimg_set_key(I); _cimg_set_key(O); _cimg_set_key(P); + _cimg_set_key(DELETE); _cimg_set_key(END); _cimg_set_key(PAGEDOWN); + _cimg_set_key(CAPSLOCK); _cimg_set_key(A); _cimg_set_key(S); _cimg_set_key(D); + _cimg_set_key(F); _cimg_set_key(G); _cimg_set_key(H); _cimg_set_key(J); + _cimg_set_key(K); _cimg_set_key(L); _cimg_set_key(ENTER); + _cimg_set_key(SHIFTLEFT); _cimg_set_key(Z); _cimg_set_key(X); _cimg_set_key(C); + _cimg_set_key(V); _cimg_set_key(B); _cimg_set_key(N); _cimg_set_key(M); + _cimg_set_key(SHIFTRIGHT); _cimg_set_key(ARROWUP); _cimg_set_key(CTRLLEFT); + _cimg_set_key(APPLEFT); _cimg_set_key(ALT); _cimg_set_key(SPACE); _cimg_set_key(ALTGR); + _cimg_set_key(APPRIGHT); _cimg_set_key(MENU); _cimg_set_key(CTRLRIGHT); + _cimg_set_key(ARROWLEFT); _cimg_set_key(ARROWDOWN); _cimg_set_key(ARROWRIGHT); + _cimg_set_key(PAD0); _cimg_set_key(PAD1); _cimg_set_key(PAD2); + _cimg_set_key(PAD3); _cimg_set_key(PAD4); _cimg_set_key(PAD5); + _cimg_set_key(PAD6); _cimg_set_key(PAD7); _cimg_set_key(PAD8); + _cimg_set_key(PAD9); _cimg_set_key(PADADD); _cimg_set_key(PADSUB); + _cimg_set_key(PADMUL); _cimg_set_key(PADDIV); + if (is_pressed) { + if (*_keys) + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = keycode; + if (*_released_keys) { + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = 0; + } + } else { + if (*_keys) { + std::memmove((void*)(_keys + 1),(void*)_keys,127*sizeof(unsigned int)); + *_keys = 0; + } + if (*_released_keys) + std::memmove((void*)(_released_keys + 1),(void*)_released_keys,127*sizeof(unsigned int)); + *_released_keys = keycode; + } + _is_event = keycode?true:false; + if (keycode) { +#if cimg_display==1 + pthread_cond_broadcast(&cimg::X11_attr().wait_event); +#elif cimg_display==2 + SetEvent(cimg::Win32_attr().wait_event); +#endif + } + return *this; + } + + //! Flush all display events. + /** + \note Remove all passed events from the current display. + **/ + CImgDisplay& flush() { + set_key().set_button().set_wheel(); + _is_resized = _is_moved = _is_event = false; + _fps_timer = _fps_frames = _timer = 0; + _fps_fps = 0; + return *this; + } + + //! Wait for any user event occuring on the current display. + CImgDisplay& wait() { + wait(*this); + return *this; + } + + //! Wait for a given number of milliseconds since the last call to wait(). + /** + \param milliseconds Number of milliseconds to wait for. + \note Similar to cimg::wait(). + **/ + CImgDisplay& wait(const unsigned int milliseconds) { + cimg::_wait(milliseconds,_timer); + return *this; + } + + //! Wait for any event occuring on the display \c disp1. + static void wait(CImgDisplay& disp1) { + disp1._is_event = false; + while (!disp1._is_closed && !disp1._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1 or \c disp2. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2) { + disp1._is_event = disp2._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed) && + !disp1._is_event && !disp2._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2 or \c disp3. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3) { + disp1._is_event = disp2._is_event = disp3._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3 or \c disp4. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4 or \c disp5. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, + CImgDisplay& disp5) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event) + wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp6. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp7. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp8. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp9. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event) wait_all(); + } + + //! Wait for any event occuring either on the display \c disp1, \c disp2, \c disp3, \c disp4, ... \c disp10. + static void wait(CImgDisplay& disp1, CImgDisplay& disp2, CImgDisplay& disp3, CImgDisplay& disp4, CImgDisplay& disp5, + CImgDisplay& disp6, CImgDisplay& disp7, CImgDisplay& disp8, CImgDisplay& disp9, + CImgDisplay& disp10) { + disp1._is_event = disp2._is_event = disp3._is_event = disp4._is_event = disp5._is_event = + disp6._is_event = disp7._is_event = disp8._is_event = disp9._is_event = disp10._is_event = false; + while ((!disp1._is_closed || !disp2._is_closed || !disp3._is_closed || !disp4._is_closed || !disp5._is_closed || + !disp6._is_closed || !disp7._is_closed || !disp8._is_closed || !disp9._is_closed || !disp10._is_closed) && + !disp1._is_event && !disp2._is_event && !disp3._is_event && !disp4._is_event && !disp5._is_event && + !disp6._is_event && !disp7._is_event && !disp8._is_event && !disp9._is_event && !disp10._is_event) + wait_all(); + } + +#if cimg_display==0 + + //! Wait for any window event occuring in any opened CImgDisplay. + static void wait_all() { + return _no_display_exception(); + } + + //! Render image into internal display buffer. + /** + \param img Input image data to render. + \note + - Convert image data representation into the internal display buffer (architecture-dependent structure). + - The content of the associated window is not modified, until paint() is called. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + template + CImgDisplay& render(const CImg& img) { + return assign(img); + } + + //! Paint internal display buffer on associated window. + /** + \note + - Update the content of the associated window with the internal display buffer, e.g. after a render() call. + - Should not be used for common CImgDisplay uses, since display() is more useful. + **/ + CImgDisplay& paint() { + 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 + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& 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. + **/ + template + const CImgDisplay& snapshot(CImg& img) const { + cimg::unused(img); + _no_display_exception(); + return *this; + } +#endif + + // X11-based implementation + //-------------------------- +#if cimg_display==1 + + Atom _wm_window_atom, _wm_protocol_atom; + Window _window, _background_window; + Colormap _colormap; + XImage *_image; + void *_data; +#ifdef cimg_use_xshm + XShmSegmentInfo *_shminfo; +#endif + + static int screen_width() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_width(): Failed to open X11 display."); + res = DisplayWidth(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width; + else res = DisplayWidth(dpy,DefaultScreen(dpy)); +#else + res = DisplayWidth(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static int screen_height() { + Display *const dpy = cimg::X11_attr().display; + int res = 0; + if (!dpy) { + Display *const _dpy = XOpenDisplay(0); + if (!_dpy) + throw CImgDisplayException("CImgDisplay::screen_height(): Failed to open X11 display."); + res = DisplayHeight(_dpy,DefaultScreen(_dpy)); + XCloseDisplay(_dpy); + } else { +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) + res = cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height; + else res = DisplayHeight(dpy,DefaultScreen(dpy)); +#else + res = DisplayHeight(dpy,DefaultScreen(dpy)); +#endif + } + return res; + } + + static void wait_all() { + if (!cimg::X11_attr().display) return; + pthread_mutex_lock(&cimg::X11_attr().wait_event_mutex); + pthread_cond_wait(&cimg::X11_attr().wait_event,&cimg::X11_attr().wait_event_mutex); + pthread_mutex_unlock(&cimg::X11_attr().wait_event_mutex); + } + + void _handle_events(const XEvent *const pevent) { + Display *const dpy = cimg::X11_attr().display; + XEvent event = *pevent; + switch (event.type) { + case ClientMessage : { + if ((int)event.xclient.message_type==(int)_wm_protocol_atom && + (int)event.xclient.data.l[0]==(int)_wm_window_atom) { + XUnmapWindow(cimg::X11_attr().display,_window); + _is_closed = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case ConfigureNotify : { + while (XCheckWindowEvent(dpy,_window,StructureNotifyMask,&event)) {} + const unsigned int nw = event.xconfigure.width, nh = event.xconfigure.height; + const int nx = event.xconfigure.x, ny = event.xconfigure.y; + if (nw && nh && (nw!=_window_width || nh!=_window_height)) { + _window_width = nw; _window_height = nh; _mouse_x = _mouse_y = -1; + XResizeWindow(dpy,_window,_window_width,_window_height); + _is_resized = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + if (nx!=_window_x || ny!=_window_y) { + _window_x = nx; _window_y = ny; _is_moved = _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } + } break; + case Expose : { + while (XCheckWindowEvent(dpy,_window,ExposureMask,&event)) {} + _paint(false); + if (_is_fullscreen) { + XWindowAttributes attr; + XGetWindowAttributes(dpy,_window,&attr); + while (attr.map_state!=IsViewable) XSync(dpy,0); + XSetInputFocus(dpy,_window,RevertToParent,CurrentTime); + } + } break; + case ButtonPress : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1); break; + case 3 : set_button(2); break; + case 2 : set_button(3); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonPressMask,&event)); + } break; + case ButtonRelease : { + do { + _mouse_x = event.xmotion.x; _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + switch (event.xbutton.button) { + case 1 : set_button(1,false); break; + case 3 : set_button(2,false); break; + case 2 : set_button(3,false); break; + case 4 : set_wheel(1); break; + case 5 : set_wheel(-1); break; + } + } while (XCheckWindowEvent(dpy,_window,ButtonReleaseMask,&event)); + } break; + case KeyPress : { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,true); + } break; + case KeyRelease : { + char keys_return[32]; // Check that the key has been physically unpressed. + XQueryKeymap(dpy,keys_return); + const unsigned int kc = event.xkey.keycode, kc1 = kc/8, kc2 = kc%8; + const bool is_key_pressed = kc1>=32?false:(keys_return[kc1]>>kc2)&1; + if (!is_key_pressed) { + char tmp = 0; KeySym ksym; + XLookupString(&event.xkey,&tmp,1,&ksym,0); + set_key((unsigned int)ksym,false); + } + } break; + case EnterNotify: { + while (XCheckWindowEvent(dpy,_window,EnterWindowMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + } break; + case LeaveNotify : { + while (XCheckWindowEvent(dpy,_window,LeaveWindowMask,&event)) {} + _mouse_x = _mouse_y = -1; _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + case MotionNotify : { + while (XCheckWindowEvent(dpy,_window,PointerMotionMask,&event)) {} + _mouse_x = event.xmotion.x; + _mouse_y = event.xmotion.y; + if (_mouse_x<0 || _mouse_y<0 || _mouse_x>=width() || _mouse_y>=height()) _mouse_x = _mouse_y = -1; + _is_event = true; + pthread_cond_broadcast(&cimg::X11_attr().wait_event); + } break; + } + } + + static void* _events_thread(void *arg) { // Thread to manage events for all opened display windows. + Display *const dpy = cimg::X11_attr().display; + XEvent event; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0); + if (!arg) for ( ; ; ) { + cimg_lock_display(); + bool event_flag = XCheckTypedEvent(dpy,ClientMessage,&event); + if (!event_flag) event_flag = XCheckMaskEvent(dpy, + ExposureMask | StructureNotifyMask | ButtonPressMask | + KeyPressMask | PointerMotionMask | EnterWindowMask | + LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask,&event); + if (event_flag) + for (unsigned int i = 0; i_is_closed && event.xany.window==cimg::X11_attr().wins[i]->_window) + cimg::X11_attr().wins[i]->_handle_events(&event); + cimg_unlock_display(); + pthread_testcancel(); + cimg::sleep(8); + } + return 0; + } + + void _set_colormap(Colormap& _colormap, const unsigned int dim) { + XColor *const colormap = new XColor[256]; + switch (dim) { + case 1 : { // colormap for greyscale images + for (unsigned int index = 0; index<256; ++index) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].green = colormap[index].blue = (unsigned short)(index<<8); + colormap[index].flags = DoRed | DoGreen | DoBlue; + } + } break; + case 2 : { // colormap for RG images + for (unsigned int index = 0, r = 8; r<256; r+=16) + for (unsigned int g = 8; g<256; g+=16) { + colormap[index].pixel = index; + colormap[index].red = colormap[index].blue = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } break; + default : { // colormap for RGB images + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap[index].pixel = index; + colormap[index].red = (unsigned short)(r<<8); + colormap[index].green = (unsigned short)(g<<8); + colormap[index].blue = (unsigned short)(b<<8); + colormap[index++].flags = DoRed | DoGreen | DoBlue; + } + } + } + XStoreColors(cimg::X11_attr().display,_colormap,colormap,256); + delete[] colormap; + } + + void _map_window() { + Display *const dpy = cimg::X11_attr().display; + bool is_exposed = false, is_mapped = false; + XWindowAttributes attr; + XEvent event; + XMapRaised(dpy,_window); + do { // Wait for the window to be mapped. + XWindowEvent(dpy,_window,StructureNotifyMask | ExposureMask,&event); + switch (event.type) { + case MapNotify : is_mapped = true; break; + case Expose : is_exposed = true; break; + } + } while (!is_exposed || !is_mapped); + do { // Wait for the window to be visible. + XGetWindowAttributes(dpy,_window,&attr); + if (attr.map_state!=IsViewable) { XSync(dpy,0); cimg::sleep(10); } + } while (attr.map_state!=IsViewable); + _window_x = attr.x; + _window_y = attr.y; + } + + void _paint(const bool wait_expose=true) { + if (_is_closed || !_image) return; + Display *const dpy = cimg::X11_attr().display; + if (wait_expose) { // Send an expose event sticked to display window to force repaint. + XEvent event; + event.xexpose.type = Expose; + event.xexpose.serial = 0; + event.xexpose.send_event = 1; + event.xexpose.display = dpy; + event.xexpose.window = _window; + event.xexpose.x = 0; + event.xexpose.y = 0; + event.xexpose.width = width(); + event.xexpose.height = height(); + event.xexpose.count = 0; + XSendEvent(dpy,_window,0,0,&event); + } else { // Repaint directly (may be called from the expose event). + GC gc = DefaultGC(dpy,DefaultScreen(dpy)); +#ifdef cimg_use_xshm + if (_shminfo) XShmPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height,1); + else XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#else + XPutImage(dpy,_window,gc,_image,0,0,0,0,_width,_height); +#endif + } + } + + template + void _resize(T pixel_type, const unsigned int ndimx, const unsigned int ndimy, const bool force_redraw) { + Display *const dpy = cimg::X11_attr().display; + cimg::unused(pixel_type); + +#ifdef cimg_use_xshm + if (_shminfo) { + XShmSegmentInfo *const nshminfo = new XShmSegmentInfo; + XImage *const nimage = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy); + if (!nimage) { delete nshminfo; return; } + else { + nshminfo->shmid = shmget(IPC_PRIVATE,ndimx*ndimy*sizeof(T),IPC_CREAT | 0777); + if (nshminfo->shmid==-1) { XDestroyImage(nimage); delete nshminfo; return; } + else { + nshminfo->shmaddr = nimage->data = (char*)shmat(nshminfo->shmid,0,0); + if (nshminfo->shmaddr==(char*)-1) { + shmctl(nshminfo->shmid,IPC_RMID,0); XDestroyImage(nimage); delete nshminfo; return; + } else { + nshminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,nshminfo); + XFlush(dpy); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(nshminfo->shmaddr); + shmctl(nshminfo->shmid,IPC_RMID,0); + XDestroyImage(nimage); + delete nshminfo; + return; + } else { + T *const ndata = (T*)nimage->data; + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + XShmDetach(dpy,_shminfo); + XDestroyImage(_image); + shmdt(_shminfo->shmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = nshminfo; + _image = nimage; + _data = (void*)ndata; + } + } + } + } + } else +#endif + { + T *ndata = (T*)std::malloc(ndimx*ndimy*sizeof(T)); + if (force_redraw) _render_resize((T*)_data,_width,_height,ndata,ndimx,ndimy); + else std::memset(ndata,0,sizeof(T)*ndimx*ndimy); + _data = (void*)ndata; + XDestroyImage(_image); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)), + cimg::X11_attr().nb_bits,ZPixmap,0,(char*)_data,ndimx,ndimy,8,0); + } + } + + void _init_fullscreen() { + if (!_is_fullscreen || _is_closed) return; + Display *const dpy = cimg::X11_attr().display; + _background_window = 0; + +#ifdef cimg_use_xrandr + int foo; + if (XRRQueryExtension(dpy,&foo,&foo)) { + XRRRotations(dpy,DefaultScreen(dpy),&cimg::X11_attr().curr_rotation); + if (!cimg::X11_attr().resolutions) { + cimg::X11_attr().resolutions = XRRSizes(dpy,DefaultScreen(dpy),&foo); + cimg::X11_attr().nb_resolutions = (unsigned int)foo; + } + if (cimg::X11_attr().resolutions) { + cimg::X11_attr().curr_resolution = 0; + for (unsigned int i = 0; i=_width && nh>=_height && + nw<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].width) && + nh<=(unsigned int)(cimg::X11_attr().resolutions[cimg::X11_attr().curr_resolution].height)) + cimg::X11_attr().curr_resolution = i; + } + if (cimg::X11_attr().curr_resolution>0) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy), + cimg::X11_attr().curr_resolution,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + } + } + } + if (!cimg::X11_attr().resolutions) + cimg::warn(_cimgdisplay_instance + "init_fullscreen(): Xrandr extension not supported by the X server.", + cimgdisplay_instance); +#endif + + const unsigned int sx = screen_width(), sy = screen_height(); + if (sx==_width && sy==_height) return; + XSetWindowAttributes winattr; + winattr.override_redirect = 1; + _background_window = XCreateWindow(dpy,DefaultRootWindow(dpy),0,0,sx,sy,0,0, + InputOutput,CopyFromParent,CWOverrideRedirect,&winattr); + const cimg_ulong buf_size = (cimg_ulong)sx*sy*(cimg::X11_attr().nb_bits==8?1: + (cimg::X11_attr().nb_bits==16?2:4)); + void *background_data = std::malloc(buf_size); + std::memset(background_data,0,buf_size); + XImage *background_image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,(char*)background_data,sx,sy,8,0); + XEvent event; + XSelectInput(dpy,_background_window,StructureNotifyMask); + XMapRaised(dpy,_background_window); + do XWindowEvent(dpy,_background_window,StructureNotifyMask,&event); + while (event.type!=MapNotify); + GC gc = DefaultGC(dpy,DefaultScreen(dpy)); +#ifdef cimg_use_xshm + if (_shminfo) XShmPutImage(dpy,_background_window,gc,background_image,0,0,0,0,sx,sy,0); + else XPutImage(dpy,_background_window,gc,background_image,0,0,0,0,sx,sy); +#else + XPutImage(dpy,_background_window,gc,background_image,0,0,0,0,sx,sy); +#endif + XWindowAttributes attr; + XGetWindowAttributes(dpy,_background_window,&attr); + while (attr.map_state!=IsViewable) XSync(dpy,0); + XDestroyImage(background_image); + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + Display *const dpy = cimg::X11_attr().display; + XUngrabKeyboard(dpy,CurrentTime); +#ifdef cimg_use_xrandr + if (cimg::X11_attr().resolutions && cimg::X11_attr().curr_resolution) { + XRRScreenConfiguration *config = XRRGetScreenInfo(dpy,DefaultRootWindow(dpy)); + XRRSetScreenConfig(dpy,config,DefaultRootWindow(dpy),0,cimg::X11_attr().curr_rotation,CurrentTime); + XRRFreeScreenConfigInfo(config); + XSync(dpy,0); + cimg::X11_attr().curr_resolution = 0; + } +#endif + if (_background_window) XDestroyWindow(dpy,_background_window); + _background_window = 0; + _is_fullscreen = false; + } + + static int _assign_xshm(Display *dpy, XErrorEvent *error) { + cimg::unused(dpy,error); + cimg::X11_attr().is_shm_enabled = false; + return 0; + } + + void _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + cimg::mutex(14); + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous display window if existing + if (!is_empty()) assign(); + + // Open X11 display and retrieve graphical properties. + Display* &dpy = cimg::X11_attr().display; + if (!dpy) { + dpy = XOpenDisplay(0); + if (!dpy) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Failed to open X11 display.", + cimgdisplay_instance); + + cimg::X11_attr().nb_bits = DefaultDepth(dpy,DefaultScreen(dpy)); + if (cimg::X11_attr().nb_bits!=8 && cimg::X11_attr().nb_bits!=16 && + cimg::X11_attr().nb_bits!=24 && cimg::X11_attr().nb_bits!=32) + throw CImgDisplayException(_cimgdisplay_instance + "assign(): Invalid %u bits screen mode detected " + "(only 8, 16, 24 and 32 bits modes are managed).", + cimgdisplay_instance, + cimg::X11_attr().nb_bits); + XVisualInfo vtemplate; + vtemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy,DefaultScreen(dpy))); + int nb_visuals; + XVisualInfo *vinfo = XGetVisualInfo(dpy,VisualIDMask,&vtemplate,&nb_visuals); + if (vinfo && vinfo->red_maskblue_mask) cimg::X11_attr().is_blue_first = true; + cimg::X11_attr().byte_order = ImageByteOrder(dpy); + XFree(vinfo); + + cimg_lock_display(); + cimg::X11_attr().events_thread = new pthread_t; + pthread_create(cimg::X11_attr().events_thread,0,_events_thread,0); + } else cimg_lock_display(); + + // Set display variables. + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = 0; + _is_closed = closed_flag; + _title = tmp_title; + flush(); + + // Create X11 window (and LUT, if 8bits display) + if (_is_fullscreen) { + if (!_is_closed) _init_fullscreen(); + const unsigned int sx = screen_width(), sy = screen_height(); + XSetWindowAttributes winattr; + winattr.override_redirect = 1; + _window = XCreateWindow(dpy,DefaultRootWindow(dpy),(sx - _width)/2,(sy - _height)/2,_width,_height,0,0, + InputOutput,CopyFromParent,CWOverrideRedirect,&winattr); + } else + _window = XCreateSimpleWindow(dpy,DefaultRootWindow(dpy),0,0,_width,_height,0,0L,0L); + + XSelectInput(dpy,_window, + ExposureMask | StructureNotifyMask | ButtonPressMask | KeyPressMask | PointerMotionMask | + EnterWindowMask | LeaveWindowMask | ButtonReleaseMask | KeyReleaseMask); + + XStoreName(dpy,_window,_title?_title:" "); + if (cimg::X11_attr().nb_bits==8) { + _colormap = XCreateColormap(dpy,_window,DefaultVisual(dpy,DefaultScreen(dpy)),AllocAll); + _set_colormap(_colormap,3); + XSetWindowColormap(dpy,_window,_colormap); + } + + static const char *const _window_class = cimg_appname; + XClassHint *const window_class = XAllocClassHint(); + window_class->res_name = (char*)_window_class; + window_class->res_class = (char*)_window_class; + XSetClassHint(dpy,_window,window_class); + XFree(window_class); + + _window_width = _width; + _window_height = _height; + + // Create XImage +#ifdef cimg_use_xshm + _shminfo = 0; + if (XShmQueryExtension(dpy)) { + _shminfo = new XShmSegmentInfo; + _image = XShmCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,_shminfo,_width,_height); + if (!_image) { delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmid = shmget(IPC_PRIVATE,_image->bytes_per_line*_image->height,IPC_CREAT|0777); + if (_shminfo->shmid==-1) { XDestroyImage(_image); delete _shminfo; _shminfo = 0; } + else { + _shminfo->shmaddr = _image->data = (char*)(_data = shmat(_shminfo->shmid,0,0)); + if (_shminfo->shmaddr==(char*)-1) { + shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); delete _shminfo; _shminfo = 0; + } else { + _shminfo->readOnly = 0; + cimg::X11_attr().is_shm_enabled = true; + XErrorHandler oldXErrorHandler = XSetErrorHandler(_assign_xshm); + XShmAttach(dpy,_shminfo); + XSync(dpy,0); + XSetErrorHandler(oldXErrorHandler); + if (!cimg::X11_attr().is_shm_enabled) { + shmdt(_shminfo->shmaddr); shmctl(_shminfo->shmid,IPC_RMID,0); XDestroyImage(_image); + delete _shminfo; _shminfo = 0; + } + } + } + } + } + if (!_shminfo) +#endif + { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*(cimg::X11_attr().nb_bits==8?1: + (cimg::X11_attr().nb_bits==16?2:4)); + _data = std::malloc(buf_size); + _image = XCreateImage(dpy,DefaultVisual(dpy,DefaultScreen(dpy)),cimg::X11_attr().nb_bits, + ZPixmap,0,(char*)_data,_width,_height,8,0); + } + + _wm_window_atom = XInternAtom(dpy,"WM_DELETE_WINDOW",0); + _wm_protocol_atom = XInternAtom(dpy,"WM_PROTOCOLS",0); + XSetWMProtocols(dpy,_window,&_wm_window_atom,1); + + if (_is_fullscreen) XGrabKeyboard(dpy,_window,1,GrabModeAsync,GrabModeAsync,CurrentTime); + cimg::X11_attr().wins[cimg::X11_attr().nb_wins++]=this; + if (!_is_closed) _map_window(); else { _window_x = _window_y = cimg::type::min(); } + cimg_unlock_display(); + cimg::mutex(14,0); + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + + // Remove display window from event thread list. + unsigned int i; + for (i = 0; ishmaddr); + shmctl(_shminfo->shmid,IPC_RMID,0); + delete _shminfo; + _shminfo = 0; + } else +#endif + XDestroyImage(_image); + _data = 0; _image = 0; + if (cimg::X11_attr().nb_bits==8) XFreeColormap(dpy,_colormap); + _colormap = 0; + XSync(dpy,0); + + // Reset display variables. + delete[] _title; + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = 0; + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + + cimg_unlock_display(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + (cimg::X11_attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))* + (size_t)_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return render(nimg).paint(); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,(cimg::X11_attr().nb_bits==8?sizeof(unsigned char): + cimg::X11_attr().nb_bits==16?sizeof(unsigned short): + sizeof(unsigned int))*(size_t)_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign(nwidth,nheight); + Display *const dpy = cimg::X11_attr().display; + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*width()/100), + tmpdimy = (nheight>0)?nheight:(-nheight*height()/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + show(); + cimg_lock_display(); + if (_window_width!=dimx || _window_height!=dimy) { + XWindowAttributes attr; + for (unsigned int i = 0; i<10; ++i) { + XResizeWindow(dpy,_window,dimx,dimy); + XGetWindowAttributes(dpy,_window,&attr); + if (attr.width==(int)dimx && attr.height==(int)dimy) break; + cimg::wait(5); + } + } + if (_width!=dimx || _height!=dimy) switch (cimg::X11_attr().nb_bits) { + case 8 : { unsigned char pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + case 16 : { unsigned short pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } break; + default : { unsigned int pixel_type = 0; _resize(pixel_type,dimx,dimy,force_redraw); } + } + _window_width = _width = dimx; _window_height = _height = dimy; + cimg_unlock_display(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - _width)/2,(screen_height() - _height)/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height* + (cimg::X11_attr().nb_bits==8?1:(cimg::X11_attr().nb_bits==16?2:4)); + void *image_data = std::malloc(buf_size); + std::memcpy(image_data,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,image_data,buf_size); + std::free(image_data); + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + cimg_lock_display(); + if (_is_fullscreen) _init_fullscreen(); + _map_window(); + _is_closed = false; + cimg_unlock_display(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + if (_is_fullscreen) _desinit_fullscreen(); + XUnmapWindow(dpy,_window); + _window_x = _window_y = -1; + _is_closed = true; + cimg_unlock_display(); + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + if (_window_x!=posx || _window_y!=posy) { + show(); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XMoveWindow(dpy,_window,posx,posy); + _window_x = posx; _window_y = posy; + cimg_unlock_display(); + } + _is_moved = false; + return paint(); + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XUndefineCursor(dpy,_window); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + static const char pix_data[8] = { 0 }; + XColor col; + col.red = col.green = col.blue = 0; + Pixmap pix = XCreateBitmapFromData(dpy,_window,pix_data,8,8); + Cursor cur = XCreatePixmapCursor(dpy,pix,pix,&col,&col,0,0); + XFreePixmap(dpy,pix); + XDefineCursor(dpy,_window,cur); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed) return *this; + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XWarpPointer(dpy,0L,_window,0,0,0,0,posx,posy); + _mouse_x = posx; _mouse_y = posy; + _is_moved = false; + XSync(dpy,0); + cimg_unlock_display(); + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + Display *const dpy = cimg::X11_attr().display; + cimg_lock_display(); + XStoreName(dpy,_window,tmp); + cimg_unlock_display(); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(false); + } + + CImgDisplay& paint(const bool wait_expose=true) { + if (is_empty()) return *this; + cimg_lock_display(); + _paint(wait_expose); + cimg_unlock_display(); + return *this; + } + + template + CImgDisplay& render(const CImg& img, const bool flag8=false) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + if (cimg::X11_attr().nb_bits==8 && (img._width!=_width || img._height!=_height)) + return render(img.get_resize(_width,_height,1,-100,1)); + if (cimg::X11_attr().nb_bits==8 && !flag8 && img._spectrum==3) { + static const CImg::ucharT> default_colormap = CImg::ucharT>::default_LUT256(); + return render(img.get_index(default_colormap,1,false)); + } + + const T + *data1 = img._data, + *data2 = (img._spectrum>1)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>2)?img.data(0,0,0,2):data1; + + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + cimg_lock_display(); + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, no normalization + _set_colormap(_colormap,img._spectrum); + unsigned char + *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height], + *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + (*ptrd++) = (unsigned char)*(data1++); + break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, no normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (G>>1); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++), G = val>>2; + ptrd[0] = (G<<5) | (G>>1); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)*(data2++)>>2; + ptrd[0] = (G<<5) | ((unsigned char)*(data3++)>>3); + ptrd[1] = ((unsigned char)*(data1++)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, no normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data2++)<<16) | ((unsigned char)*(data1++)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | + (unsigned char)*(data3++); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = ((unsigned char)*(data3++)<<24) | ((unsigned char)*(data2++)<<16) | + ((unsigned char)*(data1++)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = 0; + ptrd[3] = 0; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = 0; + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)*(data1++); + ptrd[2] = (unsigned char)*(data2++); + ptrd[3] = (unsigned char)*(data3++); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)*(data3++); + ptrd[1] = (unsigned char)*(data2++); + ptrd[2] = (unsigned char)*(data1++); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { _min = (float)cimg::type::min(); _max = (float)cimg::type::max(); } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.0f); + switch (cimg::X11_attr().nb_bits) { + case 8 : { // 256 colormap, with normalization + _set_colormap(_colormap,img._spectrum); + unsigned char *const ndata = (img._width==_width && img._height==_height)?(unsigned char*)_data: + new unsigned char[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char R = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = R; + } break; + case 2 : for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + (*ptrd++) = (R&0xf0) | (G>>4); + } break; + default : + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6); + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned char*)_data,_width,_height); + delete[] ndata; + } + } break; + case 16 : { // 16 bits colors, with normalization + unsigned short *const ndata = (img._width==_width && img._height==_height)?(unsigned short*)_data: + new unsigned short[(size_t)img._width*img._height]; + unsigned char *ptrd = (unsigned char*)ndata; + const unsigned int M = 248; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (val&M) | (G>>3); + ptrd[1] = (G<<5) | (val>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm), G = val>>2; + ptrd[0] = (G<<5) | (val>>3); + ptrd[1] = (val&M) | (G>>3); + ptrd+=2; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd[1] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd+=2; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char G = (unsigned char)((*(data2++) - _min)*mm)>>2; + ptrd[0] = (G<<5) | ((unsigned char)((*(data3++) - _min)*mm)>>3); + ptrd[1] = ((unsigned char)((*(data1++) - _min)*mm)&M) | (G>>3); + ptrd+=2; + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned short*)_data,_width,_height); + delete[] ndata; + } + } break; + default : { // 24 bits colors, with normalization + unsigned int *const ndata = (img._width==_width && img._height==_height)?(unsigned int*)_data: + new unsigned int[(size_t)img._width*img._height]; + if (sizeof(int)==4) { // 32 bits int uses optimized version + unsigned int *ptrd = ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<16) | (val<<8) | val; + } + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (val<<24) | (val<<16) | (val<<8); + } + break; + case 2 : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + break; + default : + if (cimg::X11_attr().byte_order==cimg::endianness()) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data1++) - _min)*mm)<<16) | + ((unsigned char)((*(data2++) - _min)*mm)<<8) | + (unsigned char)((*(data3++) - _min)*mm); + else + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) + *(ptrd++) = + ((unsigned char)((*(data3++) - _min)*mm)<<24) | + ((unsigned char)((*(data2++) - _min)*mm)<<16) | + ((unsigned char)((*(data1++) - _min)*mm)<<8); + } + } else { + unsigned char *ptrd = (unsigned char*)ndata; + switch (img._spectrum) { + case 1 : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = 0; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = val; + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + ptrd[0] = val; + ptrd[1] = val; + ptrd[2] = val; + ptrd[3] = 0; + ptrd+=4; + } + break; + case 2 : + if (cimg::X11_attr().byte_order) cimg::swap(data1,data2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + break; + default : + if (cimg::X11_attr().byte_order) + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = 0; + ptrd[1] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[3] = (unsigned char)((*(data3++) - _min)*mm); + ptrd+=4; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ptrd[0] = (unsigned char)((*(data3++) - _min)*mm); + ptrd[1] = (unsigned char)((*(data2++) - _min)*mm); + ptrd[2] = (unsigned char)((*(data1++) - _min)*mm); + ptrd[3] = 0; + ptrd+=4; + } + } + } + if (ndata!=_data) { + _render_resize(ndata,img._width,img._height,(unsigned int*)_data,_width,_height); + delete[] ndata; + } + } + } + } + cimg_unlock_display(); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& 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=0 && _y0red_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 + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned char *ptrs = (unsigned char*)_data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + if (cimg::X11_attr().is_blue_first) cimg::swap(data1,data3); + switch (cimg::X11_attr().nb_bits) { + case 8 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = *(ptrs++); + *(data1++) = (T)(val&0xe0); + *(data2++) = (T)((val&0x1c)<<3); + *(data3++) = (T)(val<<6); + } + } break; + case 16 : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val0&0xf8); + *(data2++) = (T)((val0<<5) | ((val1&0xe0)>>5)); + *(data3++) = (T)(val1<<3); + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned short + val0 = ptrs[0], + val1 = ptrs[1]; + ptrs+=2; + *(data1++) = (T)(val1&0xf8); + *(data2++) = (T)((val1<<5) | ((val0&0xe0)>>5)); + *(data3++) = (T)(val0<<3); + } + } break; + default : { + if (cimg::X11_attr().byte_order) for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + ++ptrs; + *(data1++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data3++) = (T)ptrs[2]; + ptrs+=3; + } else for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + *(data3++) = (T)ptrs[0]; + *(data2++) = (T)ptrs[1]; + *(data1++) = (T)ptrs[2]; + ptrs+=3; + ++ptrs; + } + } + } + return *this; + } + + // Windows-based implementation. + //------------------------------- +#elif cimg_display==2 + + bool _is_mouse_tracked, _is_cursor_visible; + HANDLE _thread, _is_created, _mutex; + HWND _window, _background_window; + CLIENTCREATESTRUCT _ccs; + unsigned int *_data; + DEVMODE _curr_mode; + BITMAPINFO _bmi; + HDC _hdc; + + static int screen_width() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsWidth; + } + + static int screen_height() { + DEVMODE mode; + mode.dmSize = sizeof(DEVMODE); + mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&mode); + return (int)mode.dmPelsHeight; + } + + static void wait_all() { + WaitForSingleObject(cimg::Win32_attr().wait_event,INFINITE); + } + + static LRESULT APIENTRY _handle_events(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { +#ifdef _WIN64 + CImgDisplay *const disp = (CImgDisplay*)GetWindowLongPtr(window,GWLP_USERDATA); +#else + CImgDisplay *const disp = (CImgDisplay*)GetWindowLong(window,GWL_USERDATA); +#endif + MSG st_msg; + switch (msg) { + case WM_CLOSE : + disp->_mouse_x = disp->_mouse_y = -1; + disp->_window_x = disp->_window_y = 0; + disp->set_button().set_key(0).set_key(0,false)._is_closed = true; + ReleaseMutex(disp->_mutex); + ShowWindow(disp->_window,SW_HIDE); + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + return 0; + case WM_SIZE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam); + if (nw && nh && (nw!=disp->_width || nh!=disp->_height)) { + disp->_window_width = nw; + disp->_window_height = nh; + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_resized = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_MOVE : { + while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE)) {} + WaitForSingleObject(disp->_mutex,INFINITE); + const int nx = (int)(short)(LOWORD(lParam)), ny = (int)(short)(HIWORD(lParam)); + if (nx!=disp->_window_x || ny!=disp->_window_y) { + disp->_window_x = nx; + disp->_window_y = ny; + disp->_is_moved = disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + } + ReleaseMutex(disp->_mutex); + } break; + case WM_PAINT : + disp->paint(); + cimg::mutex(15); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE)>=0); + cimg::mutex(15,0); + break; + case WM_ERASEBKGND : + // return 0; + break; + case WM_KEYDOWN : + disp->set_key((unsigned int)wParam); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_KEYUP : + disp->set_key((unsigned int)wParam,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MOUSEMOVE : { + while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE)) {} + disp->_mouse_x = LOWORD(lParam); + disp->_mouse_y = HIWORD(lParam); +#if (_WIN32_WINNT>=0x0400) && !defined(NOTRACKMOUSEEVENT) + if (!disp->_is_mouse_tracked) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = disp->_window; + if (TrackMouseEvent(&tme)) disp->_is_mouse_tracked = true; + } +#endif + if (disp->_mouse_x<0 || disp->_mouse_y<0 || disp->_mouse_x>=disp->width() || disp->_mouse_y>=disp->height()) + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_event = true; + SetEvent(cimg::Win32_attr().wait_event); + cimg::mutex(15); + if (disp->_is_cursor_visible) while (ShowCursor(TRUE)<0); else while (ShowCursor(FALSE)>=0); + cimg::mutex(15,0); + } break; + case WM_MOUSELEAVE : { + disp->_mouse_x = disp->_mouse_y = -1; + disp->_is_mouse_tracked = false; + cimg::mutex(15); + while (ShowCursor(TRUE)<0) {} + cimg::mutex(15,0); + } break; + case WM_LBUTTONDOWN : + disp->set_button(1); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONDOWN : + disp->set_button(2); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONDOWN : + disp->set_button(3); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_LBUTTONUP : + disp->set_button(1,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_RBUTTONUP : + disp->set_button(2,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case WM_MBUTTONUP : + disp->set_button(3,false); + SetEvent(cimg::Win32_attr().wait_event); + break; + case 0x020A : // WM_MOUSEWHEEL: + disp->set_wheel((int)((short)HIWORD(wParam))/120); + SetEvent(cimg::Win32_attr().wait_event); + } + return DefWindowProc(window,msg,wParam,lParam); + } + + static DWORD WINAPI _events_thread(void* arg) { + CImgDisplay *const disp = (CImgDisplay*)(((void**)arg)[0]); + const char *const title = (const char*)(((void**)arg)[1]); + MSG msg; + delete[] (void**)arg; + disp->_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + disp->_bmi.bmiHeader.biWidth = disp->width(); + disp->_bmi.bmiHeader.biHeight = -disp->height(); + disp->_bmi.bmiHeader.biPlanes = 1; + disp->_bmi.bmiHeader.biBitCount = 32; + disp->_bmi.bmiHeader.biCompression = BI_RGB; + disp->_bmi.bmiHeader.biSizeImage = 0; + disp->_bmi.bmiHeader.biXPelsPerMeter = 1; + disp->_bmi.bmiHeader.biYPelsPerMeter = 1; + disp->_bmi.bmiHeader.biClrUsed = 0; + disp->_bmi.bmiHeader.biClrImportant = 0; + disp->_data = new unsigned int[(size_t)disp->_width*disp->_height]; + if (!disp->_is_fullscreen) { // Normal window + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)disp->_width - 1; rect.bottom = (LONG)disp->_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int + border1 = (int)((rect.right - rect.left + 1 - disp->_width)/2), + border2 = (int)(rect.bottom - rect.top + 1 - disp->_height - border1); + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + WS_OVERLAPPEDWINDOW | (disp->_is_closed?0:WS_VISIBLE), CW_USEDEFAULT,CW_USEDEFAULT, + disp->_width + 2*border1, disp->_height + border1 + border2, + 0,0,0,&(disp->_ccs)); + if (!disp->_is_closed) { + GetWindowRect(disp->_window,&rect); + disp->_window_x = rect.left + border1; + disp->_window_y = rect.top + border2; + } else disp->_window_x = disp->_window_y = 0; + } else { // Fullscreen window + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + disp->_window = CreateWindowA("MDICLIENT",title?title:" ", + WS_POPUP | (disp->_is_closed?0:WS_VISIBLE), + (sx - disp->_width)/2, + (sy - disp->_height)/2, + disp->_width,disp->_height,0,0,0,&(disp->_ccs)); + disp->_window_x = disp->_window_y = 0; + } + SetForegroundWindow(disp->_window); + disp->_hdc = GetDC(disp->_window); + disp->_window_width = disp->_width; + disp->_window_height = disp->_height; + disp->flush(); +#ifdef _WIN64 + SetWindowLongPtr(disp->_window,GWLP_USERDATA,(LONG_PTR)disp); + SetWindowLongPtr(disp->_window,GWLP_WNDPROC,(LONG_PTR)_handle_events); +#else + SetWindowLong(disp->_window,GWL_USERDATA,(LONG)disp); + SetWindowLong(disp->_window,GWL_WNDPROC,(LONG)_handle_events); +#endif + SetEvent(disp->_is_created); + while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg); + return 0; + } + + CImgDisplay& _update_window_pos() { + if (_is_closed) _window_x = _window_y = -1; + else { + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)_width - 1; rect.bottom = (LONG)_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int + border1 = (int)((rect.right - rect.left + 1 - _width)/2), + border2 = (int)(rect.bottom - rect.top + 1 - _height - border1); + GetWindowRect(_window,&rect); + _window_x = rect.left + border1; + _window_y = rect.top + border2; + } + return *this; + } + + void _init_fullscreen() { + _background_window = 0; + if (!_is_fullscreen || _is_closed) _curr_mode.dmSize = 0; + else { + DEVMODE mode; + unsigned int imode = 0, ibest = 0, bestbpp = 0, bw = ~0U, bh = ~0U; + for (mode.dmSize = sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(0,imode,&mode); ++imode) { + const unsigned int nw = mode.dmPelsWidth, nh = mode.dmPelsHeight; + if (nw>=_width && nh>=_height && mode.dmBitsPerPel>=bestbpp && nw<=bw && nh<=bh) { + bestbpp = mode.dmBitsPerPel; + ibest = imode; + bw = nw; bh = nh; + } + } + if (bestbpp) { + _curr_mode.dmSize = sizeof(DEVMODE); _curr_mode.dmDriverExtra = 0; + EnumDisplaySettings(0,ENUM_CURRENT_SETTINGS,&_curr_mode); + EnumDisplaySettings(0,ibest,&mode); + ChangeDisplaySettings(&mode,0); + } else _curr_mode.dmSize = 0; + + const unsigned int + sx = (unsigned int)screen_width(), + sy = (unsigned int)screen_height(); + if (sx!=_width || sy!=_height) { + CLIENTCREATESTRUCT background_ccs; + _background_window = CreateWindowA("MDICLIENT","",WS_POPUP | WS_VISIBLE, 0,0,sx,sy,0,0,0,&background_ccs); + SetForegroundWindow(_background_window); + } + } + } + + void _desinit_fullscreen() { + if (!_is_fullscreen) return; + if (_background_window) DestroyWindow(_background_window); + _background_window = 0; + if (_curr_mode.dmSize) ChangeDisplaySettings(&_curr_mode,0); + _is_fullscreen = false; + } + + CImgDisplay& _assign(const unsigned int dimw, const unsigned int dimh, const char *const ptitle=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + + // Allocate space for window title + const char *const nptitle = ptitle?ptitle:""; + const unsigned int s = (unsigned int)std::strlen(nptitle) + 1; + char *const tmp_title = s?new char[s]:0; + if (s) std::memcpy(tmp_title,nptitle,s*sizeof(char)); + + // Destroy previous window if existing + if (!is_empty()) assign(); + + // Set display variables + _width = std::min(dimw,(unsigned int)screen_width()); + _height = std::min(dimh,(unsigned int)screen_height()); + _normalization = normalization_type<4?normalization_type:3; + _is_fullscreen = fullscreen_flag; + _window_x = _window_y = 0; + _is_closed = closed_flag; + _is_cursor_visible = true; + _is_mouse_tracked = false; + _title = tmp_title; + flush(); + if (_is_fullscreen) _init_fullscreen(); + + // Create event thread + void *const arg = (void*)(new void*[2]); + ((void**)arg)[0] = (void*)this; + ((void**)arg)[1] = (void*)_title; + _mutex = CreateMutex(0,FALSE,0); + _is_created = CreateEvent(0,FALSE,FALSE,0); + _thread = CreateThread(0,0,_events_thread,arg,0,0); + WaitForSingleObject(_is_created,INFINITE); + return *this; + } + + CImgDisplay& assign() { + if (is_empty()) return flush(); + DestroyWindow(_window); + TerminateThread(_thread,0); + delete[] _data; + delete[] _title; + _data = 0; + _title = 0; + if (_is_fullscreen) _desinit_fullscreen(); + _width = _height = _normalization = _window_width = _window_height = 0; + _window_x = _window_y = 0; + _is_fullscreen = false; + _is_closed = true; + _min = _max = 0; + _title = 0; + flush(); + return *this; + } + + CImgDisplay& assign(const unsigned int dimw, const unsigned int dimh, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!dimw || !dimh) return assign(); + _assign(dimw,dimh,title,normalization_type,fullscreen_flag,closed_flag); + _min = _max = 0; + std::memset(_data,0,sizeof(unsigned int)*_width*_height); + return paint(); + } + + template + CImgDisplay& assign(const CImg& img, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!img) return assign(); + CImg tmp; + const CImg& nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + template + CImgDisplay& assign(const CImgList& list, const char *const title=0, + const unsigned int normalization_type=3, + const bool fullscreen_flag=false, const bool closed_flag=false) { + if (!list) return assign(); + CImg tmp; + const CImg img = list>'x', &nimg = (img._depth==1)?img:(tmp=img.get_projections2d((img._width - 1)/2, + (img._height - 1)/2, + (img._depth - 1)/2)); + _assign(nimg._width,nimg._height,title,normalization_type,fullscreen_flag,closed_flag); + if (_normalization==2) _min = (float)nimg.min_max(_max); + return display(nimg); + } + + CImgDisplay& assign(const CImgDisplay& disp) { + if (!disp) return assign(); + _assign(disp._width,disp._height,disp._title,disp._normalization,disp._is_fullscreen,disp._is_closed); + std::memcpy(_data,disp._data,sizeof(unsigned int)*_width*_height); + return paint(); + } + + CImgDisplay& resize(const int nwidth, const int nheight, const bool force_redraw=true) { + if (!nwidth || !nheight || (is_empty() && (nwidth<0 || nheight<0))) return assign(); + if (is_empty()) return assign(nwidth,nheight); + const unsigned int + tmpdimx = (nwidth>0)?nwidth:(-nwidth*_width/100), + tmpdimy = (nheight>0)?nheight:(-nheight*_height/100), + dimx = tmpdimx?tmpdimx:1, + dimy = tmpdimy?tmpdimy:1; + if (_width!=dimx || _height!=dimy || _window_width!=dimx || _window_height!=dimy) { + if (_window_width!=dimx || _window_height!=dimy) { + RECT rect; rect.left = rect.top = 0; rect.right = (LONG)dimx - 1; rect.bottom = (LONG)dimy - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int cwidth = rect.right - rect.left + 1, cheight = rect.bottom - rect.top + 1; + SetWindowPos(_window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS); + } + if (_width!=dimx || _height!=dimy) { + unsigned int *const ndata = new unsigned int[dimx*dimy]; + if (force_redraw) _render_resize(_data,_width,_height,ndata,dimx,dimy); + else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy); + delete[] _data; + _data = ndata; + _bmi.bmiHeader.biWidth = (LONG)dimx; + _bmi.bmiHeader.biHeight = -(int)dimy; + _width = dimx; + _height = dimy; + } + _window_width = dimx; _window_height = dimy; + show(); + } + _is_resized = false; + if (_is_fullscreen) move((screen_width() - width())/2,(screen_height() - height())/2); + if (force_redraw) return paint(); + return *this; + } + + CImgDisplay& toggle_fullscreen(const bool force_redraw=true) { + if (is_empty()) return *this; + if (force_redraw) { + const cimg_ulong buf_size = (cimg_ulong)_width*_height*4; + void *odata = std::malloc(buf_size); + if (odata) { + std::memcpy(odata,_data,buf_size); + assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + std::memcpy(_data,odata,buf_size); + std::free(odata); + } + return paint(); + } + return assign(_width,_height,_title,_normalization,!_is_fullscreen,false); + } + + CImgDisplay& show() { + if (is_empty() || !_is_closed) return *this; + _is_closed = false; + if (_is_fullscreen) _init_fullscreen(); + ShowWindow(_window,SW_SHOW); + _update_window_pos(); + return paint(); + } + + CImgDisplay& close() { + if (is_empty() || _is_closed) return *this; + _is_closed = true; + if (_is_fullscreen) _desinit_fullscreen(); + ShowWindow(_window,SW_HIDE); + _window_x = _window_y = 0; + return *this; + } + + CImgDisplay& move(const int posx, const int posy) { + if (is_empty()) return *this; + if (_window_x!=posx || _window_y!=posy) { + if (!_is_fullscreen) { + RECT rect; + rect.left = rect.top = 0; rect.right = (LONG)_window_width - 1; rect.bottom = (LONG)_window_height - 1; + AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false); + const int + border1 = (int)((rect.right - rect.left + 1 -_width)/2), + border2 = (int)(rect.bottom - rect.top + 1 - _height - border1); + SetWindowPos(_window,0,posx - border1,posy - border2,0,0,SWP_NOSIZE | SWP_NOZORDER); + } else SetWindowPos(_window,0,posx,posy,0,0,SWP_NOSIZE | SWP_NOZORDER); + _window_x = posx; + _window_y = posy; + show(); + } + _is_moved = false; + return *this; + } + + CImgDisplay& show_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = true; + return *this; + } + + CImgDisplay& hide_mouse() { + if (is_empty()) return *this; + _is_cursor_visible = false; + return *this; + } + + CImgDisplay& set_mouse(const int posx, const int posy) { + if (is_empty() || _is_closed || posx<0 || posy<0) return *this; + _update_window_pos(); + const int res = (int)SetCursorPos(_window_x + posx,_window_y + posy); + if (res) { _mouse_x = posx; _mouse_y = posy; } + return *this; + } + + CImgDisplay& set_title(const char *const format, ...) { + if (is_empty()) return *this; + char *const tmp = new char[1024]; + va_list ap; + va_start(ap, format); + cimg_vsnprintf(tmp,1024,format,ap); + va_end(ap); + if (!std::strcmp(_title,tmp)) { delete[] tmp; return *this; } + delete[] _title; + const unsigned int s = (unsigned int)std::strlen(tmp) + 1; + _title = new char[s]; + std::memcpy(_title,tmp,s*sizeof(char)); + SetWindowTextA(_window, tmp); + delete[] tmp; + return *this; + } + + template + CImgDisplay& display(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "display(): Empty specified image.", + cimgdisplay_instance); + if (is_empty()) return assign(img); + return render(img).paint(); + } + + CImgDisplay& paint() { + if (_is_closed) return *this; + WaitForSingleObject(_mutex,INFINITE); + SetDIBitsToDevice(_hdc,0,0,_width,_height,0,0,0,_height,_data,&_bmi,DIB_RGB_COLORS); + ReleaseMutex(_mutex); + return *this; + } + + template + CImgDisplay& render(const CImg& img) { + if (!img) + throw CImgArgumentException(_cimgdisplay_instance + "render(): Empty specified image.", + cimgdisplay_instance); + + if (is_empty()) return *this; + if (img._depth!=1) return render(img.get_projections2d((img._width - 1)/2,(img._height - 1)/2, + (img._depth - 1)/2)); + + const T + *data1 = img._data, + *data2 = (img._spectrum>=2)?img.data(0,0,0,1):data1, + *data3 = (img._spectrum>=3)?img.data(0,0,0,2):data1; + + WaitForSingleObject(_mutex,INFINITE); + unsigned int + *const ndata = (img._width==_width && img._height==_height)?_data: + new unsigned int[(size_t)img._width*img._height], + *ptrd = ndata; + + if (!_normalization || (_normalization==3 && cimg::type::string()==cimg::type::string())) { + _min = _max = 0; + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)*(data1++); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)*(data1++), + G = (unsigned char)*(data2++), + B = (unsigned char)*(data3++); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } else { + if (_normalization==3) { + if (cimg::type::is_float()) _min = (float)img.min_max(_max); + else { _min = (float)cimg::type::min(); _max = (float)cimg::type::max(); } + } else if ((_min>_max) || _normalization==1) _min = (float)img.min_max(_max); + const float delta = _max - _min, mm = 255/(delta?delta:1.0f); + switch (img._spectrum) { + case 1 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char val = (unsigned char)((*(data1++) - _min)*mm); + *(ptrd++) = (unsigned int)((val<<16) | (val<<8) | val); + } + } break; + case 2 : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8)); + } + } break; + default : { + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned char + R = (unsigned char)((*(data1++) - _min)*mm), + G = (unsigned char)((*(data2++) - _min)*mm), + B = (unsigned char)((*(data3++) - _min)*mm); + *(ptrd++) = (unsigned int)((R<<16) | (G<<8) | B); + } + } + } + } + if (ndata!=_data) { _render_resize(ndata,img._width,img._height,_data,_width,_height); delete[] ndata; } + ReleaseMutex(_mutex); + return *this; + } + + template + static void screenshot(const int x0, const int y0, const int x1, const int y1, CImg& 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=0 && _y0 + const CImgDisplay& snapshot(CImg& img) const { + if (is_empty()) { img.assign(); return *this; } + const unsigned int *ptrs = _data; + img.assign(_width,_height,1,3); + T + *data1 = img.data(0,0,0,0), + *data2 = img.data(0,0,0,1), + *data3 = img.data(0,0,0,2); + for (cimg_ulong xy = (cimg_ulong)img._width*img._height; xy>0; --xy) { + const unsigned int val = *(ptrs++); + *(data1++) = (T)(unsigned char)(val>>16); + *(data2++) = (T)(unsigned char)((val>>8)&0xFF); + *(data3++) = (T)(unsigned char)(val&0xFF); + } + return *this; + } +#endif + + //@} + }; + + /* + #-------------------------------------- + # + # + # + # Definition of the CImg structure + # + # + # + #-------------------------------------- + */ + + //! Class representing an image (up to 4 dimensions wide), each pixel being of type \c T. + /** + This is the main class of the %CImg Library. It declares and constructs + an image, allows access to its pixel values, and is able to perform various image operations. + + \par Image representation + + A %CImg image is defined as an instance of the container \c CImg, which contains a regular grid of pixels, + each pixel value being of type \c T. The image grid can have up to 4 dimensions: width, height, depth + and number of channels. + Usually, the three first dimensions are used to describe spatial coordinates (x,y,z), + while the number of channels is rather used as a vector-valued dimension + (it may describe the R,G,B color channels for instance). + If you need a fifth dimension, you can use image lists \c CImgList rather than simple images \c CImg. + + Thus, the \c CImg class is able to represent volumetric images of vector-valued pixels, + as well as images with less dimensions (1d scalar signal, 2d color images, ...). + Most member functions of the class CImg<\c T> are designed to handle this maximum case of (3+1) dimensions. + + Concerning the pixel value type \c T: + fully supported template types are the basic C++ types: unsigned char, char, short, unsigned int, int, + unsigned long, long, float, double, ... . + Typically, fast image display can be done using CImg images, + while complex image processing algorithms may be rather coded using CImg or CImg + images that have floating-point pixel values. The default value for the template T is \c float. + Using your own template types may be possible. However, you will certainly have to define the complete set + of arithmetic and logical operators for your class. + + \par Image structure + + The \c CImg structure contains \e six fields: + - \c _width defines the number of \a columns of the image (size along the X-axis). + - \c _height defines the number of \a rows of the image (size along the Y-axis). + - \c _depth defines the number of \a slices of the image (size along the Z-axis). + - \c _spectrum defines the number of \a channels of the image (size along the C-axis). + - \c _data defines a \a pointer to the \a pixel \a data (of type \c T). + - \c _is_shared is a boolean that tells if the memory buffer \c data is shared with + another image. + + You can access these fields publicly although it is recommended to use the dedicated functions + width(), height(), depth(), spectrum() and ptr() to do so. + Image dimensions are not limited to a specific range (as long as you got enough available memory). + A value of \e 1 usually means that the corresponding dimension is \a flat. + If one of the dimensions is \e 0, or if the data pointer is null, the image is considered as \e empty. + Empty images should not contain any pixel data and thus, will not be processed by CImg member functions + (a CImgInstanceException will be thrown instead). + Pixel data are stored in memory, in a non interlaced mode (See \ref cimg_storage). + + \par Image declaration and construction + + Declaring an image can be done by using one of the several available constructors. + Here is a list of the most used: + + - Construct images from arbitrary dimensions: + - CImg img; declares an empty image. + - CImg img(128,128); declares a 128x128 greyscale image with + \c unsigned \c char pixel values. + - CImg img(3,3); declares a 3x3 matrix with \c double coefficients. + - CImg img(256,256,1,3); declares a 256x256x1x3 (color) image + (colors are stored as an image with three channels). + - CImg img(128,128,128); declares a 128x128x128 volumetric and greyscale image + (with \c double pixel values). + - CImg<> img(128,128,128,3); declares a 128x128x128 volumetric color image + (with \c float pixels, which is the default value of the template parameter \c T). + - \b Note: images pixels are not automatically initialized to 0. You may use the function \c fill() to + do it, or use the specific constructor taking 5 parameters like this: + CImg<> img(128,128,128,3,0); declares a 128x128x128 volumetric color image with all pixel values to 0. + + - Construct images from filenames: + - CImg img("image.jpg"); reads a JPEG color image from the file "image.jpg". + - CImg img("analyze.hdr"); reads a volumetric image (ANALYZE7.5 format) from the + file "analyze.hdr". + - \b Note: You need to install ImageMagick + to be able to read common compressed image formats (JPG,PNG, ...) (See \ref cimg_files_io). + + - Construct images from C-style arrays: + - CImg img(data_buffer,256,256); constructs a 256x256 greyscale image from a \c int* buffer + \c data_buffer (of size 256x256=65536). + - CImg img(data_buffer,256,256,1,3); constructs a 256x256 color image + from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others). + + The complete list of constructors can be found here. + + \par Most useful functions + + The \c CImg class contains a lot of functions that operates on images. + Some of the most useful are: + + - operator()(): Read or write pixel values. + - display(): displays the image in a new window. + **/ + template + struct CImg { + + unsigned int _width, _height, _depth, _spectrum; + bool _is_shared; + T *_data; + + //! Simple iterator type, to loop through each pixel value of an image instance. + /** + \note + - The \c CImg::iterator type is defined to be a T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + CImg img("reference.jpg"); // Load image from file. + for (CImg::iterator it = img.begin(), it::const_iterator type is defined to be a \c const \c T*. + - You will seldom have to use iterators in %CImg, most classical operations + being achieved (often in a faster way) using methods of \c CImg. + \par Example + \code + const CImg img("reference.jpg"); // Load image from file. + float sum = 0; + for (CImg::iterator it = img.begin(), it::value_type type of a \c CImg is defined to be a \c T. + - \c CImg::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimg_plugin +#include cimg_plugin +#endif +#ifdef cimg_plugin1 +#include cimg_plugin1 +#endif +#ifdef cimg_plugin2 +#include cimg_plugin2 +#endif +#ifdef cimg_plugin3 +#include cimg_plugin3 +#endif +#ifdef cimg_plugin4 +#include cimg_plugin4 +#endif +#ifdef cimg_plugin5 +#include cimg_plugin5 +#endif +#ifdef cimg_plugin6 +#include cimg_plugin6 +#endif +#ifdef cimg_plugin7 +#include cimg_plugin7 +#endif +#ifdef cimg_plugin8 +#include cimg_plugin8 +#endif + + //@} + //--------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //--------------------------------------------------------- + + //! Destroy image. + /** + \note + - The pixel buffer data() is deallocated if necessary, e.g. for non-empty and non-shared image instances. + - Destroying an empty or shared image does nothing actually. + \warning + - When destroying a non-shared image, make sure that you will \e not operate on a remaining shared image + that shares its buffer with the destroyed instance, in order to avoid further invalid memory access + (to a deallocated buffer). + **/ + ~CImg() { + if (!_is_shared) delete[] _data; + } + + //! Construct empty image. + /** + \note + - An empty image has no pixel data and all of its dimensions width(), height(), depth(), spectrum() + are set to \c 0, as well as its pixel buffer pointer data(). + - An empty image may be re-assigned afterwards, e.g. with the family of + assign(unsigned int,unsigned int,unsigned int,unsigned int) methods, + or by operator=(const CImg&). In all cases, the type of pixels stays \c T. + - An empty image is never shared. + \par Example + \code + CImg img1, img2; // Construct two empty images. + img1.assign(256,256,1,3); // Re-assign 'img1' to be a 256x256x1x3 (color) image. + img2 = img1.get_rand(0,255); // Re-assign 'img2' to be a random-valued version of 'img1'. + img2.assign(); // Re-assign 'img2' to be an empty image again. + \endcode + **/ + CImg():_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) {} + + //! Construct image with specified size. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \note + - It is able to create only \e non-shared images, and allocates thus a pixel buffer data() + for each constructed image instance. + - Setting one dimension \c size_x,\c size_y,\c size_z or \c size_c to \c 0 leads to the construction of + an \e empty image. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values during construction (e.g. with \c 0), use constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) instead. + \par Example + \code + CImg img1(256,256,1,3); // Construct a 256x256x1x3 (color) image, filled with garbage values. + CImg img2(256,256,1,3,0); // Construct a 256x256x1x3 (color) image, filled with value '0'. + \endcode + **/ + explicit CImg(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1): + _is_shared(false) { + size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values. + /** + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value Initialization value. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), + but it also fills the pixel buffer with the specified \c value. + \warning + - It cannot be used to construct a vector-valued image and initialize it with \e vector-valued pixels + (e.g. RGB vector, for color images). + For this task, you may use fillC() after construction. + **/ + CImg(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value): + _is_shared(false) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(value); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified sequence of integers \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be an \e integer). + \param value1 Second value of the initialization sequence (must be an \e integer). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \warning + - You must specify \e exactly \c size_x*\c size_y*\c size_z*\c size_c integers in the initialization sequence. + Otherwise, the constructor may crash or fill your image pixels with garbage. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image. + 0,255,0,255, // Set the 4 values for the red component. + 0,0,255,255, // Set the 4 values for the green component. + 64,64,64,64); // Set the 4 values for the blue component. + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _CImg_stdarg(img,a0,a1,N,t) { \ + size_t _siz = (size_t)N; \ + if (_siz--) { \ + va_list ap; \ + va_start(ap,a1); \ + T *ptrd = (img)._data; \ + *(ptrd++) = (T)a0; \ + if (_siz--) { \ + *(ptrd++) = (T)a1; \ + for ( ; _siz; --_siz) *(ptrd++) = (T)va_arg(ap,t); \ + } \ + va_end(ap); \ + } \ + } + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,int); + } + +#if cimg_use_cpp11==1 + //! Construct image with specified size and initialize pixel values from an initializer list of integers. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... } + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param { value0, value1, ... } Initialization list + \param repeat_values Tells if the value filling process is repeated over the image. + + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img(2,2,1,3, // Construct a 2x2 color (RGB) image. + { 0,255,0,255, // Set the 4 values for the red component. + 0,0,255,255, // Set the 4 values for the green component. + 64,64,64,64 }); // Set the 4 values for the blue component. + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { +#define _cimg_constructor_cpp11(repeat_values) \ + auto it = values.begin(); \ + size_t siz = size(); \ + if (repeat_values) for (T *ptrd = _data; siz--; ) { \ + *(ptrd++) = (T)(*(it++)); if (it==values.end()) it = values.begin(); } \ + else { siz = std::min(siz,values.size()); for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); } + assign(size_x,size_y,size_z,size_c); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, const unsigned int size_y, + std::initializer_list values, + const bool repeat_values=true): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y); + _cimg_constructor_cpp11(repeat_values); + } + + template + CImg(const unsigned int size_x, + std::initializer_list values, + const bool repeat_values=true):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x); + _cimg_constructor_cpp11(repeat_values); + } + + //! Construct single channel 1D image with pixel values and width obtained from an initializer list of integers. + /** + Construct a new image instance of size \c width x \c 1 x \c 1 x \c 1, + with pixels of type \c T, and initialize pixel + values from the specified initializer list of integers { \c value0,\c value1,\c ... }. Image width is + given by the size of the initializer list. + \param { value0, value1, ... } Initialization list + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int) with height=1, depth=1, and spectrum=1, + but it also fills the pixel buffer with a sequence of specified integer values. + \par Example + \code + const CImg img = {10,20,30,20,10 }; // Construct a 5x1 image with one channel, and set its pixel values. + img.resize(150,150).display(); + \endcode + \image html ref_constructor1.jpg + **/ + template + CImg(const std::initializer_list values): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(values.size(),1,1,1); + auto it = values.begin(); + unsigned int siz = _width; + for (T *ptrd = _data; siz--; ) *(ptrd++) = (T)(*(it++)); + } + + template + CImg & operator=(std::initializer_list values) { + _cimg_constructor_cpp11(siz>values.size()); + return *this; + } +#endif + + //! Construct image with specified size and initialize pixel values from a sequence of doubles. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initialize pixel values from the specified sequence of doubles \c value0,\c value1,\c ... + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param value0 First value of the initialization sequence (must be a \e double). + \param value1 Second value of the initialization sequence (must be a \e double). + \param ... + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...), but + takes a sequence of double values instead of integers. + \warning + - You must specify \e exactly \c dx*\c dy*\c dz*\c dc doubles in the initialization sequence. + Otherwise, the constructor may crash or fill your image with garbage. + For instance, the code below will probably crash on most platforms: + \code + const CImg img(2,2,1,1, 0.5,0.5,255,255); // FAIL: The two last arguments are 'int', not 'double'! + \endcode + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,double); + } + + //! Construct image with specified size and initialize pixel values from a value string. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified string \c values. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param values Value string describing the way pixel values are set. + \param repeat_values Tells if the value filling process is repeated over the image. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it also fills + the pixel buffer with values described in the value string \c values. + - Value string \c values may describe two different filling processes: + - Either \c values is a sequences of values assigned to the image pixels, as in "1,2,3,7,8,2". + In this case, set \c repeat_values to \c true to periodically fill the image with the value sequence. + - Either, \c values is a formula, as in "cos(x/10)*sin(y/20)". + In this case, parameter \c repeat_values is pointless. + - For both cases, specifying \c repeat_values is mandatory. + It disambiguates the possible overloading of constructor + CImg(unsigned int,unsigned int,unsigned int,unsigned int,T) with \c T being a const char*. + - A \c CImgArgumentException is thrown when an invalid value string \c values is specified. + \par Example + \code + const CImg img1(129,129,1,3,"0,64,128,192,255",true), // Construct image filled from a value sequence. + img2(129,129,1,3,"if(c==0,255*abs(cos(x/10)),1.8*y)",false); // Construct image filled from a formula. + (img1,img2).display(); + \endcode + \image html ref_constructor2.jpg + **/ + CImg(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values):_is_shared(false) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + fill(values,repeat_values); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer. + /** + Construct a new image instance of size \c size_x x \c size_y x \c size_z x \c size_c, with pixels of type \c T, + and initializes pixel values from the specified \c t* memory buffer. + \param values Pointer to the input memory buffer. + \param size_x Image width(). + \param size_y Image height(). + \param size_z Image depth(). + \param size_c Image spectrum() (number of channels). + \param is_shared Tells if input memory buffer must be shared by the current instance. + \note + - If \c is_shared is \c false, the image instance allocates its own pixel buffer, + and values from the specified input buffer are copied to the instance buffer. + If buffer types \c T and \c t are different, a regular static cast is performed during buffer copy. + - Otherwise, the image instance does \e not allocate a new buffer, and uses the input memory buffer as its + own pixel buffer. This case requires that types \c T and \c t are the same. Later, destroying such a shared + image will not deallocate the pixel buffer, this task being obviously charged to the initial buffer allocator. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. when requested size is too big for available memory). + \warning + - You must take care when operating on a shared image, since it may have an invalid pixel buffer pointer data() + (e.g. already deallocated). + \par Example + \code + unsigned char tab[256*256] = { 0 }; + CImg img1(tab,256,256,1,1,false), // Construct new non-shared image from buffer 'tab'. + img2(tab,256,256,1,1,true); // Construct new shared-image from buffer 'tab'. + tab[1024] = 255; // Here, 'img2' is indirectly modified, but not 'img1'. + \endcode + **/ + template + CImg(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a (%u,%u,%u,%u) shared instance " + "from a (%s*) buffer (pixel types are different).", + cimg_instance, + size_x,size_y,size_z,size_c,CImg::pixel_type()); + } + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + + } + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, const bool is_shared=false) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (values && siz) { + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = is_shared; + if (_is_shared) _data = const_cast(values); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy(_data,values,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image from reading an image file. + /** + Construct a new image instance with pixels of type \c T, and initialize pixel values with the data read from + an image file. + \param filename Filename, as a C-string. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it reads the image + dimensions and pixel values from the specified image file. + - The recognition of the image file format by %CImg higly depends on the tools installed on your system + and on the external libraries you used to link your code against. + - Considered pixel type \c T should better fit the file format specification, or data loss may occur during + file load (e.g. constructing a \c CImg from a float-valued image file). + - A \c CImgIOException is thrown when the specified \c filename cannot be read, or if the file format is not + recognized. + \par Example + \code + const CImg img("reference.jpg"); + img.display(); + \endcode + \image html ref_image.jpg + **/ + explicit CImg(const char *const filename):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(filename); + } + + //! Construct image copy. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance. + \param img Input image to copy. + \note + - Constructed copy has the same size width() x height() x depth() x spectrum() and pixel values as the + input image \c img. + - If input image \c img is \e shared and if types \c T and \c t are the same, the constructed copy is also + \e shared, and shares its pixel buffer with \c img. + Modifying a pixel value in the constructed copy will thus also modifies it in the input image \c img. + This behavior is needful to allow functions to return shared images. + - Otherwise, the constructed copy allocates its own pixel buffer, and copies pixel values from the input + image \c img into its buffer. The copied pixel values may be eventually statically casted if types \c T and + \c t are different. + - Constructing a copy from an image \c img when types \c t and \c T are the same is significantly faster than + with different types. + - A \c CImgInstanceException is thrown when the pixel buffer cannot be allocated + (e.g. not enough available memory). + **/ + template + CImg(const CImg& img):_is_shared(false) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Construct image copy \specialization. + CImg(const CImg& img) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = img._is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Advanced copy constructor. + /** + Construct a new image instance with pixels of type \c T, as a copy of an existing \c CImg instance, + while forcing the shared state of the constructed copy. + \param img Input image to copy. + \param is_shared Tells about the shared state of the constructed copy. + \note + - Similar to CImg(const CImg&), except that it allows to decide the shared state of + the constructed image, which does not depend anymore on the shared state of the input image \c img: + - If \c is_shared is \c true, the constructed copy will share its pixel buffer with the input image \c img. + For that case, the pixel types \c T and \c t \e must be the same. + - If \c is_shared is \c false, the constructed copy will allocate its own pixel buffer, whether the input + image \c img is shared or not. + - A \c CImgArgumentException is thrown when a shared copy is requested with different pixel types \c T and \c t. + **/ + template + CImg(const CImg& img, const bool is_shared):_is_shared(false) { + if (is_shared) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgArgumentException(_cimg_instance + "CImg(): Invalid construction request of a shared instance from a " + "CImg<%s> image (%u,%u,%u,%u,%p) (pixel types are different).", + cimg_instance, + CImg::pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data); + } + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + const t *ptrs = img._data; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + } else { _width = _height = _depth = _spectrum = 0; _data = 0; } + } + + //! Advanced copy constructor \specialization. + CImg(const CImg& img, const bool is_shared) { + const size_t siz = (size_t)img.size(); + if (img._data && siz) { + _width = img._width; _height = img._height; _depth = img._depth; _spectrum = img._spectrum; + _is_shared = is_shared; + if (_is_shared) _data = const_cast(img._data); + else { + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "CImg(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*img._width*img._height*img._depth*img._spectrum), + img._width,img._height,img._depth,img._spectrum); + } + std::memcpy(_data,img._data,siz*sizeof(T)); + } + } else { _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; } + } + + //! Construct image with dimensions borrowed from another image. + /** + Construct a new image instance with pixels of type \c T, and size get from some dimensions of an existing + \c CImg instance. + \param img Input image from which dimensions are borrowed. + \param dimensions C-string describing the image size along the X,Y,Z and C-dimensions. + \note + - Similar to CImg(unsigned int,unsigned int,unsigned int,unsigned int), but it takes the image dimensions + (\e not its pixel values) from an existing \c CImg instance. + - The allocated pixel buffer is \e not filled with a default value, and is likely to contain garbage values. + In order to initialize pixel values (e.g. with \c 0), use constructor CImg(const CImg&,const char*,T) + instead. + \par Example + \code + const CImg img1(256,128,1,3), // 'img1' is a 256x128x1x3 image. + img2(img1,"xyzc"), // 'img2' is a 256x128x1x3 image. + img3(img1,"y,x,z,c"), // 'img3' is a 128x256x1x3 image. + img4(img1,"c,x,y,3",0), // 'img4' is a 3x128x256x3 image (with pixels initialized to '0'). + \endcode + **/ + template + CImg(const CImg& img, const char *const dimensions): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values. + /** + Construct a new image instance with pixels of type \c T, and size get from the dimensions of an existing + \c CImg instance, and set all pixel values to specified \c value. + \param img Input image from which dimensions are borrowed. + \param dimensions String describing the image size along the X,Y,Z and V-dimensions. + \param value Value used for initialization. + \note + - Similar to CImg(const CImg&,const char*), but it also fills the pixel buffer with the specified \c value. + **/ + template + CImg(const CImg& img, const char *const dimensions, const T& value): + _width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + assign(img,dimensions).fill(value); + } + + //! Construct image from a display window. + /** + Construct a new image instance with pixels of type \c T, as a snapshot of an existing \c CImgDisplay instance. + \param disp Input display window. + \note + - The width() and height() of the constructed image instance are the same as the specified \c CImgDisplay. + - The depth() and spectrum() of the constructed image instance are respectively set to \c 1 and \c 3 + (i.e. a 2d color image). + - The image pixels are read as 8-bits RGB values. + **/ + explicit CImg(const CImgDisplay &disp):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + disp.snapshot(*this); + } + + // Constructor and assignment operator for rvalue references (c++11). + // This avoids an additional image copy for methods returning new images. Can save RAM for big images ! +#if cimg_use_cpp11==1 + CImg(CImg&& img):_width(0),_height(0),_depth(0),_spectrum(0),_is_shared(false),_data(0) { + swap(img); + } + CImg& operator=(CImg&& img) { + if (_is_shared) return assign(img); + return img.swap(*this); + } +#endif + + //! Construct empty image \inplace. + /** + In-place version of the default constructor CImg(). It simply resets the instance to an empty image. + **/ + CImg& assign() { + if (!_is_shared) delete[] _data; + _width = _height = _depth = _spectrum = 0; _is_shared = false; _data = 0; + return *this; + } + + //! Construct image with specified size \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (!siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (siz!=curr_siz) { + if (_is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignement request of shared instance from specified " + "image (%u,%u,%u,%u).", + cimg_instance, + size_x,size_y,size_z,size_c); + else { + delete[] _data; + try { _data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + } + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + return *this; + } + + //! Construct image with specified size and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,T). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const T& value) { + return assign(size_x,size_y,size_z,size_c).fill(value); + } + + //! Construct image with specified size and initialize pixel values from a sequence of integers \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,int,int,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const int value0, const int value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,int); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a sequence of doubles \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,double,double,...). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const double value0, const double value1, ...) { + assign(size_x,size_y,size_z,size_c); + _CImg_stdarg(*this,value0,value1,(size_t)size_x*size_y*size_z*size_c,double); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a value string \inplace. + /** + In-place version of the constructor CImg(unsigned int,unsigned int,unsigned int,unsigned int,const char*,bool). + **/ + CImg& assign(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const char *const values, const bool repeat_values) { + return assign(size_x,size_y,size_z,size_c).fill(values,repeat_values); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \inplace. + /** + In-place version of the constructor CImg(const t*,unsigned int,unsigned int,unsigned int,unsigned int). + **/ + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (!values || !siz) return assign(); + assign(size_x,size_y,size_z,size_c); + const t *ptrs = values; cimg_for(*this,ptrd,T) *ptrd = (T)*(ptrs++); + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \specialization. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (!values || !siz) return assign(); + const size_t curr_siz = (size_t)size(); + if (values==_data && siz==curr_siz) return assign(size_x,size_y,size_z,size_c); + if (_is_shared || values + siz<_data || values>=_data + size()) { + assign(size_x,size_y,size_z,size_c); + if (_is_shared) std::memmove(_data,values,siz*sizeof(T)); + else std::memcpy(_data,values,siz*sizeof(T)); + } else { + T *new_data = 0; + try { new_data = new T[siz]; } catch (...) { + _width = _height = _depth = _spectrum = 0; _data = 0; + throw CImgInstanceException(_cimg_instance + "assign(): Failed to allocate memory (%s) for image (%u,%u,%u,%u).", + cimg_instance, + cimg::strbuffersize(sizeof(T)*size_x*size_y*size_z*size_c), + size_x,size_y,size_z,size_c); + } + std::memcpy(new_data,values,siz*sizeof(T)); + delete[] _data; _data = new_data; _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; + } + return *this; + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + template + CImg& assign(const t *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + if (is_shared) + throw CImgArgumentException(_cimg_instance + "assign(): Invalid assignment request of shared instance from (%s*) buffer" + "(pixel types are different).", + cimg_instance, + CImg::pixel_type()); + return assign(values,size_x,size_y,size_z,size_c); + } + + //! Construct image with specified size and initialize pixel values from a memory buffer \overloading. + CImg& assign(const T *const values, const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, const bool is_shared) { + const size_t siz = (size_t)size_x*size_y*size_z*size_c; + if (!values || !siz) return assign(); + if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); } + else { + if (!_is_shared) { + if (values + siz<_data || values>=_data + size()) assign(); + else cimg::warn(_cimg_instance + "assign(): Shared image instance has overlapping memory.", + cimg_instance); + } + _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = true; + _data = const_cast(values); + } + return *this; + } + + //! Construct image from reading an image file \inplace. + /** + In-place version of the constructor CImg(const char*). + **/ + CImg& assign(const char *const filename) { + return load(filename); + } + + //! Construct image copy \inplace. + /** + In-place version of the constructor CImg(const CImg&). + **/ + template + CImg& assign(const CImg& img) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum); + } + + //! In-place version of the advanced copy constructor. + /** + In-place version of the constructor CImg(const CImg&,bool). + **/ + template + CImg& assign(const CImg& img, const bool is_shared) { + return assign(img._data,img._width,img._height,img._depth,img._spectrum,is_shared); + } + + //! Construct image with dimensions borrowed from another image \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions) { + if (!dimensions || !*dimensions) return assign(img._width,img._height,img._depth,img._spectrum); + unsigned int siz[4] = { 0,1,1,1 }, k = 0; + CImg item(256); + for (const char *s = dimensions; *s && k<4; ++k) { + if (cimg_sscanf(s,"%255[^0-9%xyzvwhdcXYZVWHDC]",item._data)>0) s+=std::strlen(item); + if (*s) { + unsigned int val = 0; char sep = 0; + if (cimg_sscanf(s,"%u%c",&val,&sep)>0) { + if (sep=='%') siz[k] = val*(k==0?_width:k==1?_height:k==2?_depth:_spectrum)/100; + else siz[k] = val; + while (*s>='0' && *s<='9') ++s; + if (sep=='%') ++s; + } else switch (cimg::lowercase(*s)) { + case 'x' : case 'w' : siz[k] = img._width; ++s; break; + case 'y' : case 'h' : siz[k] = img._height; ++s; break; + case 'z' : case 'd' : siz[k] = img._depth; ++s; break; + case 'c' : case 's' : siz[k] = img._spectrum; ++s; break; + default : + throw CImgArgumentException(_cimg_instance + "assign(): Invalid character '%c' detected in specified dimension string '%s'.", + cimg_instance, + *s,dimensions); + } + } + } + return assign(siz[0],siz[1],siz[2],siz[3]); + } + + //! Construct image with dimensions borrowed from another image and initialize pixel values \inplace. + /** + In-place version of the constructor CImg(const CImg&,const char*,T). + **/ + template + CImg& assign(const CImg& img, const char *const dimensions, const T& value) { + return assign(img,dimensions).fill(value); + } + + //! Construct image from a display window \inplace. + /** + In-place version of the constructor CImg(const CImgDisplay&). + **/ + CImg& assign(const CImgDisplay &disp) { + disp.snapshot(*this); + return *this; + } + + //! Construct empty image \inplace. + /** + Equivalent to assign(). + \note + - It has been defined for compatibility with STL naming conventions. + **/ + CImg& clear() { + return assign(); + } + + //! Transfer content of an image instance into another one. + /** + Transfer the dimensions and the pixel buffer content of an image instance into another one, + and replace instance by an empty image. It avoids the copy of the pixel buffer + when possible. + \param img Destination image. + \note + - Pixel types \c T and \c t of source and destination images can be different, though the process is + designed to be instantaneous when \c T and \c t are the same. + \par Example + \code + CImg src(256,256,1,3,0), // Construct a 256x256x1x3 (color) image filled with value '0'. + dest(16,16); // Construct a 16x16x1x1 (scalar) image. + src.move_to(dest); // Now, 'src' is empty and 'dest' is the 256x256x1x3 image. + \endcode + **/ + template + CImg& move_to(CImg& img) { + img.assign(*this); + assign(); + return img; + } + + //! Transfer content of an image instance into another one \specialization. + CImg& move_to(CImg& img) { + if (_is_shared || img._is_shared) img.assign(*this); + else swap(img); + assign(); + return img; + } + + //! Transfer content of an image instance into a new image in an image list. + /** + Transfer the dimensions and the pixel buffer content of an image instance + into a newly inserted image at position \c pos in specified \c CImgList instance. + \param list Destination list. + \param pos Position of the newly inserted image in the list. + \note + - When optionnal parameter \c pos is ommited, the image instance is transfered as a new + image at the end of the specified \c list. + - It is convenient to sequentially insert new images into image lists, with no + additional copies of memory buffer. + \par Example + \code + CImgList list; // Construct an empty image list. + CImg img("reference.jpg"); // Read image from filename. + img.move_to(list); // Transfer image content as a new item in the list (no buffer copy). + \endcode + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos=~0U) { + const unsigned int npos = pos>list._width?list._width:pos; + move_to(list.insert(1,npos)[npos]); + return list; + } + + //! Swap fields of two image instances. + /** + \param img Image to swap fields with. + \note + - It can be used to interchange the content of two images in a very fast way. Can be convenient when dealing + with algorithms requiring two swapping buffers. + \par Example + \code + CImg img1("lena.jpg"), + img2("milla.jpg"); + img1.swap(img2); // Now, 'img1' is 'milla' and 'img2' is 'lena'. + \endcode + **/ + CImg& swap(CImg& img) { + cimg::swap(_width,img._width,_height,img._height,_depth,img._depth,_spectrum,img._spectrum); + cimg::swap(_data,img._data); + cimg::swap(_is_shared,img._is_shared); + return img; + } + + //! Return a reference to an empty image. + /** + \note + This function is useful mainly to declare optional parameters having type \c CImg in functions prototypes, + e.g. + \code + void f(const int x=0, const int y=0, const CImg& img=CImg::empty()); + \endcode + **/ + static CImg& empty() { + static CImg _empty; + return _empty.assign(); + } + + //! Return a reference to an empty image \const. + static const CImg& const_empty() { + static const CImg _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Access to a pixel value. + /** + Return a reference to a located pixel value of the image instance, + being possibly \e const, whether the image instance is \e const or not. + This is the standard method to get/set pixel values in \c CImg images. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Range of pixel coordinates start from (0,0,0,0) to + (width() - 1,height() - 1,depth() - 1,spectrum() - 1). + - Due to the particular arrangement of the pixel buffers defined in %CImg, you can omit one coordinate if the + corresponding dimension is equal to \c 1. + For instance, pixels of a 2d image (depth() equal to \c 1) can be accessed by img(x,y,c) instead of + img(x,y,0,c). + \warning + - There is \e no boundary checking done in this operator, to make it as fast as possible. + You \e must take care of out-of-bounds access by yourself, if necessary. + For debuging purposes, you may want to define macro \c 'cimg_verbosity'>=3 to enable additional boundary + checking operations in this operator. In that case, warning messages will be printed on the error output + when accessing out-of-bounds pixels. + \par Example + \code + CImg img(100,100,1,3,0); // Construct a 100x100x1x3 (color) image with pixels set to '0'. + const float + valR = img(10,10,0,0), // Read red value at coordinates (10,10). + valG = img(10,10,0,1), // Read green value at coordinates (10,10) + valB = img(10,10,2), // Read blue value at coordinates (10,10) (Z-coordinate can be omitted). + avg = (valR + valG + valB)/3; // Compute average pixel value. + img(10,10,0) = img(10,10,1) = img(10,10,2) = avg; // Replace the color pixel (10,10) by the average grey value. + \endcode + **/ +#if cimg_verbosity>=3 + T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (!_data || off>=size()) { + cimg::warn(_cimg_instance + "operator(): Invalid pixel request, at coordinates (%d,%d,%d,%d) [offset=%u].", + cimg_instance, + (int)x,(int)y,(int)z,(int)c,off); + return *_data; + } + else return _data[off]; + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->operator()(x,y,z,c); + } + + //! Access to a pixel value. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param wh Precomputed offset, must be equal to width()*\ref height(). + \param whd Precomputed offset, must be equal to width()*\ref height()*\ref depth(). + \note + - Similar to (but faster than) operator()(). + It uses precomputed offsets to optimize memory access. You may use it to optimize + the reading/writing of several pixel values in the same image (e.g. in a loop). + **/ + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } + + //! Access to a pixel value \const. + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd=0) const { + cimg::unused(wh,whd); + return (*this)(x,y,z,c); + } +#else + T& operator()(const unsigned int x) { + return _data[x]; + } + + const T& operator()(const unsigned int x) const { + return _data[x]; + } + + T& operator()(const unsigned int x, const unsigned int y) { + return _data[x + y*_width]; + } + + const T& operator()(const unsigned int x, const unsigned int y) const { + return _data[x + y*_width]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c) const { + return _data[x + y*(ulongT)_width + z*(ulongT)_width*_height + c*(ulongT)_width*_height*_depth]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) { + return _data[x + y*_width + z*wh]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int, + const ulongT wh) const { + return _data[x + y*_width + z*wh]; + } + + T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) { + return _data[x + y*_width + z*wh + c*whd]; + } + + const T& operator()(const unsigned int x, const unsigned int y, const unsigned int z, const unsigned int c, + const ulongT wh, const ulongT whd) const { + return _data[x + y*_width + z*wh + c*whd]; + } +#endif + + //! Implicitely cast an image into a \c T*. + /** + Implicitely cast a \c CImg instance into a \c T* or \c const \c T* pointer, whether the image instance + is \e const or not. The returned pointer points on the first value of the image pixel buffer. + \note + - It simply returns the pointer data() to the pixel buffer. + - This implicit conversion is convenient to test the empty state of images (data() being \c 0 in this case), e.g. + \code + CImg img1(100,100), img2; // 'img1' is a 100x100 image, 'img2' is an empty image. + if (img1) { // Test succeeds, 'img1' is not an empty image. + if (!img2) { // Test succeeds, 'img2' is an empty image. + std::printf("'img1' is not empty, 'img2' is empty."); + } + } + \endcode + - It also allows to use brackets to access pixel values, without need for a \c CImg::operator[](), e.g. + \code + CImg img(100,100); + const float value = img[99]; // Access to value of the last pixel on the first row. + img[510] = 255; // Set pixel value at (10,5). + \endcode + **/ + operator T*() { + return _data; + } + + //! Implicitely cast an image into a \c T* \const. + operator const T*() const { + return _data; + } + + //! Assign a value to all image pixels. + /** + Assign specified \c value to each pixel value of the image instance. + \param value Value that will be assigned to image pixels. + \note + - The image size is never modified. + - The \c value may be casted to pixel type \c T if necessary. + \par Example + \code + CImg img(100,100); // Declare image (with garbage values). + img = 0; // Set all pixel values to '0'. + img = 1.2; // Set all pixel values to '1' (cast of '1.2' as a 'char'). + \endcode + **/ + CImg& operator=(const T& value) { + return fill(value); + } + + //! Assign pixels values from a specified expression. + /** + Initialize all pixel values from the specified string \c expression. + \param expression Value string describing the way pixel values are set. + \note + - String parameter \c expression may describe different things: + - If \c expression is a list of values (as in \c "1,2,3,8,3,2"), or a formula (as in \c "(x*y)%255"), + the pixel values are set from specified \c expression and the image size is not modified. + - If \c expression is a filename (as in \c "reference.jpg"), the corresponding image file is loaded and + replace the image instance. The image size is modified if necessary. + \par Example + \code + CImg img1(100,100), img2(img1), img3(img1); // Declare three 100x100 scalar images with unitialized pixel values. + img1 = "0,50,100,150,200,250,200,150,100,50"; // Set pixel values of 'img1' from a value sequence. + img2 = "10*((x*y)%25)"; // Set pixel values of 'img2' from a formula. + img3 = "reference.jpg"; // Set pixel values of 'img3' from a file (image size is modified). + (img1,img2,img3).display(); + \endcode + \image html ref_operator_eq.jpg + **/ + CImg& operator=(const char *const expression) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + _fill(expression,true,true,0,0,"operator=",0); + } catch (CImgException&) { + cimg::exception_mode(omode); + load(expression); + } + cimg::exception_mode(omode); + return *this; + } + + //! Copy an image into the current image instance. + /** + Similar to the in-place copy constructor assign(const CImg&). + **/ + template + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy an image into the current image instance \specialization. + CImg& operator=(const CImg& img) { + return assign(img); + } + + //! Copy the content of a display window to the current image instance. + /** + Similar to assign(const CImgDisplay&). + **/ + CImg& operator=(const CImgDisplay& disp) { + disp.snapshot(*this); + return *this; + } + + //! In-place addition operator. + /** + Add specified \c value to all pixels of an image instance. + \param value Value to add. + \note + - Resulting pixel values are casted to fit the pixel type \c T. + For instance, adding \c 0.2 to a \c CImg is possible but does nothing indeed. + - Overflow values are treated as with standard C++ numeric types. For instance, + \code + CImg img(100,100,1,1,255); // Construct a 100x100 image with pixel values '255'. + img+=1; // Add '1' to each pixels -> Overflow. + // here all pixels of image 'img' are equal to '0'. + \endcode + - To prevent value overflow, you may want to consider pixel type \c T as \c float or \c double, + and use cut() after addition. + \par Example + \code + CImg img1("reference.jpg"); // Load a 8-bits RGB image (values in [0,255]). + CImg img2(img1); // Construct a float-valued copy of 'img1'. + img2+=100; // Add '100' to pixel values -> goes out of [0,255] but no problems with floats. + img2.cut(0,255); // Cut values in [0,255] to fit the 'unsigned char' constraint. + img1 = img2; // Rewrite safe result in 'unsigned char' version 'img1'. + const CImg img3 = (img1 + 100).cut(0,255); // Do the same in a more simple and elegant way. + (img1,img2,img3).display(); + \endcode + \image html ref_operator_plus.jpg + **/ + template + CImg& operator+=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288)) + cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd + value); + return *this; + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the specified string \c expression. + \param expression Value string describing the way pixel values are added. + \note + - Similar to operator=(const char*), except that it adds values to the pixels of the current image instance, + instead of assigning them. + **/ + CImg& operator+=(const char *const expression) { + return *this+=(+*this)._fill(expression,true,true,0,0,"operator+=",this); + } + + //! In-place addition operator. + /** + Add values to image pixels, according to the values of the input image \c img. + \param img Input image to add. + \note + - The size of the image instance is never modified. + - It is not mandatory that input image \c img has the same size as the image instance. + If less values are available in \c img, then the values are added periodically. For instance, adding one + WxH scalar image (spectrum() equal to \c 1) to one WxH color image (spectrum() equal to \c 3) + means each color channel will be incremented with the same values at the same locations. + \par Example + \code + CImg img1("reference.jpg"); // Load a RGB color image (img1.spectrum()==3) + const CImg img2(img1.width(),img.height(),1,1,"255*(x/w)^2"); // Construct a scalar shading (img2.spectrum()==1). + img1+=img2; // Add shading to each channel of 'img1'. + img1.cut(0,255); // Prevent [0,255] overflow. + (img2,img1).display(); + \endcode + \image html ref_operator_plus1.jpg + **/ + template + CImg& operator+=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this+=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator++() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288)) + cimg_rof(*this,ptrd,T) ++*ptrd; + return *this; + } + + //! In-place increment operator (postfix). + /** + Add \c 1 to all image pixels, and return a new copy of the initial (pre-incremented) image instance. + \note + - Use the prefixed version operator++() if you don't need a copy of the initial + (pre-incremented) image instance, since a useless image copy may be expensive in terms of memory usage. + **/ + CImg operator++(int) { + const CImg copy(*this,false); + ++*this; + return copy; + } + + //! Return a non-shared copy of the image instance. + /** + \note + - Use this operator to ensure you get a non-shared copy of an image instance with same pixel type \c T. + Indeed, the usual copy constructor CImg(const CImg&) returns a shared copy of a shared input image, + and it may be not desirable to work on a regular copy (e.g. for a resize operation) if you have no + information about the shared state of the input image. + - Writing \c (+img) is equivalent to \c CImg(img,false). + **/ + CImg operator+() const { + return CImg(*this,false); + } + + //! Addition operator. + /** + Similar to operator+=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const t value) const { + return CImg<_cimg_Tt>(*this,false)+=value; + } + + //! Addition operator. + /** + Similar to operator+=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator+(const char *const expression) const { + return CImg(*this,false)+=expression; + } + + //! Addition operator. + /** + Similar to operator+=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator+(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)+=img; + } + + //! In-place substraction operator. + /** + Similar to operator+=(const t), except that it performs a substraction instead of an addition. + **/ + template + CImg& operator-=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288)) + cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd - value); + return *this; + } + + //! In-place substraction operator. + /** + Similar to operator+=(const char*), except that it performs a substraction instead of an addition. + **/ + CImg& operator-=(const char *const expression) { + return *this-=(+*this)._fill(expression,true,true,0,0,"operator-=",this); + } + + //! In-place substraction operator. + /** + Similar to operator+=(const CImg&), except that it performs a substraction instead of an addition. + **/ + template + CImg& operator-=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this-=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs& operator--() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288)) + cimg_rof(*this,ptrd,T) *ptrd = *ptrd - (T)1; + return *this; + } + + //! In-place decrement operator (postfix). + /** + Similar to operator++(int), except that it performs a decrement instead of an increment. + **/ + CImg operator--(int) { + const CImg copy(*this,false); + --*this; + return copy; + } + + //! Replace each pixel by its opposite value. + /** + \note + - If the computed opposite values are out-of-range, they are treated as with standard C++ numeric types. + For instance, the \c unsigned \c char opposite of \c 1 is \c 255. + \par Example + \code + const CImg + img1("reference.jpg"), // Load a RGB color image. + img2 = -img1; // Compute its opposite (in 'unsigned char'). + (img1,img2).display(); + \endcode + \image html ref_operator_minus.jpg + **/ + CImg operator-() const { + return CImg(_width,_height,_depth,_spectrum,(T)0)-=*this; + } + + //! Substraction operator. + /** + Similar to operator-=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const t value) const { + return CImg<_cimg_Tt>(*this,false)-=value; + } + + //! Substraction operator. + /** + Similar to operator-=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator-(const char *const expression) const { + return CImg(*this,false)-=expression; + } + + //! Substraction operator. + /** + Similar to operator-=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator-(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)-=img; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const t), except that it performs a multiplication instead of an addition. + **/ + template + CImg& operator*=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=262144)) + cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd * value); + return *this; + } + + //! In-place multiplication operator. + /** + Similar to operator+=(const char*), except that it performs a multiplication instead of an addition. + **/ + CImg& operator*=(const char *const expression) { + return mul((+*this)._fill(expression,true,true,0,0,"operator*=",this)); + } + + //! In-place multiplication operator. + /** + Replace the image instance by the matrix multiplication between the image instance and the specified matrix + \c img. + \param img Second operand of the matrix multiplication. + \note + - It does \e not compute a pointwise multiplication between two images. For this purpose, use + mul(const CImg&) instead. + - The size of the image instance can be modified by this operator. + \par Example + \code + CImg A(2,2,1,1, 1,2,3,4); // Construct 2x2 matrix A = [1,2;3,4]. + const CImg X(1,2,1,1, 1,2); // Construct 1x2 vector X = [1;2]. + A*=X; // Assign matrix multiplication A*X to 'A'. + // 'A' is now a 1x2 vector whose values are [5;11]. + \endcode + **/ + template + CImg& operator*=(const CImg& img) { + return ((*this)*img).move_to(*this); + } + + //! Multiplication operator. + /** + Similar to operator*=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const t value) const { + return CImg<_cimg_Tt>(*this,false)*=value; + } + + //! Multiplication operator. + /** + Similar to operator*=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator*(const char *const expression) const { + return CImg(*this,false)*=expression; + } + + //! Multiplication operator. + /** + Similar to operator*=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator*(const CImg& img) const { + if (_width!=img._height || _depth!=1 || _spectrum!=1) + throw CImgArgumentException(_cimg_instance + "operator*(): Invalid multiplication of instance by specified " + "matrix (%u,%u,%u,%u,%p)", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + CImg<_cimg_Tt> res(img._width,_height); +#ifdef cimg_use_openmp + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(size()>1024 && img.size()>1024)) + cimg_forXY(res,i,j) { + _cimg_Ttdouble value = 0; cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); res(i,j) = (_cimg_Tt)value; + } +#else + _cimg_Tt *ptrd = res._data; + cimg_forXY(res,i,j) { + _cimg_Ttdouble value = 0; cimg_forX(*this,k) value+=(*this)(k,j)*img(i,k); *(ptrd++) = (_cimg_Tt)value; + } +#endif + return res; + } + + //! In-place division operator. + /** + Similar to operator+=(const t), except that it performs a division instead of an addition. + **/ + template + CImg& operator/=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (T)(*ptrd / value); + return *this; + } + + //! In-place division operator. + /** + Similar to operator+=(const char*), except that it performs a division instead of an addition. + **/ + CImg& operator/=(const char *const expression) { + return div((+*this)._fill(expression,true,true,0,0,"operator/=",this)); + } + + //! In-place division operator. + /** + Replace the image instance by the (right) matrix division between the image instance and the specified + matrix \c img. + \param img Second operand of the matrix division. + \note + - It does \e not compute a pointwise division between two images. For this purpose, use + div(const CImg&) instead. + - It returns the matrix operation \c A*inverse(img). + - The size of the image instance can be modified by this operator. + **/ + template + CImg& operator/=(const CImg& img) { + return (*this*img.get_invert()).move_to(*this); + } + + //! Division operator. + /** + Similar to operator/=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const t value) const { + return CImg<_cimg_Tt>(*this,false)/=value; + } + + //! Division operator. + /** + Similar to operator/=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator/(const char *const expression) const { + return CImg(*this,false)/=expression; + } + + //! Division operator. + /** + Similar to operator/=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator/(const CImg& img) const { + return (*this)*img.get_invert(); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const t), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=16384)) + cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::mod(*ptrd,(T)value); + return *this; + } + + //! In-place modulo operator. + /** + Similar to operator+=(const char*), except that it performs a modulo operation instead of an addition. + **/ + CImg& operator%=(const char *const expression) { + return *this%=(+*this)._fill(expression,true,true,0,0,"operator%=",this); + } + + //! In-place modulo operator. + /** + Similar to operator+=(const CImg&), except that it performs a modulo operation instead of an addition. + **/ + template + CImg& operator%=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this%=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> operator%(const t value) const { + return CImg<_cimg_Tt>(*this,false)%=value; + } + + //! Modulo operator. + /** + Similar to operator%=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + CImg operator%(const char *const expression) const { + return CImg(*this,false)%=expression; + } + + //! Modulo operator. + /** + Similar to operator%=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image may be a superset of the initial pixel type \c T, if necessary. + **/ + template + CImg<_cimg_Tt> operator%(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false)%=img; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const t), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (T)((ulongT)*ptrd & (ulongT)value); + return *this; + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise AND operation instead of an addition. + **/ + CImg& operator&=(const char *const expression) { + return *this&=(+*this)._fill(expression,true,true,0,0,"operator&=",this); + } + + //! In-place bitwise AND operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise AND operation instead of an addition. + **/ + template + CImg& operator&=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this&=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator&(const t value) const { + return (+*this)&=value; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator&(const char *const expression) const { + return (+*this)&=expression; + } + + //! Bitwise AND operator. + /** + Similar to operator&=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator&(const CImg& img) const { + return (+*this)&=img; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (T)((ulongT)*ptrd | (ulongT)value); + return *this; + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise OR operation instead of an addition. + **/ + CImg& operator|=(const char *const expression) { + return *this|=(+*this)._fill(expression,true,true,0,0,"operator|=",this); + } + + //! In-place bitwise OR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise OR operation instead of an addition. + **/ + template + CImg& operator|=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this|=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator|(const t value) const { + return (+*this)|=value; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator|(const char *const expression) const { + return (+*this)|=expression; + } + + //! Bitwise OR operator. + /** + Similar to operator|=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator|(const CImg& img) const { + return (+*this)|=img; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const t), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const t) instead. + **/ + template + CImg& operator^=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (T)((ulongT)*ptrd ^ (ulongT)value); + return *this; + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const char*) instead. + **/ + CImg& operator^=(const char *const expression) { + return *this^=(+*this)._fill(expression,true,true,0,0,"operator^=",this); + } + + //! In-place bitwise XOR operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise XOR operation instead of an addition. + \warning + - It does \e not compute the \e power of pixel values. For this purpose, use pow(const CImg&) instead. + **/ + template + CImg& operator^=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator^(const t value) const { + return (+*this)^=value; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator^(const char *const expression) const { + return (+*this)^=expression; + } + + //! Bitwise XOR operator. + /** + Similar to operator^=(const CImg&), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator^(const CImg& img) const { + return (+*this)^=img; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536)) + cimg_rof(*this,ptrd,T) *ptrd = (T)(((longT)*ptrd) << (int)value); + return *this; + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise left shift instead of an addition. + **/ + CImg& operator<<=(const char *const expression) { + return *this<<=(+*this)._fill(expression,true,true,0,0,"operator<<=",this); + } + + //! In-place bitwise left shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise left shift instead of an addition. + **/ + template + CImg& operator<<=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg operator<<(const t value) const { + return (+*this)<<=value; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator<<(const char *const expression) const { + return (+*this)<<=expression; + } + + //! Bitwise left shift operator. + /** + Similar to operator<<=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator<<(const CImg& img) const { + return (+*this)<<=img; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const t), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const t value) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536)) + cimg_rof(*this,ptrd,T) *ptrd = (T)(((longT)*ptrd) >> (int)value); + return *this; + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const char*), except that it performs a bitwise right shift instead of an addition. + **/ + CImg& operator>>=(const char *const expression) { + return *this>>=(+*this)._fill(expression,true,true,0,0,"operator>>=",this); + } + + //! In-place bitwise right shift operator. + /** + Similar to operator+=(const CImg&), except that it performs a bitwise right shift instead of an addition. + **/ + template + CImg& operator>>=(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return *this^=+img; + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs> (int)*(ptrs++)); + for (const t *ptrs = img._data; ptrd> (int)*(ptrs++)); + } + return *this; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const t), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const t value) const { + return (+*this)>>=value; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const char*), except that it returns a new image instance instead of operating in-place. + The pixel type of the returned image is \c T. + **/ + CImg operator>>(const char *const expression) const { + return (+*this)>>=expression; + } + + //! Bitwise right shift operator. + /** + Similar to operator>>=(const CImg&), except that it returns a new image instance instead of + operating in-place. + The pixel type of the returned image is \c T. + **/ + template + CImg operator>>(const CImg& img) const { + return (+*this)>>=img; + } + + //! Bitwise inversion operator. + /** + Similar to operator-(), except that it compute the bitwise inverse instead of the opposite value. + **/ + CImg operator~() const { + CImg res(_width,_height,_depth,_spectrum); + const T *ptrs = _data; + cimg_for(res,ptrd,T) { const ulongT value = (ulongT)*(ptrs++); *ptrd = (T)~value; } + return res; + } + + //! Test if all pixels of an image have the same value. + /** + Return \c true is all pixels of the image instance are equal to the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator==(const t value) const { + if (is_empty()) return false; + typedef _cimg_Tt Tt; + bool is_equal = true; + for (T *ptrd = _data + size(); is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)value)) {} + return is_equal; + } + + //! Test if all pixel values of an image follow a specified expression. + /** + Return \c true is all pixels of the image instance are equal to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator==(const char *const expression) const { + return *this==(+*this)._fill(expression,true,true,0,0,"operator==",this); + } + + //! Test if two images have the same size and values. + /** + Return \c true if the image instance and the input image \c img have the same dimensions and pixel values, + and \c false otherwise. + \param img Input image to compare with. + \note + - The pixel buffer pointers data() of the two compared images do not have to be the same for operator==() + to return \c true. + Only the dimensions and the pixel values matter. Thus, the comparison can be \c true even for different + pixel types \c T and \c t. + \par Example + \code + const CImg img1(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'float' pixel values). + const CImg img2(1,3,1,1, 0,1,2); // Construct a 1x3 vector [0;1;2] (with 'char' pixel values). + if (img1==img2) { // Test succeeds, image dimensions and values are the same. + std::printf("'img1' and 'img2' have same dimensions and values."); + } + \endcode + **/ + template + bool operator==(const CImg& img) const { + typedef _cimg_Tt Tt; + const ulongT siz = size(); + bool is_equal = true; + if (siz!=img.size()) return false; + t *ptrs = img._data + siz; + for (T *ptrd = _data + siz; is_equal && ptrd>_data; is_equal = ((Tt)*(--ptrd)==(Tt)*(--ptrs))) {} + return is_equal; + } + + //! Test if pixels of an image are all different from a value. + /** + Return \c true is all pixels of the image instance are different than the specified \c value. + \param value Reference value to compare with. + **/ + template + bool operator!=(const t value) const { + return !((*this)==value); + } + + //! Test if all pixel values of an image are different from a specified expression. + /** + Return \c true is all pixels of the image instance are different to the specified \c expression. + \param expression Value string describing the way pixel values are compared. + **/ + bool operator!=(const char *const expression) const { + return !((*this)==expression); + } + + //! Test if two images have different sizes or values. + /** + Return \c true if the image instance and the input image \c img have different dimensions or pixel values, + and \c false otherwise. + \param img Input image to compare with. + \note + - Writing \c img1!=img2 is equivalent to \c !(img1==img2). + **/ + template + bool operator!=(const CImg& img) const { + return !((*this)==img); + } + + //! Construct an image list from two images. + /** + Return a new list of image (\c CImgList instance) containing exactly two elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image \c img, at position [\c 1]. + + \param img Input image that will be the second image of the resulting list. + \note + - The family of operator,() is convenient to easily create list of images, but it is also \e quite \e slow + in practice (see warning below). + - Constructed lists contain no shared images. If image instance or input image \c img are shared, they are + inserted as new non-shared copies in the resulting list. + - The pixel type of the returned list may be a superset of the initial pixel type \c T, if necessary. + \warning + - Pipelining operator,() \c N times will perform \c N copies of the entire content of a (growing) image list. + This may become very expensive in terms of speed and used memory. You should avoid using this technique to + build a new CImgList instance from several images, if you are seeking for performance. + Fast insertions of images in an image list are possible with + CImgList::insert(const CImg&,unsigned int,bool) or move_to(CImgList&,unsigned int). + \par Example + \code + const CImg + img1("reference.jpg"), + img2 = img1.get_mirror('x'), + img3 = img2.get_blur(5); + const CImgList list = (img1,img2); // Create list of two elements from 'img1' and 'img2'. + (list,img3).display(); // Display image list containing copies of 'img1','img2' and 'img3'. + \endcode + \image html ref_operator_comma.jpg + **/ + template + CImgList<_cimg_Tt> operator,(const CImg& img) const { + return CImgList<_cimg_Tt>(*this,img); + } + + //! Construct an image list from image instance and an input image list. + /** + Return a new list of images (\c CImgList instance) containing exactly \c list.size() \c + \c 1 elements: + - A copy of the image instance, at position [\c 0]. + - A copy of the specified image list \c list, from positions [\c 1] to [\c list.size()]. + + \param list Input image list that will be appended to the image instance. + \note + - Similar to operator,(const CImg&) const, except that it takes an image list as an argument. + **/ + template + CImgList<_cimg_Tt> operator,(const CImgList& list) const { + return CImgList<_cimg_Tt>(list,false).insert(*this,0); + } + + //! Split image along specified axis. + /** + Return a new list of images (\c CImgList instance) containing the splitted components + of the instance image along the specified axis. + \param axis Splitting axis (can be '\c x','\c y','\c z' or '\c c') + \note + - Similar to get_split(char,int) const, with default second argument. + \par Example + \code + const CImg img("reference.jpg"); // Load a RGB color image. + const CImgList list = (img<'c'); // Get a list of its three R,G,B channels. + (img,list).display(); + \endcode + \image html ref_operator_less.jpg + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the number of image columns. + /** + Return the image width, i.e. the image dimension along the X-axis. + \note + - The width() of an empty image is equal to \c 0. + - width() is typically equal to \c 1 when considering images as \e vectors for matrix calculations. + - width() returns an \c int, although the image width is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._width. + **/ + int width() const { + return (int)_width; + } + + //! Return the number of image rows. + /** + Return the image height, i.e. the image dimension along the Y-axis. + \note + - The height() of an empty image is equal to \c 0. + - height() returns an \c int, although the image height is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._height. + **/ + int height() const { + return (int)_height; + } + + //! Return the number of image slices. + /** + Return the image depth, i.e. the image dimension along the Z-axis. + \note + - The depth() of an empty image is equal to \c 0. + - depth() is typically equal to \c 1 when considering usual 2d images. When depth()\c > \c 1, the image + is said to be \e volumetric. + - depth() returns an \c int, although the image depth is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._depth. + **/ + int depth() const { + return (int)_depth; + } + + //! Return the number of image channels. + /** + Return the number of image channels, i.e. the image dimension along the C-axis. + \note + - The spectrum() of an empty image is equal to \c 0. + - spectrum() is typically equal to \c 1 when considering scalar-valued images, to \c 3 + for RGB-coded color images, and to \c 4 for RGBA-coded color images (with alpha-channel). + The number of channels of an image instance is not limited. The meaning of the pixel values is not linked + up to the number of channels (e.g. a 4-channel image may indifferently stands for a RGBA or CMYK color image). + - spectrum() returns an \c int, although the image spectrum is internally stored as an \c unsigned \c int. + Using an \c int is safer and prevents arithmetic traps possibly encountered when doing calculations involving + \c unsigned \c int variables. + Access to the initial \c unsigned \c int variable is possible (though not recommended) by + (*this)._spectrum. + **/ + int spectrum() const { + return (int)_spectrum; + } + + //! Return the total number of pixel values. + /** + Return width()*\ref height()*\ref depth()*\ref spectrum(), + i.e. the total number of values of type \c T in the pixel buffer of the image instance. + \note + - The size() of an empty image is equal to \c 0. + - The allocated memory size for a pixel buffer of a non-shared \c CImg instance is equal to + size()*sizeof(T). + \par Example + \code + const CImg img(100,100,1,3); // Construct new 100x100 color image. + if (img.size()==30000) // Test succeeds. + std::printf("Pixel buffer uses %lu bytes", + img.size()*sizeof(float)); + \endcode + **/ + ulongT size() const { + return (ulongT)_width*_height*_depth*_spectrum; + } + + //! Return a pointer to the first pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the first value in the pixel buffer of the image instance, + whether the instance is \c const or not. + \note + - The data() of an empty image is equal to \c 0 (null pointer). + - The allocated pixel buffer for the image instance starts from \c data() + and goes to data()+\ref size() - 1 (included). + - To get the pointer to one particular location of the pixel buffer, use + data(unsigned int,unsigned int,unsigned int,unsigned int) instead. + **/ + T* data() { + return _data; + } + + //! Return a pointer to the first pixel value \const. + const T* data() const { + return _data; + } + + //! Return a pointer to a located pixel value. + /** + Return a \c T*, or a \c const \c T* pointer to the value located at (\c x,\c y,\c z,\c c) in the pixel buffer + of the image instance, + whether the instance is \c const or not. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)). Thus, this method has the same + properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + **/ +#if cimg_verbosity>=3 + T *data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + const ulongT off = (ulongT)offset(x,y,z,c); + if (off>=size()) + cimg::warn(_cimg_instance + "data(): Invalid pointer request, at coordinates (%u,%u,%u,%u) [offset=%u].", + cimg_instance, + x,y,z,c,off); + return _data + off; + } + + //! Return a pointer to a located pixel value \const. + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return const_cast*>(this)->data(x,y,z,c); + } +#else + T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } + + const T* data(const unsigned int x, const unsigned int y=0, const unsigned int z=0, const unsigned int c=0) const { + return _data + x + (ulongT)y*_width + (ulongT)z*_width*_height + (ulongT)c*_width*_height*_depth; + } +#endif + + //! Return the offset to a located pixel value, with respect to the beginning of the pixel buffer. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Writing \c img.data(x,y,z,c) is equivalent to &(img(x,y,z,c)) - img.data(). + Thus, this method has the same properties as operator()(unsigned int,unsigned int,unsigned int,unsigned int). + \par Example + \code + const CImg img(100,100,1,3); // Define a 100x100 RGB-color image. + const long off = img.offset(10,10,0,2); // Get the offset of the blue value of the pixel located at (10,10). + const float val = img[off]; // Get the blue value of this pixel. + \endcode + **/ + longT offset(const int x, const int y=0, const int z=0, const int c=0) const { + return x + (longT)y*_width + (longT)z*_width*_height + (longT)c*_width*_height*_depth; + } + + //! Return a CImg::iterator pointing to the first pixel value. + /** + \note + - Equivalent to data(). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + iterator begin() { + return _data; + } + + //! Return a CImg::iterator pointing to the first value of the pixel buffer \const. + const_iterator begin() const { + return _data; + } + + //! Return a CImg::iterator pointing next to the last pixel value. + /** + \note + - Writing \c img.end() is equivalent to img.data() + img.size(). + - It has been mainly defined for compatibility with STL naming conventions. + \warning + - The returned iterator actually points to a value located \e outside the acceptable bounds of the pixel buffer. + Trying to read or write the content of the returned iterator will probably result in a crash. + Use it mainly as a strict upper bound for a CImg::iterator. + \par Example + \code + CImg img(100,100,1,3); // Define a 100x100 RGB color image. + for (CImg::iterator it = img.begin(); it::iterator pointing next to the last pixel value \const. + const_iterator end() const { + return _data + size(); + } + + //! Return a reference to the first pixel value. + /** + \note + - Writing \c img.front() is equivalent to img[0], or img(0,0,0,0). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& front() { + return *_data; + } + + //! Return a reference to the first pixel value \const. + const T& front() const { + return *_data; + } + + //! Return a reference to the last pixel value. + /** + \note + - Writing \c img.end() is equivalent to img[img.size() - 1], or + img(img.width() - 1,img.height() - 1,img.depth() - 1,img.spectrum() - 1). + - It has been mainly defined for compatibility with STL naming conventions. + **/ + T& back() { + return *(_data + size() - 1); + } + + //! Return a reference to the last pixel value \const. + const T& back() const { + return *(_data + size() - 1); + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to a specified default value in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note + - Writing \c img.at(offset,out_value) is similar to img[offset], except that if \c offset + is outside bounds (e.g. \c offset<0 or \c offset>=img.size()), a reference to a value \c out_value + is safely returned instead. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + **/ + T& at(const int offset, const T& out_value) { + return (offset<0 || offset>=(int)size())?(cimg::temporary(out_value)=out_value):(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Dirichlet boundary conditions \const. + T at(const int offset, const T& out_value) const { + return (offset<0 || offset>=(int)size())?out_value:(*this)[offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions. + /** + Return a reference to the pixel value of the image instance located at a specified \c offset, + or to the nearest pixel location in the image instance in case of out-of-bounds access. + \param offset Offset to the desired pixel value. + \note + - Similar to at(int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified offset, i.e. + - If \c offset<0, then \c img[0] is returned. + - If \c offset>=img.size(), then \c img[img.size() - 1] is returned. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel offset. + - If you know your image instance is \e not empty, you may rather use the slightly faster method \c _at(int). + **/ + T& at(const int offset) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + T& _at(const int offset) { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value at a specified offset, using Neumann boundary conditions \const. + const T& at(const int offset) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "at(): Empty instance.", + cimg_instance); + return _at(offset); + } + + const T& _at(const int offset) const { + const unsigned int siz = (unsigned int)size(); + return (*this)[offset<0?0:(unsigned int)offset>=siz?siz - 1:offset]; + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to a specified default value in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c x,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to operator()(), except that an out-of-bounds access along the X-axis returns the specified value + \c out_value. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || x>=width())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X-coordinate \const. + T atX(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || x>=width())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate. + /** + Return a reference to the pixel value of the image instance located at (\c x,\c y,\c z,\c c), + or to the nearest pixel location in the image instance in case of out-of-bounds access along the X-axis. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to at(int,int,int,int,const T), except that an out-of-bounds access returns the value of the + nearest pixel in the image instance, regarding the specified X-coordinate. + - Due to the additional boundary checking operation, this method is slower than operator()(). Use it when + you are \e not sure about the validity of the specified pixel coordinates. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _at(int,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + T& atX(const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + T& _atX(const int x, const int y=0, const int z=0, const int c=0) { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X-coordinate \const. + const T& atX(const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atX(): Empty instance.", + cimg_instance); + return _atX(x,y,z,c); + } + + const T& _atX(const int x, const int y=0, const int z=0, const int c=0) const { + return (*this)(x<0?0:(x>=width()?width() - 1:x),y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on X and Y-coordinates. + **/ + T& atXY(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || x>=width() || y>=height())?(cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X and Y coordinates \const. + T atXY(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || x>=width() || y>=height())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXY(int,int,int,int). + **/ + T& atXY(const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + T& _atXY(const int x, const int y, const int z=0, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X and Y-coordinates \const. + const T& atXY(const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXY(): Empty instance.", + cimg_instance); + return _atXY(x,y,z,c); + } + + const T& _atXY(const int x, const int y, const int z=0, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1),z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed both on + X,Y and Z-coordinates. + **/ + T& atXYZ(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions for the X,Y and Z-coordinates \const. + T atXYZ(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || x>=width() || y>=height() || z>=depth())?out_value:(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed both on X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZ(int,int,int,int). + **/ + T& atXYZ(const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + T& _atXYZ(const int x, const int y, const int z, const int c=0) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Neumann boundary conditions for the X,Y and Z-coordinates \const. + const T& atXYZ(const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZ(): Empty instance.", + cimg_instance); + return _atXYZ(x,y,z,c); + } + + const T& _atXYZ(const int x, const int y, const int z, const int c=0) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1),c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions. + /** + Similar to atX(int,int,int,int,const T), except that boundary checking is performed on all + X,Y,Z and C-coordinates. + **/ + T& atXYZC(const int x, const int y, const int z, const int c, const T& out_value) { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())? + (cimg::temporary(out_value)=out_value):(*this)(x,y,z,c); + } + + //! Access to a pixel value, using Dirichlet boundary conditions \const. + T atXYZC(const int x, const int y, const int z, const int c, const T& out_value) const { + return (x<0 || y<0 || z<0 || c<0 || x>=width() || y>=height() || z>=depth() || c>=spectrum())?out_value: + (*this)(x,y,z,c); + } + + //! Access to a pixel value, using Neumann boundary conditions. + /** + Similar to atX(int,int,int,int), except that boundary checking is performed on all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _atXYZC(int,int,int,int). + **/ + T& atXYZC(const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + T& _atXYZC(const int x, const int y, const int z, const int c) { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Access to a pixel value, using Neumann boundary conditions \const. + const T& atXYZC(const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "atXYZC(): Empty instance.", + cimg_instance); + return _atXYZC(x,y,z,c); + } + + const T& _atXYZC(const int x, const int y, const int z, const int c) const { + return (*this)(cimg::cut(x,0,width() - 1), + cimg::cut(y,0,height() - 1), + cimg::cut(z,0,depth() - 1), + cimg::cut(c,0,spectrum() - 1)); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to atX(int,int,int,int,const T), except that the returned pixel value is approximated by + a linear interpolation along the X-axis, if corresponding coordinates are not integers. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + const Tfloat + Ic = (Tfloat)atX(x,y,z,c,out_value), In = (Tfloat)atXY(nx,y,z,c,out_value); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a linearly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access along + the X-axis. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that an out-of-bounds access returns + the value of the nearest pixel in the image instance, regarding the specified X-coordinate. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atX(): Empty instance.", + cimg_instance); + + return _linear_atX(fx,y,z,c); + } + + Tfloat _linear_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1); + const unsigned int + x = (unsigned int)nfx; + const float + dx = nfx - x; + const unsigned int + nx = dx>0?x + 1:x; + const Tfloat + Ic = (Tfloat)(*this)(x,y,z,c), In = (Tfloat)(*this)(nx,y,z,c); + return Ic + dx*(In - Ic); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X and Y-coordinates. + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + const Tfloat + Icc = (Tfloat)atXY(x,y,z,c,out_value), Inc = (Tfloat)atXY(nx,y,z,c,out_value), + Icn = (Tfloat)atXY(x,ny,z,c,out_value), Inn = (Tfloat)atXY(nx,ny,z,c,out_value); + return Icc + dx*(Inc - Icc + dy*(Icc + Inn - Icn - Inc)) + dy*(Icn - Icc); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXY(float,float,int,int). + **/ + Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXY(): Empty instance.", + cimg_instance); + + return _linear_atXY(fx,fy,z,c); + } + + Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy; + const float + dx = nfx - x, + dy = nfy - y; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y; + const Tfloat + Icc = (Tfloat)(*this)(x,y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c); + return Icc + dx*(Inc - Icc + dy*(Icc + Inn - Icn - Inc)) + dy*(Icn - Icc); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved both for X,Y and Z-coordinates. + **/ + Tfloat linear_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + const Tfloat + Iccc = (Tfloat)atXYZ(x,y,z,c,out_value), Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), + Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), + Iccn = (Tfloat)atXYZ(x,y,nz,c,out_value), Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), + Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value); + return Iccc + + dx*(Incc - Iccc + + dy*(Iccc + Innc - Icnc - Incc + + dz*(Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)) + + dz*(Iccc + Incn - Iccn - Incc)) + + dy*(Icnc - Iccc + + dz*(Iccc + Icnn - Iccn - Icnc)) + + dz*(Iccn - Iccc); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZ(float,float,float,int). + **/ + Tfloat linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZ(): Empty instance.", + cimg_instance); + + return _linear_atXYZ(fx,fy,fz,c); + } + + Tfloat _linear_atXYZ(const float fx, const float fy=0, const float fz=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z; + const Tfloat + Iccc = (Tfloat)(*this)(x,y,z,c), Incc = (Tfloat)(*this)(nx,y,z,c), + Icnc = (Tfloat)(*this)(x,ny,z,c), Innc = (Tfloat)(*this)(nx,ny,z,c), + Iccn = (Tfloat)(*this)(x,y,nz,c), Incn = (Tfloat)(*this)(nx,y,nz,c), + Icnn = (Tfloat)(*this)(x,ny,nz,c), Innn = (Tfloat)(*this)(nx,ny,nz,c); + return Iccc + + dx*(Incc - Iccc + + dy*(Iccc + Innc - Icnc - Incc + + dz*(Iccn + Innn + Icnc + Incc - Icnn - Incn - Iccc - Innc)) + + dz*(Iccc + Incn - Iccn - Incc)) + + dy*(Icnc - Iccc + + dz*(Iccc + Icnn - Iccn - Icnc)) + + dz*(Iccn - Iccc); + } + + //! Return pixel value, using linear interpolation and Dirichlet boundary conditions for all X,Y,Z,C-coordinates. + /** + Similar to linear_atX(float,int,int,int,const T) const, except that the linear interpolation and the + boundary checking are achieved for all X,Y,Z and C-coordinates. + **/ + Tfloat linear_atXYZC(const float fx, const float fy, const float fz, const float fc, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1, + c = (int)fc - (fc>=0?0:1), nc = c + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z, + dc = fc - c; + const Tfloat + Icccc = (Tfloat)atXYZC(x,y,z,c,out_value), Inccc = (Tfloat)atXYZC(nx,y,z,c,out_value), + Icncc = (Tfloat)atXYZC(x,ny,z,c,out_value), Inncc = (Tfloat)atXYZC(nx,ny,z,c,out_value), + Iccnc = (Tfloat)atXYZC(x,y,nz,c,out_value), Incnc = (Tfloat)atXYZC(nx,y,nz,c,out_value), + Icnnc = (Tfloat)atXYZC(x,ny,nz,c,out_value), Innnc = (Tfloat)atXYZC(nx,ny,nz,c,out_value), + Icccn = (Tfloat)atXYZC(x,y,z,nc,out_value), Inccn = (Tfloat)atXYZC(nx,y,z,nc,out_value), + Icncn = (Tfloat)atXYZC(x,ny,z,nc,out_value), Inncn = (Tfloat)atXYZC(nx,ny,z,nc,out_value), + Iccnn = (Tfloat)atXYZC(x,y,nz,nc,out_value), Incnn = (Tfloat)atXYZC(nx,y,nz,nc,out_value), + Icnnn = (Tfloat)atXYZC(x,ny,nz,nc,out_value), Innnn = (Tfloat)atXYZC(nx,ny,nz,nc,out_value); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn -Icccc); + } + + //! Return pixel value, using linear interpolation and Neumann boundary conditions for all X,Y,Z and C-coordinates. + /** + Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking + are achieved for all X,Y,Z and C-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _linear_atXYZC(float,float,float,float). + **/ + Tfloat linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "linear_atXYZC(): Empty instance.", + cimg_instance); + + return _linear_atXYZC(fx,fy,fz,fc); + } + + Tfloat _linear_atXYZC(const float fx, const float fy=0, const float fz=0, const float fc=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1), + nfc = cimg::cut(fc,0,spectrum() - 1); + const unsigned int + x = (unsigned int)nfx, + y = (unsigned int)nfy, + z = (unsigned int)nfz, + c = (unsigned int)nfc; + const float + dx = nfx - x, + dy = nfy - y, + dz = nfz - z, + dc = nfc - c; + const unsigned int + nx = dx>0?x + 1:x, + ny = dy>0?y + 1:y, + nz = dz>0?z + 1:z, + nc = dc>0?c + 1:c; + const Tfloat + Icccc = (Tfloat)(*this)(x,y,z,c), Inccc = (Tfloat)(*this)(nx,y,z,c), + Icncc = (Tfloat)(*this)(x,ny,z,c), Inncc = (Tfloat)(*this)(nx,ny,z,c), + Iccnc = (Tfloat)(*this)(x,y,nz,c), Incnc = (Tfloat)(*this)(nx,y,nz,c), + Icnnc = (Tfloat)(*this)(x,ny,nz,c), Innnc = (Tfloat)(*this)(nx,ny,nz,c), + Icccn = (Tfloat)(*this)(x,y,z,nc), Inccn = (Tfloat)(*this)(nx,y,z,nc), + Icncn = (Tfloat)(*this)(x,ny,z,nc), Inncn = (Tfloat)(*this)(nx,ny,z,nc), + Iccnn = (Tfloat)(*this)(x,y,nz,nc), Incnn = (Tfloat)(*this)(nx,y,nz,nc), + Icnnn = (Tfloat)(*this)(x,ny,nz,nc), Innnn = (Tfloat)(*this)(nx,ny,nz,nc); + return Icccc + + dx*(Inccc - Icccc + + dy*(Icccc + Inncc - Icncc - Inccc + + dz*(Iccnc + Innnc + Icncc + Inccc - Icnnc - Incnc - Icccc - Inncc + + dc*(Iccnn + Innnn + Icncn + Inccn + Icnnc + Incnc + Icccc + Inncc - + Icnnn - Incnn - Icccn - Inncn - Iccnc - Innnc - Icncc - Inccc)) + + dc*(Icccn + Inncn + Icncc + Inccc - Icncn - Inccn - Icccc - Inncc)) + + dz*(Icccc + Incnc - Iccnc - Inccc + + dc*(Icccn + Incnn + Iccnc + Inccc - Iccnn - Inccn - Icccc - Incnc)) + + dc*(Icccc + Inccn - Inccc - Icccn)) + + dy*(Icncc - Icccc + + dz*(Icccc + Icnnc - Iccnc - Icncc + + dc*(Icccn + Icnnn + Iccnc + Icncc - Iccnn - Icncn - Icccc - Icnnc)) + + dc*(Icccc + Icncn - Icncc - Icccn)) + + dz*(Iccnc - Icccc + + dc*(Icccc + Iccnn - Iccnc - Icccn)) + + dc*(Icccn - Icccc); + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or a specified default value in case of out-of-bounds access along the X-axis. + The cubic interpolation uses Hermite splines. + \param fx d X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c (\c fx,\c y,\c z,\c c) is outside image bounds. + \note + - Similar to linear_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a \e cubic interpolation along the X-axis. + - The type of the returned pixel value is extended to \c float, if the pixel type \c T is not float-valued. + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2; + const float + dx = fx - x; + const Tfloat + Ip = (Tfloat)atX(px,y,z,c,out_value), Ic = (Tfloat)atX(x,y,z,c,out_value), + In = (Tfloat)atX(nx,y,z,c,out_value), Ia = (Tfloat)atX(ax,y,z,c,out_value); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return damped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that you can specify the authorized minimum + and maximum of the returned value. + **/ + Tfloat cubic_atX(const float fx, const int y, const int z, const int c, const T& out_value, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = cubic_atX(fx,y,z,c,out_value); + return valmax_value?max_value:val; + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c), + or the value of the nearest pixel location in the image instance in case of out-of-bounds access + along the X-axis. The cubic interpolation uses Hermite splines. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Similar to cubic_atX(float,int,int,int,const T) const, except that the returned pixel value is + approximated by a cubic interpolation along the X-axis. + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atX(float,int,int,int). + \warning + - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds. + **/ + Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atX(): Empty instance.", + cimg_instance); + return _cubic_atX(fx,y,z,c); + } + + Tfloat _cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1); + const int + x = (int)nfx; + const float + dx = nfx - x; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2; + const Tfloat + Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c), + In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c); + return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return damped pixel value, using cubic interpolation and Neumann boundary conditions for the X-coordinate. + /** + Similar to cubic_atX(float,int,int,int) const, except that you can specify the authorized minimum and maximum + of the returned value. + **/ + Tfloat cubic_atX(const float fx, const int y, const int z, const int c, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = cubic_atX(fx,y,z,c); + return valmax_value?max_value:val; + } + + Tfloat _cubic_atX(const float fx, const int y, const int z, const int c, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = _cubic_atX(fx,y,z,c); + return valmax_value?max_value:val; + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X and Y-coordinates. + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2; + const float dx = fx - x, dy = fy - y; + const Tfloat + Ipp = (Tfloat)atXY(px,py,z,c,out_value), Icp = (Tfloat)atXY(x,py,z,c,out_value), + Inp = (Tfloat)atXY(nx,py,z,c,out_value), Iap = (Tfloat)atXY(ax,py,z,c,out_value), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)atXY(px,y,z,c,out_value), Icc = (Tfloat)atXY(x, y,z,c,out_value), + Inc = (Tfloat)atXY(nx,y,z,c,out_value), Iac = (Tfloat)atXY(ax,y,z,c,out_value), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)atXY(px,ny,z,c,out_value), Icn = (Tfloat)atXY(x,ny,z,c,out_value), + Inn = (Tfloat)atXY(nx,ny,z,c,out_value), Ian = (Tfloat)atXY(ax,ny,z,c,out_value), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)atXY(px,ay,z,c,out_value), Ica = (Tfloat)atXY(x,ay,z,c,out_value), + Ina = (Tfloat)atXY(nx,ay,z,c,out_value), Iaa = (Tfloat)atXY(ax,ay,z,c,out_value), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return damped pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int,const T) const, except that you can specify the authorized + minimum and maximum of the returned value. + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, const T& out_value, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = cubic_atXY(fx,fy,z,c,out_value); + return valmax_value?max_value:val; + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X and Y-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved for both X and Y-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXY(float,float,int,int). + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXY(): Empty instance.", + cimg_instance); + return _cubic_atXY(fx,fy,z,c); + } + + Tfloat _cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1); + const int x = (int)nfx, y = (int)nfy; + const float dx = nfx - x, dy = nfy - y; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy>0?y + 1:y, ay = y + 2>=height()?height() - 1:y + 2; + const Tfloat + Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c), + Iap = (Tfloat)(*this)(ax,py,z,c), + Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ipc = (Tfloat)(*this)(px,y,z,c), Icc = (Tfloat)(*this)(x, y,z,c), Inc = (Tfloat)(*this)(nx,y,z,c), + Iac = (Tfloat)(*this)(ax,y,z,c), + Ic = Icc + 0.5f*(dx*(-Ipc + Inc) + dx*dx*(2*Ipc - 5*Icc + 4*Inc - Iac) + dx*dx*dx*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ipn = (Tfloat)(*this)(px,ny,z,c), Icn = (Tfloat)(*this)(x,ny,z,c), Inn = (Tfloat)(*this)(nx,ny,z,c), + Ian = (Tfloat)(*this)(ax,ny,z,c), + In = Icn + 0.5f*(dx*(-Ipn + Inn) + dx*dx*(2*Ipn - 5*Icn + 4*Inn - Ian) + dx*dx*dx*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ipa = (Tfloat)(*this)(px,ay,z,c), Ica = (Tfloat)(*this)(x,ay,z,c), Ina = (Tfloat)(*this)(nx,ay,z,c), + Iaa = (Tfloat)(*this)(ax,ay,z,c), + Ia = Ica + 0.5f*(dx*(-Ipa + Ina) + dx*dx*(2*Ipa - 5*Ica + 4*Ina - Iaa) + dx*dx*dx*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dy*(-Ip + In) + dy*dy*(2*Ip - 5*Ic + 4*In - Ia) + dy*dy*dy*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return damped pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y-coordinates. + /** + Similar to cubic_atXY(float,float,int,int) const, except that you can specify the authorized minimum and + maximum of the returned value. + **/ + Tfloat cubic_atXY(const float fx, const float fy, const int z, const int c, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = cubic_atXY(fx,fy,z,c); + return valmax_value?max_value:val; + } + + Tfloat _cubic_atXY(const float fx, const float fy, const int z, const int c, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = _cubic_atXY(fx,fy,z,c); + return valmax_value?max_value:val; + } + + //! Return pixel value, using cubic interpolation and Dirichlet boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int,const T) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value) const { + const int + x = (int)fx - (fx>=0?0:1), px = x - 1, nx = x + 1, ax = x + 2, + y = (int)fy - (fy>=0?0:1), py = y - 1, ny = y + 1, ay = y + 2, + z = (int)fz - (fz>=0?0:1), pz = z - 1, nz = z + 1, az = z + 2; + const float dx = fx - x, dy = fy - y, dz = fz - z; + const Tfloat + Ippp = (Tfloat)atXYZ(px,py,pz,c,out_value), Icpp = (Tfloat)atXYZ(x,py,pz,c,out_value), + Inpp = (Tfloat)atXYZ(nx,py,pz,c,out_value), Iapp = (Tfloat)atXYZ(ax,py,pz,c,out_value), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)atXYZ(px,y,pz,c,out_value), Iccp = (Tfloat)atXYZ(x, y,pz,c,out_value), + Incp = (Tfloat)atXYZ(nx,y,pz,c,out_value), Iacp = (Tfloat)atXYZ(ax,y,pz,c,out_value), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)atXYZ(px,ny,pz,c,out_value), Icnp = (Tfloat)atXYZ(x,ny,pz,c,out_value), + Innp = (Tfloat)atXYZ(nx,ny,pz,c,out_value), Ianp = (Tfloat)atXYZ(ax,ny,pz,c,out_value), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)atXYZ(px,ay,pz,c,out_value), Icap = (Tfloat)atXYZ(x,ay,pz,c,out_value), + Inap = (Tfloat)atXYZ(nx,ay,pz,c,out_value), Iaap = (Tfloat)atXYZ(ax,ay,pz,c,out_value), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)atXYZ(px,py,z,c,out_value), Icpc = (Tfloat)atXYZ(x,py,z,c,out_value), + Inpc = (Tfloat)atXYZ(nx,py,z,c,out_value), Iapc = (Tfloat)atXYZ(ax,py,z,c,out_value), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)atXYZ(px,y,z,c,out_value), Iccc = (Tfloat)atXYZ(x, y,z,c,out_value), + Incc = (Tfloat)atXYZ(nx,y,z,c,out_value), Iacc = (Tfloat)atXYZ(ax,y,z,c,out_value), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)atXYZ(px,ny,z,c,out_value), Icnc = (Tfloat)atXYZ(x,ny,z,c,out_value), + Innc = (Tfloat)atXYZ(nx,ny,z,c,out_value), Ianc = (Tfloat)atXYZ(ax,ny,z,c,out_value), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)atXYZ(px,ay,z,c,out_value), Icac = (Tfloat)atXYZ(x,ay,z,c,out_value), + Inac = (Tfloat)atXYZ(nx,ay,z,c,out_value), Iaac = (Tfloat)atXYZ(ax,ay,z,c,out_value), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)atXYZ(px,py,nz,c,out_value), Icpn = (Tfloat)atXYZ(x,py,nz,c,out_value), + Inpn = (Tfloat)atXYZ(nx,py,nz,c,out_value), Iapn = (Tfloat)atXYZ(ax,py,nz,c,out_value), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)atXYZ(px,y,nz,c,out_value), Iccn = (Tfloat)atXYZ(x, y,nz,c,out_value), + Incn = (Tfloat)atXYZ(nx,y,nz,c,out_value), Iacn = (Tfloat)atXYZ(ax,y,nz,c,out_value), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)atXYZ(px,ny,nz,c,out_value), Icnn = (Tfloat)atXYZ(x,ny,nz,c,out_value), + Innn = (Tfloat)atXYZ(nx,ny,nz,c,out_value), Iann = (Tfloat)atXYZ(ax,ny,nz,c,out_value), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)atXYZ(px,ay,nz,c,out_value), Ican = (Tfloat)atXYZ(x,ay,nz,c,out_value), + Inan = (Tfloat)atXYZ(nx,ay,nz,c,out_value), Iaan = (Tfloat)atXYZ(ax,ay,nz,c,out_value), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)atXYZ(px,py,az,c,out_value), Icpa = (Tfloat)atXYZ(x,py,az,c,out_value), + Inpa = (Tfloat)atXYZ(nx,py,az,c,out_value), Iapa = (Tfloat)atXYZ(ax,py,az,c,out_value), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)atXYZ(px,y,az,c,out_value), Icca = (Tfloat)atXYZ(x, y,az,c,out_value), + Inca = (Tfloat)atXYZ(nx,y,az,c,out_value), Iaca = (Tfloat)atXYZ(ax,y,az,c,out_value), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)atXYZ(px,ny,az,c,out_value), Icna = (Tfloat)atXYZ(x,ny,az,c,out_value), + Inna = (Tfloat)atXYZ(nx,ny,az,c,out_value), Iana = (Tfloat)atXYZ(ax,ny,az,c,out_value), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)atXYZ(px,ay,az,c,out_value), Icaa = (Tfloat)atXYZ(x,ay,az,c,out_value), + Inaa = (Tfloat)atXYZ(nx,ay,az,c,out_value), Iaaa = (Tfloat)atXYZ(ax,ay,az,c,out_value), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return damped pixel value, using cubic interpolation and Dirichlet boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int,const T) const, except that you can specify the authorized + minimum and maximum of the returned value. + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, const T& out_value, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = cubic_atXYZ(fx,fy,fz,c,out_value); + return valmax_value?max_value:val; + } + + //! Return pixel value, using cubic interpolation and Neumann boundary conditions for the X,Y and Z-coordinates. + /** + Similar to cubic_atX(float,int,int,int) const, except that the cubic interpolation and boundary checking + are achieved both for X,Y and Z-coordinates. + \note + - If you know your image instance is \e not empty, you may rather use the slightly faster method + \c _cubic_atXYZ(float,float,float,int). + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "cubic_atXYZ(): Empty instance.", + cimg_instance); + return _cubic_atXYZ(fx,fy,fz,c); + } + + Tfloat _cubic_atXYZ(const float fx, const float fy, const float fz, const int c=0) const { + const float + nfx = cimg::cut(fx,0,width() - 1), + nfy = cimg::cut(fy,0,height() - 1), + nfz = cimg::cut(fz,0,depth() - 1); + const int x = (int)nfx, y = (int)nfy, z = (int)nfz; + const float dx = nfx - x, dy = nfy - y, dz = nfz - z; + const int + px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2, + py = y - 1<0?0:y - 1, ny = dy>0?y + 1:y, ay = y + 2>=height()?height() - 1:y + 2, + pz = z - 1<0?0:z - 1, nz = dz>0?z + 1:z, az = z + 2>=depth()?depth() - 1:z + 2; + const Tfloat + Ippp = (Tfloat)(*this)(px,py,pz,c), Icpp = (Tfloat)(*this)(x,py,pz,c), + Inpp = (Tfloat)(*this)(nx,py,pz,c), Iapp = (Tfloat)(*this)(ax,py,pz,c), + Ipp = Icpp + 0.5f*(dx*(-Ippp + Inpp) + dx*dx*(2*Ippp - 5*Icpp + 4*Inpp - Iapp) + + dx*dx*dx*(-Ippp + 3*Icpp - 3*Inpp + Iapp)), + Ipcp = (Tfloat)(*this)(px,y,pz,c), Iccp = (Tfloat)(*this)(x, y,pz,c), + Incp = (Tfloat)(*this)(nx,y,pz,c), Iacp = (Tfloat)(*this)(ax,y,pz,c), + Icp = Iccp + 0.5f*(dx*(-Ipcp + Incp) + dx*dx*(2*Ipcp - 5*Iccp + 4*Incp - Iacp) + + dx*dx*dx*(-Ipcp + 3*Iccp - 3*Incp + Iacp)), + Ipnp = (Tfloat)(*this)(px,ny,pz,c), Icnp = (Tfloat)(*this)(x,ny,pz,c), + Innp = (Tfloat)(*this)(nx,ny,pz,c), Ianp = (Tfloat)(*this)(ax,ny,pz,c), + Inp = Icnp + 0.5f*(dx*(-Ipnp + Innp) + dx*dx*(2*Ipnp - 5*Icnp + 4*Innp - Ianp) + + dx*dx*dx*(-Ipnp + 3*Icnp - 3*Innp + Ianp)), + Ipap = (Tfloat)(*this)(px,ay,pz,c), Icap = (Tfloat)(*this)(x,ay,pz,c), + Inap = (Tfloat)(*this)(nx,ay,pz,c), Iaap = (Tfloat)(*this)(ax,ay,pz,c), + Iap = Icap + 0.5f*(dx*(-Ipap + Inap) + dx*dx*(2*Ipap - 5*Icap + 4*Inap - Iaap) + + dx*dx*dx*(-Ipap + 3*Icap - 3*Inap + Iaap)), + Ip = Icp + 0.5f*(dy*(-Ipp + Inp) + dy*dy*(2*Ipp - 5*Icp + 4*Inp - Iap) + + dy*dy*dy*(-Ipp + 3*Icp - 3*Inp + Iap)), + Ippc = (Tfloat)(*this)(px,py,z,c), Icpc = (Tfloat)(*this)(x,py,z,c), + Inpc = (Tfloat)(*this)(nx,py,z,c), Iapc = (Tfloat)(*this)(ax,py,z,c), + Ipc = Icpc + 0.5f*(dx*(-Ippc + Inpc) + dx*dx*(2*Ippc - 5*Icpc + 4*Inpc - Iapc) + + dx*dx*dx*(-Ippc + 3*Icpc - 3*Inpc + Iapc)), + Ipcc = (Tfloat)(*this)(px,y,z,c), Iccc = (Tfloat)(*this)(x, y,z,c), + Incc = (Tfloat)(*this)(nx,y,z,c), Iacc = (Tfloat)(*this)(ax,y,z,c), + Icc = Iccc + 0.5f*(dx*(-Ipcc + Incc) + dx*dx*(2*Ipcc - 5*Iccc + 4*Incc - Iacc) + + dx*dx*dx*(-Ipcc + 3*Iccc - 3*Incc + Iacc)), + Ipnc = (Tfloat)(*this)(px,ny,z,c), Icnc = (Tfloat)(*this)(x,ny,z,c), + Innc = (Tfloat)(*this)(nx,ny,z,c), Ianc = (Tfloat)(*this)(ax,ny,z,c), + Inc = Icnc + 0.5f*(dx*(-Ipnc + Innc) + dx*dx*(2*Ipnc - 5*Icnc + 4*Innc - Ianc) + + dx*dx*dx*(-Ipnc + 3*Icnc - 3*Innc + Ianc)), + Ipac = (Tfloat)(*this)(px,ay,z,c), Icac = (Tfloat)(*this)(x,ay,z,c), + Inac = (Tfloat)(*this)(nx,ay,z,c), Iaac = (Tfloat)(*this)(ax,ay,z,c), + Iac = Icac + 0.5f*(dx*(-Ipac + Inac) + dx*dx*(2*Ipac - 5*Icac + 4*Inac - Iaac) + + dx*dx*dx*(-Ipac + 3*Icac - 3*Inac + Iaac)), + Ic = Icc + 0.5f*(dy*(-Ipc + Inc) + dy*dy*(2*Ipc - 5*Icc + 4*Inc - Iac) + + dy*dy*dy*(-Ipc + 3*Icc - 3*Inc + Iac)), + Ippn = (Tfloat)(*this)(px,py,nz,c), Icpn = (Tfloat)(*this)(x,py,nz,c), + Inpn = (Tfloat)(*this)(nx,py,nz,c), Iapn = (Tfloat)(*this)(ax,py,nz,c), + Ipn = Icpn + 0.5f*(dx*(-Ippn + Inpn) + dx*dx*(2*Ippn - 5*Icpn + 4*Inpn - Iapn) + + dx*dx*dx*(-Ippn + 3*Icpn - 3*Inpn + Iapn)), + Ipcn = (Tfloat)(*this)(px,y,nz,c), Iccn = (Tfloat)(*this)(x, y,nz,c), + Incn = (Tfloat)(*this)(nx,y,nz,c), Iacn = (Tfloat)(*this)(ax,y,nz,c), + Icn = Iccn + 0.5f*(dx*(-Ipcn + Incn) + dx*dx*(2*Ipcn - 5*Iccn + 4*Incn - Iacn) + + dx*dx*dx*(-Ipcn + 3*Iccn - 3*Incn + Iacn)), + Ipnn = (Tfloat)(*this)(px,ny,nz,c), Icnn = (Tfloat)(*this)(x,ny,nz,c), + Innn = (Tfloat)(*this)(nx,ny,nz,c), Iann = (Tfloat)(*this)(ax,ny,nz,c), + Inn = Icnn + 0.5f*(dx*(-Ipnn + Innn) + dx*dx*(2*Ipnn - 5*Icnn + 4*Innn - Iann) + + dx*dx*dx*(-Ipnn + 3*Icnn - 3*Innn + Iann)), + Ipan = (Tfloat)(*this)(px,ay,nz,c), Ican = (Tfloat)(*this)(x,ay,nz,c), + Inan = (Tfloat)(*this)(nx,ay,nz,c), Iaan = (Tfloat)(*this)(ax,ay,nz,c), + Ian = Ican + 0.5f*(dx*(-Ipan + Inan) + dx*dx*(2*Ipan - 5*Ican + 4*Inan - Iaan) + + dx*dx*dx*(-Ipan + 3*Ican - 3*Inan + Iaan)), + In = Icn + 0.5f*(dy*(-Ipn + Inn) + dy*dy*(2*Ipn - 5*Icn + 4*Inn - Ian) + + dy*dy*dy*(-Ipn + 3*Icn - 3*Inn + Ian)), + Ippa = (Tfloat)(*this)(px,py,az,c), Icpa = (Tfloat)(*this)(x,py,az,c), + Inpa = (Tfloat)(*this)(nx,py,az,c), Iapa = (Tfloat)(*this)(ax,py,az,c), + Ipa = Icpa + 0.5f*(dx*(-Ippa + Inpa) + dx*dx*(2*Ippa - 5*Icpa + 4*Inpa - Iapa) + + dx*dx*dx*(-Ippa + 3*Icpa - 3*Inpa + Iapa)), + Ipca = (Tfloat)(*this)(px,y,az,c), Icca = (Tfloat)(*this)(x, y,az,c), + Inca = (Tfloat)(*this)(nx,y,az,c), Iaca = (Tfloat)(*this)(ax,y,az,c), + Ica = Icca + 0.5f*(dx*(-Ipca + Inca) + dx*dx*(2*Ipca - 5*Icca + 4*Inca - Iaca) + + dx*dx*dx*(-Ipca + 3*Icca - 3*Inca + Iaca)), + Ipna = (Tfloat)(*this)(px,ny,az,c), Icna = (Tfloat)(*this)(x,ny,az,c), + Inna = (Tfloat)(*this)(nx,ny,az,c), Iana = (Tfloat)(*this)(ax,ny,az,c), + Ina = Icna + 0.5f*(dx*(-Ipna + Inna) + dx*dx*(2*Ipna - 5*Icna + 4*Inna - Iana) + + dx*dx*dx*(-Ipna + 3*Icna - 3*Inna + Iana)), + Ipaa = (Tfloat)(*this)(px,ay,az,c), Icaa = (Tfloat)(*this)(x,ay,az,c), + Inaa = (Tfloat)(*this)(nx,ay,az,c), Iaaa = (Tfloat)(*this)(ax,ay,az,c), + Iaa = Icaa + 0.5f*(dx*(-Ipaa + Inaa) + dx*dx*(2*Ipaa - 5*Icaa + 4*Inaa - Iaaa) + + dx*dx*dx*(-Ipaa + 3*Icaa - 3*Inaa + Iaaa)), + Ia = Ica + 0.5f*(dy*(-Ipa + Ina) + dy*dy*(2*Ipa - 5*Ica + 4*Ina - Iaa) + + dy*dy*dy*(-Ipa + 3*Ica - 3*Ina + Iaa)); + return Ic + 0.5f*(dz*(-Ip + In) + dz*dz*(2*Ip - 5*Ic + 4*In - Ia) + dz*dz*dz*(-Ip + 3*Ic - 3*In + Ia)); + } + + //! Return damped pixel value, using cubic interpolation and Neumann boundary conditions for the XYZ-coordinates. + /** + Similar to cubic_atXYZ(float,float,float,int) const, except that you can specify the authorized minimum and + maximum of the returned value. + **/ + Tfloat cubic_atXYZ(const float fx, const float fy, const float fz, const int c, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = cubic_atXYZ(fx,fy,fz,c); + return valmax_value?max_value:val; + } + + Tfloat _cubic_atXYZ(const float fx, const float fy, const float fz, const int c, + const Tfloat min_value, const Tfloat max_value) const { + const Tfloat val = _cubic_atXYZ(fx,fy,fz,c); + return valmax_value?max_value:val; + } + + //! Set pixel value, using linear interpolation for the X-coordinates. + /** + Set pixel value at specified coordinates (\c fx,\c y,\c z,\c c) in the image instance, in a way that + the value is spread amongst several neighbors if the pixel coordinates are float-valued. + \param value Pixel value to set. + \param fx X-coordinate of the pixel value (float-valued). + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param is_added Tells if the pixel value is added to (\c true), or simply replace (\c false) the current image + pixel(s). + \return A reference to the current image instance. + \note + - Calling this method with out-of-bounds coordinates does nothing. + **/ + CImg& set_linear_atX(const T& value, const float fx, const int y=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1; + const float + dx = fx - x; + if (y>=0 && y=0 && z=0 && c=0 && x=0 && nx& set_linear_atXY(const T& value, const float fx, const float fy=0, const int z=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1; + const float + dx = fx - x, + dy = fy - y; + if (z>=0 && z=0 && c=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx& set_linear_atXYZ(const T& value, const float fx, const float fy=0, const float fz=0, const int c=0, + const bool is_added=false) { + const int + x = (int)fx - (fx>=0?0:1), nx = x + 1, + y = (int)fy - (fy>=0?0:1), ny = y + 1, + z = (int)fz - (fz>=0?0:1), nz = z + 1; + const float + dx = fx - x, + dy = fy - y, + dz = fz - z; + if (c>=0 && c=0 && z=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx=0 && nz=0 && y=0 && x=0 && nx=0 && ny=0 && x=0 && nx image whose buffer data() is a \c char* string describing the list of all pixel values + of the image instance (written in base 10), separated by specified \c separator character. + \param separator A \c char character which specifies the separator between values in the returned C-string. + \param max_size Maximum size of the returned image. + \param format For float-values, tell the printf format used to generate the ascii representation of the numbers. + (or \c 0 for default representation). + \note + - The returned image is never empty. + - For an empty image instance, the returned string is "". + - If \c max_size is equal to \c 0, there are no limits on the size of the returned string. + - Otherwise, if the maximum number of string characters is exceeded, the value string is cut off + and terminated by character \c '\0'. In that case, the returned image size is max_size + 1. + **/ + CImg value_string(const char separator=',', const unsigned int max_size=0, + const char *const format=0) const { + if (is_empty()) return CImg::string(""); + CImgList items; + CImg s_item(256); *s_item = 0; + const T *ptrs = _data; + unsigned int string_size = 0; + const char *const _format = format?format:cimg::type::format(); + for (ulongT off = 0, siz = size(); off::format(*(ptrs++))); + CImg item(s_item._data,printed_size); + item[printed_size - 1] = separator; + item.move_to(items); + if (max_size) string_size+=printed_size; + } + CImg res; + (items>'x').move_to(res); + if (max_size && res._width>max_size) res.crop(0,max_size); + res.back() = 0; + return res; + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Test shared state of the pixel buffer. + /** + Return \c true if image instance has a shared memory buffer, and \c false otherwise. + \note + - A shared image do not own his pixel buffer data() and will not deallocate it on destruction. + - Most of the time, a \c CImg image instance will \e not be shared. + - A shared image can only be obtained by a limited set of constructors and methods (see list below). + **/ + bool is_shared() const { + return _is_shared; + } + + //! Test if image instance is empty. + /** + Return \c true, if image instance is empty, i.e. does \e not contain any pixel values, has dimensions + \c 0 x \c 0 x \c 0 x \c 0 and a pixel buffer pointer set to \c 0 (null pointer), and \c false otherwise. + **/ + bool is_empty() const { + return !(_data && _width && _height && _depth && _spectrum); + } + + //! Test if image instance contains a 'inf' value. + /** + Return \c true, if image instance contains a 'inf' value, and \c false otherwise. + **/ + bool is_inf() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_inf((float)*p)) return true; + return false; + } + + //! Test if image instance contains a NaN value. + /** + Return \c true, if image instance contains a NaN value, and \c false otherwise. + **/ + bool is_nan() const { + if (cimg::type::is_float()) cimg_for(*this,p,T) if (cimg::type::is_nan((float)*p)) return true; + return false; + } + + //! Test if image width is equal to specified value. + bool is_sameX(const unsigned int size_x) const { + return _width==size_x; + } + + //! Test if image width is equal to specified value. + template + bool is_sameX(const CImg& img) const { + return is_sameX(img._width); + } + + //! Test if image width is equal to specified value. + bool is_sameX(const CImgDisplay& disp) const { + return is_sameX(disp._width); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const unsigned int size_y) const { + return _height==size_y; + } + + //! Test if image height is equal to specified value. + template + bool is_sameY(const CImg& img) const { + return is_sameY(img._height); + } + + //! Test if image height is equal to specified value. + bool is_sameY(const CImgDisplay& disp) const { + return is_sameY(disp._height); + } + + //! Test if image depth is equal to specified value. + bool is_sameZ(const unsigned int size_z) const { + return _depth==size_z; + } + + //! Test if image depth is equal to specified value. + template + bool is_sameZ(const CImg& img) const { + return is_sameZ(img._depth); + } + + //! Test if image spectrum is equal to specified value. + bool is_sameC(const unsigned int size_c) const { + return _spectrum==size_c; + } + + //! Test if image spectrum is equal to specified value. + template + bool is_sameC(const CImg& img) const { + return is_sameC(img._spectrum); + } + + //! Test if image width and height are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameY(unsigned int) const are both verified. + **/ + bool is_sameXY(const unsigned int size_x, const unsigned int size_y) const { + return _width==size_x && _height==size_y; + } + + //! Test if image width and height are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameY(const CImg&) const are both verified. + **/ + template + bool is_sameXY(const CImg& img) const { + return is_sameXY(img._width,img._height); + } + + //! Test if image width and height are the same as that of an existing display window. + /** + Test if is_sameX(const CImgDisplay&) const and is_sameY(const CImgDisplay&) const are both verified. + **/ + bool is_sameXY(const CImgDisplay& disp) const { + return is_sameXY(disp._width,disp._height); + } + + //! Test if image width and depth are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXZ(const unsigned int size_x, const unsigned int size_z) const { + return _width==size_x && _depth==size_z; + } + + //! Test if image width and depth are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXZ(const CImg& img) const { + return is_sameXZ(img._width,img._depth); + } + + //! Test if image width and spectrum are equal to specified values. + /** + Test if is_sameX(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXC(const unsigned int size_x, const unsigned int size_c) const { + return _width==size_x && _spectrum==size_c; + } + + //! Test if image width and spectrum are the same as that of another image. + /** + Test if is_sameX(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXC(const CImg& img) const { + return is_sameXC(img._width,img._spectrum); + } + + //! Test if image height and depth are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameYZ(const unsigned int size_y, const unsigned int size_z) const { + return _height==size_y && _depth==size_z; + } + + //! Test if image height and depth are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameYZ(const CImg& img) const { + return is_sameYZ(img._height,img._depth); + } + + //! Test if image height and spectrum are equal to specified values. + /** + Test if is_sameY(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYC(const unsigned int size_y, const unsigned int size_c) const { + return _height==size_y && _spectrum==size_c; + } + + //! Test if image height and spectrum are the same as that of another image. + /** + Test if is_sameY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYC(const CImg& img) const { + return is_sameYC(img._height,img._spectrum); + } + + //! Test if image depth and spectrum are equal to specified values. + /** + Test if is_sameZ(unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameZC(const unsigned int size_z, const unsigned int size_c) const { + return _depth==size_z && _spectrum==size_c; + } + + //! Test if image depth and spectrum are the same as that of another image. + /** + Test if is_sameZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameZC(const CImg& img) const { + return is_sameZC(img._depth,img._spectrum); + } + + //! Test if image width, height and depth are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameZ(unsigned int) const are both verified. + **/ + bool is_sameXYZ(const unsigned int size_x, const unsigned int size_y, const unsigned int size_z) const { + return is_sameXY(size_x,size_y) && _depth==size_z; + } + + //! Test if image width, height and depth are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameZ(const CImg&) const are both verified. + **/ + template + bool is_sameXYZ(const CImg& img) const { + return is_sameXYZ(img._width,img._height,img._depth); + } + + //! Test if image width, height and spectrum are equal to specified values. + /** + Test if is_sameXY(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXYC(const unsigned int size_x, const unsigned int size_y, const unsigned int size_c) const { + return is_sameXY(size_x,size_y) && _spectrum==size_c; + } + + //! Test if image width, height and spectrum are the same as that of another image. + /** + Test if is_sameXY(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYC(const CImg& img) const { + return is_sameXYC(img._width,img._height,img._spectrum); + } + + //! Test if image width, depth and spectrum are equal to specified values. + /** + Test if is_sameXZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameXZC(const unsigned int size_x, const unsigned int size_z, const unsigned int size_c) const { + return is_sameXZ(size_x,size_z) && _spectrum==size_c; + } + + //! Test if image width, depth and spectrum are the same as that of another image. + /** + Test if is_sameXZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXZC(const CImg& img) const { + return is_sameXZC(img._width,img._depth,img._spectrum); + } + + //! Test if image height, depth and spectrum are equal to specified values. + /** + Test if is_sameYZ(unsigned int,unsigned int) const and is_sameC(unsigned int) const are both verified. + **/ + bool is_sameYZC(const unsigned int size_y, const unsigned int size_z, const unsigned int size_c) const { + return is_sameYZ(size_y,size_z) && _spectrum==size_c; + } + + //! Test if image height, depth and spectrum are the same as that of another image. + /** + Test if is_sameYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameYZC(const CImg& img) const { + return is_sameYZC(img._height,img._depth,img._spectrum); + } + + //! Test if image width, height, depth and spectrum are equal to specified values. + /** + Test if is_sameXYZ(unsigned int,unsigned int,unsigned int) const and is_sameC(unsigned int) const are both + verified. + **/ + bool is_sameXYZC(const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c) const { + return is_sameXYZ(size_x,size_y,size_z) && _spectrum==size_c; + } + + //! Test if image width, height, depth and spectrum are the same as that of another image. + /** + Test if is_sameXYZ(const CImg&) const and is_sameC(const CImg&) const are both verified. + **/ + template + bool is_sameXYZC(const CImg& img) const { + return is_sameXYZC(img._width,img._height,img._depth,img._spectrum); + } + + //! Test if specified coordinates are inside image bounds. + /** + Return \c true if pixel located at (\c x,\c y,\c z,\c c) is inside bounds of the image instance, + and \c false otherwise. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note + - Return \c true only if all these conditions are verified: + - The image instance is \e not empty. + - 0<=x<=\ref width() - 1. + - 0<=y<=\ref height() - 1. + - 0<=z<=\ref depth() - 1. + - 0<=c<=\ref spectrum() - 1. + **/ + bool containsXYZC(const int x, const int y=0, const int z=0, const int c=0) const { + return !is_empty() && x>=0 && x=0 && y=0 && z=0 && c img(100,100,1,3); // Construct a 100x100 RGB color image. + const unsigned long offset = 1249; // Offset to the pixel (49,12,0,0). + unsigned int x,y,z,c; + if (img.contains(img[offset],x,y,z,c)) { // Convert offset to (x,y,z,c) coordinates. + std::printf("Offset %u refers to pixel located at (%u,%u,%u,%u).\n", + offset,x,y,z,c); + } + \endcode + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z, t& c) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = (ulongT)(ppixel - _data); + const ulongT nc = off/whd; + off%=whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; c = (t)nc; + return true; + } + + //! Test if pixel value is inside image bounds and get its X,Y and Z-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X,Y and Z-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y, t& z) const { + const ulongT wh = (ulongT)_width*_height, whd = wh*_depth, siz = whd*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((ulongT)(ppixel - _data))%whd; + const ulongT nz = off/wh; + off%=wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; z = (t)nz; + return true; + } + + //! Test if pixel value is inside image bounds and get its X and Y-coordinates. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X and Y-coordinates are set. + **/ + template + bool contains(const T& pixel, t& x, t& y) const { + const ulongT wh = (ulongT)_width*_height, siz = wh*_depth*_spectrum; + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + siz) return false; + ulongT off = ((unsigned int)(ppixel - _data))%wh; + const ulongT ny = off/_width, nx = off%_width; + x = (t)nx; y = (t)ny; + return true; + } + + //! Test if pixel value is inside image bounds and get its X-coordinate. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that only the X-coordinate is set. + **/ + template + bool contains(const T& pixel, t& x) const { + const T *const ppixel = &pixel; + if (is_empty() || ppixel<_data || ppixel>=_data + size()) return false; + x = (t)(((ulongT)(ppixel - _data))%_width); + return true; + } + + //! Test if pixel value is inside image bounds. + /** + Similar to contains(const T&,t&,t&,t&,t&) const, except that no pixel coordinates are set. + **/ + bool contains(const T& pixel) const { + const T *const ppixel = &pixel; + return !is_empty() && ppixel>=_data && ppixel<_data + size(); + } + + //! Test if pixel buffers of instance and input images overlap. + /** + Return \c true, if pixel buffers attached to image instance and input image \c img overlap, + and \c false otherwise. + \param img Input image to compare with. + \note + - Buffer overlapping may happen when manipulating \e shared images. + - If two image buffers overlap, operating on one of the image will probably modify the other one. + - Most of the time, \c CImg instances are \e non-shared and do not overlap between each others. + \par Example + \code + const CImg + img1("reference.jpg"), // Load RGB-color image. + img2 = img1.get_shared_channel(1); // Get shared version of the green channel. + if (img1.is_overlapped(img2)) { // Test succeeds, 'img1' and 'img2' overlaps. + std::printf("Buffers overlap!\n"); + } + \endcode + **/ + template + bool is_overlapped(const CImg& img) const { + const ulongT csiz = size(), isiz = img.size(); + return !((void*)(_data + csiz)<=(void*)img._data || (void*)_data>=(void*)(img._data + isiz)); + } + + //! Test if the set {\c *this,\c primitives,\c colors,\c opacities} defines a valid 3d object. + /** + Return \c true is the 3d object represented by the set {\c *this,\c primitives,\c colors,\c opacities} defines a + valid 3d object, and \c false otherwise. The vertex coordinates are defined by the instance image. + \param primitives List of primitives of the 3d object. + \param colors List of colors of the 3d object. + \param opacities List (or image) of opacities of the 3d object. + \param full_check Tells if full checking of the 3d object must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_checking to \c false to speed-up the 3d object checking. In this case, only the size of + each 3d object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + template + bool is_object3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true, + char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check consistency for the particular case of an empty 3d object. + if (is_empty()) { + if (primitives || colors || opacities) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) defines no vertices but %u primitives, " + "%u colors and %lu opacities", + _width,primitives._width,primitives._width, + colors._width,(unsigned long)opacities.size()); + return false; + } + return true; + } + + // Check consistency of vertices. + if (_height!=3 || _depth>1 || _spectrum>1) { // Check vertices dimensions. + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) has invalid vertex dimensions (%u,%u,%u,%u)", + _width,primitives._width,_width,_height,_depth,_spectrum); + return false; + } + if (colors._width>primitives._width + 1) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) defines %u colors", + _width,primitives._width,colors._width); + return false; + } + if (opacities.size()>primitives._width) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) defines %lu opacities", + _width,primitives._width,(unsigned long)opacities.size()); + return false; + } + if (!full_check) return true; + + // Check consistency of primitives. + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + const unsigned int psiz = (unsigned int)primitive.size(); + switch (psiz) { + case 1 : { // Point. + const unsigned int i0 = (unsigned int)primitive(0); + if (i0>=_width) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) refers to invalid vertex indice %u in " + "point primitive [%u]", + _width,primitives._width,i0,l); + return false; + } + } break; + case 5 : { // Sphere. + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 2 : // Segment. + case 6 : { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + if (i0>=_width || i1>=_width) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + _width,primitives._width,i0,i1,l); + return false; + } + } break; + case 3 : // Triangle. + case 9 : { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + if (i0>=_width || i1>=_width || i2>=_width) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + _width,primitives._width,i0,i1,i2,l); + return false; + } + } break; + case 4 : // Quadrangle. + case 12 : { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + if (i0>=_width || i1>=_width || i2>=_width || i3>=_width) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + _width,primitives._width,i0,i1,i2,i3,l); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) defines an invalid primitive [%u] of size %u", + _width,primitives._width,l,(unsigned int)psiz); + return false; + } + } + + // Check consistency of colors. + cimglist_for(colors,c) { + const CImg& color = colors[c]; + if (!color) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) defines no color for primitive [%u]", + _width,primitives._width,c); + return false; + } + } + + // Check consistency of light texture. + if (colors._width>primitives._width) { + const CImg &light = colors.back(); + if (!light || light._depth>1) { + if (error_message) cimg_sprintf(error_message, + "3d object (%u,%u) defines an invalid light texture (%u,%u,%u,%u)", + _width,primitives._width,light._width, + light._height,light._depth,light._spectrum); + return false; + } + } + + return true; + } + + //! Test if image instance represents a valid serialization of a 3d object. + /** + Return \c true if the image instance represents a valid serialization of a 3d object, and \c false otherwise. + \param full_check Tells if full checking of the instance must be performed. + \param[out] error_message C-string to contain the error message, if the test does not succeed. + \note + - Set \c full_check to \c false to speed-up the 3d object checking. In this case, only the size of + each 3d object component is checked. + - Size of the string \c error_message should be at least 128-bytes long, to be able to contain the error message. + **/ + bool is_CImg3d(const bool full_check=true, char *const error_message=0) const { + if (error_message) *error_message = 0; + + // Check instance dimension and header. + if (_width!=1 || _height<8 || _depth!=1 || _spectrum!=1) { + if (error_message) cimg_sprintf(error_message, + "CImg3d has invalid dimensions (%u,%u,%u,%u)", + _width,_height,_depth,_spectrum); + return false; + } + const T *ptrs = _data, *const ptre = end(); + if (!_is_CImg3d(*(ptrs++),'C') || !_is_CImg3d(*(ptrs++),'I') || !_is_CImg3d(*(ptrs++),'m') || + !_is_CImg3d(*(ptrs++),'g') || !_is_CImg3d(*(ptrs++),'3') || !_is_CImg3d(*(ptrs++),'d')) { + if (error_message) cimg_sprintf(error_message, + "CImg3d header not found"); + return false; + } + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + + // Check consistency of number of vertices / primitives. + if (!full_check) { + const ulongT minimal_size = 8UL + 3*nb_points + 6*nb_primitives; + if (_data + minimal_size>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has only %lu values, while at least %lu values were expected", + nb_points,nb_primitives,size(),minimal_size); + return false; + } + } + + // Check consistency of vertex data. + if (!nb_points) { + if (nb_primitives) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no vertices but %u primitives", + nb_points,nb_primitives,nb_primitives); + return false; + } + if (ptrs!=ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) is an empty object but contains %u value%s " + "more than expected", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs),(ptre - ptrs)>1?"s":""); + return false; + } + return true; + } + if (ptrs + 3*nb_points>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines only %u vertices data", + nb_points,nb_primitives,(unsigned int)(ptre - ptrs)/3); + return false; + } + ptrs+=3*nb_points; + + // Check consistency of primitive data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines %u vertices but no primitive", + nb_points,nb_primitives,nb_points); + return false; + } + + if (!full_check) return true; + + for (unsigned int p = 0; p=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indice %u in point primitive [%u]", + nb_points,nb_primitives,i0,p); + return false; + } + } break; + case 5 : { // Sphere. + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + ptrs+=3; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "sphere primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 2 : case 6 : { // Segment. + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==6) ptrs+=4; + if (i0>=nb_points || i1>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u) in " + "segment primitive [%u]", + nb_points,nb_primitives,i0,i1,p); + return false; + } + } break; + case 3 : case 9 : { // Triangle. + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==9) ptrs+=6; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u) in " + "triangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,p); + return false; + } + } break; + case 4 : case 12 : { // Quadrangle. + const unsigned int + i0 = cimg::float2uint((float)*(ptrs++)), + i1 = cimg::float2uint((float)*(ptrs++)), + i2 = cimg::float2uint((float)*(ptrs++)), + i3 = cimg::float2uint((float)*(ptrs++)); + if (nb_inds==12) ptrs+=8; + if (i0>=nb_points || i1>=nb_points || i2>=nb_points || i3>=nb_points) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid vertex indices (%u,%u,%u,%u) in " + "quadrangle primitive [%u]", + nb_points,nb_primitives,i0,i1,i2,i3,p); + return false; + } + } break; + default : + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines an invalid primitive [%u] of size %u", + nb_points,nb_primitives,p,nb_inds); + return false; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete primitive data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,p,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of color data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no color/texture data", + nb_points,nb_primitives); + return false; + } + for (unsigned int c = 0; c=c) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared sprite/texture indice %u " + "for primitive [%u]", + nb_points,nb_primitives,w,c); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete color/texture data for primitive [%u], " + "%u values missing", + nb_points,nb_primitives,c,(unsigned int)(ptrs - ptre)); + return false; + } + } + + // Check consistency of opacity data. + if (ptrs==ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) defines no opacity data", + nb_points,nb_primitives); + return false; + } + for (unsigned int o = 0; o=o) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) refers to invalid shared opacity indice %u " + "for primitive [%u]", + nb_points,nb_primitives,w,o); + return false; + } + } else ptrs+=w*h*s; + } + if (ptrs>ptre) { + if (error_message) cimg_sprintf(error_message, + "CImg3d (%u,%u) has incomplete opacity data for primitive [%u]", + nb_points,nb_primitives,o); + return false; + } + } + + // Check end of data. + if (ptrs1?"s":""); + return false; + } + return true; + } + + static bool _is_CImg3d(const T val, const char c) { + return val>=(T)c && val<(T)(c + 1); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + // Define the math formula parser/compiler and expression evaluator. + struct _cimg_math_parser { + CImg mem; + CImg memtype; + CImgList _code, &code; + CImg opcode; + const CImg *p_code_begin, *p_code_end, *p_code; + const CImg *const p_break; + + CImg expr, pexpr; + const CImg& imgin; + const CImgList& listin; + CImg &imgout; + CImgList& listout; + + CImg _img_stats, &img_stats, constcache_vals; + CImgList _list_stats, &list_stats, _list_median, &list_median; + CImg mem_img_stats, constcache_inds; + + CImg level, variable_pos, reserved_label; + CImgList variable_def, macro_def, macro_body; + CImgList macro_body_is_string; + char *user_macro; + + 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; + typedef double (*mp_func)(_cimg_math_parser&); + +#define _cimg_mp_is_constant(arg) (memtype[arg]==1) // Is constant value? +#define _cimg_mp_is_scalar(arg) (memtype[arg]<2) // Is scalar value? +#define _cimg_mp_is_comp(arg) (!memtype[arg]) // Is computation value? +#define _cimg_mp_is_variable(arg) (memtype[arg]==-1) // Is scalar variable? +#define _cimg_mp_is_vector(arg) (memtype[arg]>1) // Is vector? +#define _cimg_mp_vector_size(arg) (_cimg_mp_is_scalar(arg)?0U:(unsigned int)memtype[arg] - 1) // Vector size +#define _cimg_mp_calling_function calling_function_s()._data +#define _cimg_mp_op(s) s_op = s; ss_op = ss +#define _cimg_mp_check_type(arg,n_arg,mode,N) check_type(arg,n_arg,mode,N,ss,se,saved_char) +#define _cimg_mp_check_constant(arg,n_arg,mode) check_constant(arg,n_arg,mode,ss,se,saved_char) +#define _cimg_mp_check_matrix_square(arg,n_arg) check_matrix_square(arg,n_arg,ss,se,saved_char) +#define _cimg_mp_check_vector0(dim) check_vector0(dim,ss,se,saved_char) +#define _cimg_mp_check_list(is_out) check_list(is_out,ss,se,saved_char) +#define _cimg_mp_defunc(mp) (*(mp_func)(*(mp).opcode))(mp) +#define _cimg_mp_return(x) { *se = saved_char; s_op = previous_s_op; ss_op = previous_ss_op; return x; } +#define _cimg_mp_constant(val) _cimg_mp_return(constant((double)(val))) +#define _cimg_mp_scalar0(op) _cimg_mp_return(scalar0(op)) +#define _cimg_mp_scalar1(op,i1) _cimg_mp_return(scalar1(op,i1)) +#define _cimg_mp_scalar2(op,i1,i2) _cimg_mp_return(scalar2(op,i1,i2)) +#define _cimg_mp_scalar3(op,i1,i2,i3) _cimg_mp_return(scalar3(op,i1,i2,i3)) +#define _cimg_mp_scalar4(op,i1,i2,i3,i4) _cimg_mp_return(scalar4(op,i1,i2,i3,i4)) +#define _cimg_mp_scalar5(op,i1,i2,i3,i4,i5) _cimg_mp_return(scalar5(op,i1,i2,i3,i4,i5)) +#define _cimg_mp_scalar6(op,i1,i2,i3,i4,i5,i6) _cimg_mp_return(scalar6(op,i1,i2,i3,i4,i5,i6)) +#define _cimg_mp_scalar7(op,i1,i2,i3,i4,i5,i6,i7) _cimg_mp_return(scalar7(op,i1,i2,i3,i4,i5,i6,i7)) +#define _cimg_mp_vector1_v(op,i1) _cimg_mp_return(vector1_v(op,i1)) +#define _cimg_mp_vector2_sv(op,i1,i2) _cimg_mp_return(vector2_sv(op,i1,i2)) +#define _cimg_mp_vector2_vs(op,i1,i2) _cimg_mp_return(vector2_vs(op,i1,i2)) +#define _cimg_mp_vector2_vv(op,i1,i2) _cimg_mp_return(vector2_vv(op,i1,i2)) +#define _cimg_mp_vector3_vss(op,i1,i2,i3) _cimg_mp_return(vector3_vss(op,i1,i2,i3)) + + // Constructors. + _cimg_math_parser(const char *const expression, const char *const funcname=0, + const CImg& img_input=CImg::const_empty(), CImg *const img_output=0, + const CImgList *const list_input=0, CImgList *const list_output=0): + code(_code),p_break((CImg*)0 - 2), + imgin(img_input),listin(list_input?*list_input:CImgList::const_empty()), + imgout(img_output?*img_output:CImg::empty()),listout(list_output?*list_output:CImgList::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),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] " + "CImg<%s>::%s: Empty expression.", + pixel_type(),_cimg_mp_calling_function); + const char *_expression = expression; + while (*_expression && ((signed char)*_expression<=' ' || *_expression==';')) ++_expression; + CImg::string(_expression).move_to(expr); + char *ps = &expr.back() - 1; + while (ps>expr._data && ((signed char)*ps<=' ' || *ps==';')) --ps; + *(++ps) = 0; expr._width = (unsigned int)(ps - expr._data + 1); + + // Ease the retrieval of previous non-space characters afterwards. + pexpr.assign(expr._width); + char c, *pe = pexpr._data; + for (ps = expr._data, c = ' '; *ps; ++ps) { + if ((signed char)*ps>' ') c = *ps; else *ps = ' '; + *(pe++) = c; + } + *pe = 0; + level = get_level(expr); + + // Init constant values. +#define _cimg_mp_interpolation (reserved_label[29]!=~0U?reserved_label[29]:0) +#define _cimg_mp_boundary (reserved_label[30]!=~0U?reserved_label[30]:0) +#define _cimg_mp_slot_nan 29 +#define _cimg_mp_slot_x 30 +#define _cimg_mp_slot_y 31 +#define _cimg_mp_slot_z 32 +#define _cimg_mp_slot_c 33 + + mem.assign(96); + for (unsigned int i = 0; i<=10; ++i) mem[i] = (double)i; // mem[0-10] = 0...10 + for (unsigned int i = 1; i<=5; ++i) mem[i + 10] = -(double)i; // mem[11-15] = -1...-5 + mem[16] = 0.5; + mem[17] = 0; // thread_id + mem[18] = (double)imgin._width; // w + mem[19] = (double)imgin._height; // h + mem[20] = (double)imgin._depth; // d + mem[21] = (double)imgin._spectrum; // s + mem[22] = (double)imgin._is_shared; // r + mem[23] = (double)imgin._width*imgin._height; // wh + mem[24] = (double)imgin._width*imgin._height*imgin._depth; // whd + mem[25] = (double)imgin._width*imgin._height*imgin._depth*imgin._spectrum; // whds + mem[26] = (double)listin._width; // l + mem[27] = std::exp(1.0); // e + mem[28] = cimg::PI; // pi + mem[_cimg_mp_slot_nan] = cimg::type::nan(); // nan + + // Set value property : + // { -2 = other | -1 = variable | 0 = computation value | + // 1 = compile-time constant | N>1 = constant ptr to vector[N-1] }. + memtype.assign(mem._width,1,1,1,0); + for (unsigned int i = 0; i<_cimg_mp_slot_x; ++i) memtype[i] = 1; + memtype[17] = 0; + mempos = _cimg_mp_slot_c + 1; + variable_pos.assign(8); + + reserved_label.assign(128,1,1,1,~0U); + // reserved_label[4-28] are used to store these two-char variables: + // [0] = wh, [1] = whd, [2] = whds, [3] = pi, [4] = im, [5] = iM, [6] = ia, [7] = iv, + // [8] = is, [9] = ip, [10] = ic, [11] = xm, [12] = ym, [13] = zm, [14] = cm, [15] = xM, + // [16] = yM, [17] = zM, [18]=cM, [19]=i0...[28]=i9, [29] = interpolation, [30] = boundary + + // Compile expression into a serie of opcodes. + s_op = ""; ss_op = expr._data; + const unsigned int ind_result = compile(expr._data,expr._data + expr._width - 1,0,0); + p_code_end = code.end(); + if (!_cimg_mp_is_constant(ind_result)) { + if (_cimg_mp_is_vector(ind_result)) + CImg(&mem[ind_result] + 1,_cimg_mp_vector_size(ind_result),1,1,1,true). + fill(cimg::type::nan()); + else mem[ind_result] = cimg::type::nan(); + } + + // 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(); + expr.assign(); + pexpr.assign(); + opcode.assign(); + opcode._is_shared = true; + + // 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; + for (p_code = code._data; p_code &op = *p_code; + opcode._data = op._data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + } + } + + _cimg_math_parser(): + code(_code),p_code_begin(0),p_code_end(0),p_break((CImg*)0 - 2), + imgin(CImg::const_empty()),listin(CImgList::const_empty()), + imgout(CImg::empty()),listout(CImgList::empty()), + img_stats(_img_stats),list_stats(_list_stats),list_median(_list_median),debug_indent(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; + } + + _cimg_math_parser(const _cimg_math_parser& mp): + 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),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(); +#endif + opcode.assign(); + opcode._is_shared = true; + } + + // Count parentheses/brackets level of each character of the expression. + CImg get_level(CImg& expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res(expr._width - 1); + unsigned int *pd = res._data; + 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?level + (mode==1): + *ps=='(' || *ps=='['?level++: + *ps==')' || *ps==']'?--level: + level); + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + if (mode) { + cimg::strellipsize(expr,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Unterminated string literal, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + expr._data); + } + if (level) { + cimg::strellipsize(expr,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Unbalanced parentheses/brackets, in expression '%s'.", + pixel_type(),_cimg_mp_calling_function, + expr._data); + } + return res; + } + + // Tell for each character of an expression if it is inside a string or not. + CImg is_inside_string(CImg& expr) const { + bool is_escaped = false, next_is_escaped = false; + unsigned int mode = 0, next_mode = 0; // { 0=normal | 1=char-string | 2=vector-string + CImg res = CImg::string(expr); + bool *pd = res._data; + for (const char *ps = expr._data; *ps; ++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++) = mode>=1 || is_escaped; + mode = next_mode; + is_escaped = next_is_escaped; + next_is_escaped = false; + } + return res; + } + + // Compilation procedure. + unsigned int compile(char *ss, char *se, const unsigned int depth, unsigned int *const p_ref) { + if (depth>256) { + cimg::strellipsize(expr,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Call stack overflow (infinite recursion?), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + (ss - 4)>expr._data?"...":"", + (ss - 4)>expr._data?ss - 4:expr._data, + se<&expr.back()?"...":""); + } + + const char *const ss0 = ss; + char c1, c2, c3, c4; + + // Simplify expression when possible. + do { + c2 = 0; + if (ssss && ((signed char)(c1 = *(se - 1))<=' ' || c1==';')) --se; + } + while (*ss=='(' && *(se - 1)==')' && std::strchr(ss,')')==se - 1) { + ++ss; --se; c2 = 1; + } + } while (c2 && ss::%s: %s%s Missing %s, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + *s_op=='F'?"argument":"item", + (ss_op - 4)>expr._data?"...":"", + (ss_op - 4)>expr._data?ss_op - 4:expr._data, + ss_op + std::strlen(ss_op)<&expr.back()?"...":""); + } + + const char *const previous_s_op = s_op, *const previous_ss_op = ss_op; + const unsigned int depth1 = depth + 1; + unsigned int pos, p1, p2, p3, arg1, arg2, arg3, arg4, arg5, arg6; + char + *const se1 = se - 1, *const se2 = se - 2, *const se3 = se - 3, + *const ss1 = ss + 1, *const ss2 = ss + 2, *const ss3 = ss + 3, *const ss4 = ss + 4, + *const ss5 = ss + 5, *const ss6 = ss + 6, *const ss7 = ss + 7, *const ss8 = ss + 8, + *s, *ps, *ns, *s0, *s1, *s2, *s3, sep = 0, end = 0; + double val, val1, val2; + mp_func op; + + // 'p_ref' is a 'unsigned int[7]' used to return a reference to an image or vector value + // linked to the returned memory slot (reference that cannot be determined at compile time). + // p_ref[0] can be { 0 = scalar (unlinked) | 1 = vector value | 2 = image value (offset) | + // 3 = image value (coordinates) | 4 = image value as a vector (offsets) | + // 5 = image value as a vector (coordinates) }. + // Depending on p_ref[0], the remaining p_ref[k] have the following meaning: + // When p_ref[0]==0, p_ref is actually unlinked. + // When p_ref[0]==1, p_ref = [ 1, vector_ind, offset ]. + // When p_ref[0]==2, p_ref = [ 2, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==3, p_ref = [ 3, image_ind (or ~0U), is_relative, x, y, z, c ]. + // When p_ref[0]==4, p_ref = [ 4, image_ind (or ~0U), is_relative, offset ]. + // When p_ref[0]==5, p_ref = [ 5, image_ind (or ~0U), is_relative, x, y, z ]. + if (p_ref) { *p_ref = 0; p_ref[1] = p_ref[2] = p_ref[3] = p_ref[4] = p_ref[5] = p_ref[6] = ~0U; } + + const char saved_char = *se; *se = 0; + const unsigned int clevel = level[ss - expr._data], clevel1 = clevel + 1; + bool is_sth, is_relative; + CImg ref; + CImgList _opcode; + CImg variable_name; + + // Look for a single value or a pre-defined variable. + int nb = cimg_sscanf(ss,"%lf%c%c",&val,&(sep=0),&(end=0)); + +#if cimg_OS==2 + // Check for +/-NaN and +/-inf as Microsoft's sscanf() version is not able + // to read those particular values. + if (!nb && (*ss=='+' || *ss=='-' || *ss=='i' || *ss=='I' || *ss=='n' || *ss=='N')) { + is_sth = true; + s = ss; + if (*s=='+') ++s; else if (*s=='-') { ++s; is_sth = false; } + if (!cimg::strcasecmp(s,"inf")) { val = cimg::type::inf(); nb = 1; } + else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type::nan(); nb = 1; } + if (nb==1 && !is_sth) val = -val; + } +#endif + if (nb==1) _cimg_mp_constant(val); + if (nb==2 && sep=='%') _cimg_mp_constant(val/100); + + if (ss1==se) switch (*ss) { // One-char variable + case 'c' : _cimg_mp_return(reserved_label['c']!=~0U?reserved_label['c']:_cimg_mp_slot_c); + case 'd' : _cimg_mp_return(reserved_label['d']!=~0U?reserved_label['d']:20); + case 'e' : _cimg_mp_return(reserved_label['e']!=~0U?reserved_label['e']:27); + case 'h' : _cimg_mp_return(reserved_label['h']!=~0U?reserved_label['h']:19); + case 'l' : _cimg_mp_return(reserved_label['l']!=~0U?reserved_label['l']:26); + case 'r' : _cimg_mp_return(reserved_label['r']!=~0U?reserved_label['r']:22); + case 's' : _cimg_mp_return(reserved_label['s']!=~0U?reserved_label['s']:21); + case 't' : _cimg_mp_return(reserved_label['t']!=~0U?reserved_label['t']:17); + case 'w' : _cimg_mp_return(reserved_label['w']!=~0U?reserved_label['w']:18); + case 'x' : _cimg_mp_return(reserved_label['x']!=~0U?reserved_label['x']:_cimg_mp_slot_x); + case 'y' : _cimg_mp_return(reserved_label['y']!=~0U?reserved_label['y']:_cimg_mp_slot_y); + case 'z' : _cimg_mp_return(reserved_label['z']!=~0U?reserved_label['z']:_cimg_mp_slot_z); + case 'u' : + if (reserved_label['u']!=~0U) _cimg_mp_return(reserved_label['u']); + _cimg_mp_scalar2(mp_u,0,1); + case 'g' : + if (reserved_label['g']!=~0U) _cimg_mp_return(reserved_label['g']); + _cimg_mp_scalar0(mp_g); + case 'i' : + if (reserved_label['i']!=~0U) _cimg_mp_return(reserved_label['i']); + _cimg_mp_scalar0(mp_i); + case 'I' : + _cimg_mp_op("Variable 'I'"); + if (reserved_label['I']!=~0U) _cimg_mp_return(reserved_label['I']); + _cimg_mp_check_vector0(imgin._spectrum); + need_input_copy = true; + pos = vector(imgin._spectrum); + CImg::vector((ulongT)mp_Joff,pos,0,0).move_to(code); + _cimg_mp_return(pos); + case 'R' : + if (reserved_label['R']!=~0U) _cimg_mp_return(reserved_label['R']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0,0,0); + case 'G' : + if (reserved_label['G']!=~0U) _cimg_mp_return(reserved_label['G']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1,0,0); + case 'B' : + if (reserved_label['B']!=~0U) _cimg_mp_return(reserved_label['B']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2,0,0); + case 'A' : + if (reserved_label['A']!=~0U) _cimg_mp_return(reserved_label['A']); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3,0,0); + } + else if (ss2==se) { // Two-chars variable + arg1 = arg2 = ~0U; + if (*ss=='w' && *ss1=='h') // wh + _cimg_mp_return(reserved_label[0]!=~0U?reserved_label[0]:23); + if (*ss=='p' && *ss1=='i') // pi + _cimg_mp_return(reserved_label[3]!=~0U?reserved_label[3]:28); + if (*ss=='i') { + if (*ss1>='0' && *ss1<='9') { // i0...i9 + pos = 19 + *ss1 - '0'; + if (reserved_label[pos]!=~0U) _cimg_mp_return(reserved_label[pos]); + need_input_copy = true; + _cimg_mp_scalar6(mp_ixyzc,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,pos - 19,0,0); + } + switch (*ss1) { + case 'm' : arg1 = 4; arg2 = 0; break; // im + case 'M' : arg1 = 5; arg2 = 1; break; // iM + case 'a' : arg1 = 6; arg2 = 2; break; // ia + case 'v' : arg1 = 7; arg2 = 3; break; // iv + case 's' : arg1 = 8; arg2 = 12; break; // is + case 'p' : arg1 = 9; arg2 = 13; break; // is + case 'c' : // ic + if (reserved_label[10]!=~0U) _cimg_mp_return(reserved_label[10]); + if (mem_img_median==~0U) mem_img_median = imgin?constant(imgin.median()):0; + _cimg_mp_return(mem_img_median); + break; + } + } + else if (*ss1=='m') switch (*ss) { + case 'x' : arg1 = 11; arg2 = 4; break; // xm + case 'y' : arg1 = 12; arg2 = 5; break; // ym + case 'z' : arg1 = 13; arg2 = 6; break; // zm + case 'c' : arg1 = 14; arg2 = 7; break; // cm + } + else if (*ss1=='M') switch (*ss) { + case 'x' : arg1 = 15; arg2 = 8; break; // xM + case 'y' : arg1 = 16; arg2 = 9; break; // yM + case 'z' : arg1 = 17; arg2 = 10; break; // zM + case 'c' : arg1 = 18; arg2 = 11; break; // cM + } + if (arg1!=~0U) { + if (reserved_label[arg1]!=~0U) _cimg_mp_return(reserved_label[arg1]); + if (!img_stats) { + img_stats.assign(1,14,1,1,0).fill(imgin.get_stats(),false); + mem_img_stats.assign(1,14,1,1,~0U); + } + if (mem_img_stats[arg2]==~0U) mem_img_stats[arg2] = constant(img_stats[arg2]); + _cimg_mp_return(mem_img_stats[arg2]); + } + } else if (ss3==se) { // Three-chars variable + if (*ss=='w' && *ss1=='h' && *ss2=='d') // whd + _cimg_mp_return(reserved_label[1]!=~0U?reserved_label[1]:24); + } else if (ss4==se) { // Four-chars variable + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='s') // whds + _cimg_mp_return(reserved_label[2]!=~0U?reserved_label[2]:25); + } + + pos = ~0U; + for (s0 = ss, s = ss1; s='i'?1:3,p2); + + if (p_ref) { + *p_ref = _cimg_mp_is_vector(arg2)?4:2; + p_ref[1] = p1; + p_ref[2] = (unsigned int)is_relative; + p_ref[3] = arg1; + if (_cimg_mp_is_vector(arg2)) + set_variable_vector(arg2); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -2; + if (p1!=~0U && _cimg_mp_is_comp(p1)) memtype[p1] = -2; + if (_cimg_mp_is_comp(arg1)) memtype[arg1] = -2; + } + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg1).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg1).move_to(code); + else if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg1).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg1).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ss1=='(' && *ve1==')') { // i/j/I/J(_#ind,_x,_y,_z,_c) = value + is_parallelizable = false; + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + } else if (s1='i'?1:3,p2); + + if (p_ref) { + *p_ref = _cimg_mp_is_vector(arg5)?5:3; + p_ref[1] = p1; + p_ref[2] = (unsigned int)is_relative; + p_ref[3] = arg1; + p_ref[4] = arg2; + p_ref[5] = arg3; + p_ref[6] = arg4; + if (_cimg_mp_is_vector(arg5)) + set_variable_vector(arg5); // Prevent from being used in further optimization + else if (_cimg_mp_is_comp(arg5)) memtype[arg5] = -2; + if (p1!=~0U && _cimg_mp_is_comp(p1)) memtype[p1] = -2; + if (_cimg_mp_is_comp(arg1)) memtype[arg1] = -2; + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -2; + if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -2; + if (_cimg_mp_is_comp(arg4)) memtype[arg4] = -2; + } + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg5); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg5,p1,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg5,p1,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg5,p1,arg1,arg2,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg5); + if (*ss>='i') + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg5,arg1,arg2,arg3,arg4).move_to(code); + else if (_cimg_mp_is_scalar(arg5)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg5,arg1,arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg5,arg1,arg2,arg3).move_to(code); + } + _cimg_mp_return(arg5); + } + } + + // Assign vector value (direct). + if (l_variable_name>3 && *ve1==']' && *ss!='[') { + s0 = ve1; while (s0>ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + is_sth = true; // is_valid_variable_name? + if (*ss>='0' && *ss<='9') is_sth = false; + else for (ns = ss; nsss) { + variable_name[s0 - ss] = 0; // Remove brackets in variable name + arg1 = ~0U; // Vector slot + arg2 = compile(++s0,ve1,depth1,0); // Index + arg3 = compile(s + 1,se,depth1,0); // Value to assign + _cimg_mp_check_type(arg3,2,1,0); + + if (variable_name[1]) { // Multi-char variable + cimglist_for(variable_def,i) if (!std::strcmp(variable_name,variable_def[i])) { + arg1 = variable_pos[i]; break; + } + } else arg1 = reserved_label[*variable_name]; // Single-char variable + if (arg1==~0U) compile(ss,s0 - 1,depth1,0); // Variable does not exist -> error + else { // Variable already exists + if (_cimg_mp_is_scalar(arg1)) compile(ss,s,depth1,0); // Variable is not a vector -> error + if (_cimg_mp_is_constant(arg2)) { // Constant index -> return corresponding variable slot directly + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_vector_size(arg1)) { + arg1+=nb + 1; + CImg::vector((ulongT)mp_copy,arg1,arg3).move_to(code); + _cimg_mp_return(arg1); + } + compile(ss,s,depth1,0); // Out-of-bounds reference -> error + } + + // Case of non-constant index -> return assigned value + linked reference + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg3)) memtype[arg3] = -2; // Prevent from being used in further optimization + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -2; + } + CImg::vector((ulongT)mp_vector_set_off,arg3,arg1,(ulongT)_cimg_mp_vector_size(arg1), + arg2,arg3). + move_to(code); + _cimg_mp_return(arg3); + } + } + } + + // Assign user-defined macro. + if (l_variable_name>2 && *ve1==')' && *ss!='(') { + s0 = ve1; while (s0>ss && *s0!='(') --s0; + is_sth = std::strncmp(variable_name,"debug(",6) && + std::strncmp(variable_name,"print(",6); // is_valid_function_name? + if (*ss>='0' && *ss<='9') is_sth = false; + else for (ns = ss; nsss) { // Looks like a valid function declaration + s0 = variable_name._data + (s0 - ss); + *s0 = 0; + s1 = variable_name._data + l_variable_name - 1; // Pointer to closing parenthesis + CImg(variable_name._data,(unsigned int)(s0 - variable_name._data + 1)).move_to(macro_def,0); + ++s; while (*s && *s<=' ') ++s; + CImg(s,(unsigned int)(se - s + 1)).move_to(macro_body,0); + + p1 = 1; // Indice of current parsed argument + for (s = s0 + 1; s<=s1; ++p1, s = ns + 1) { // Parse function arguments + if (p1>24) { + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Too much specified arguments (>24) in macro " + "definition '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + while (*s && *s<=' ') ++s; + if (*s==')' && p1==1) break; // Function has no arguments + + s2 = s; // Start of the argument name + is_sth = true; // is_valid_argument_name? + if (*s>='0' && *s<='9') is_sth = false; + else for (ns = s; ns' '; ++ns) + if (!is_varchar(*ns)) { is_sth = false; break; } + s3 = ns; // End of the argument name + while (*ns && *ns<=' ') ++ns; + if (!is_sth || s2==s3 || (*ns!=',' && ns!=s1)) { + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: %s name specified for argument %u when defining " + "macro '%s()', in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + is_sth?"Empty":"Invalid",p1, + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (ns==s1 || *ns==',') { // New argument found + *s3 = 0; + p2 = (unsigned int)(s3 - s2); // Argument length + for (ps = std::strstr(macro_body[0],s2); ps; ps = std::strstr(ps,s2)) { // Replace by arg number + if (!((ps>macro_body[0]._data && is_varchar(*(ps - 1))) || + (ps + p2macro_body[0]._data && *(ps - 1)=='#') { // Remove pre-number sign + *(ps - 1) = (char)p1; + if (ps + p26 && !std::strncmp(variable_name,"const ",6); + + s0 = variable_name._data; + if (is_const) { + s0+=6; while ((signed char)*s0<=' ') ++s0; + variable_name.resize(variable_name.end() - s0,1,1,1,0,0,1); + } + + if (*variable_name>='0' && *variable_name<='9') is_sth = false; + else for (ns = variable_name._data; *ns; ++ns) + if (!is_varchar(*ns)) { is_sth = false; break; } + + // Assign variable (direct). + if (is_sth) { + arg3 = variable_name[1]?~0U:*variable_name; // One-char variable + if (variable_name[1] && !variable_name[2]) { // Two-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + if (c1=='w' && c2=='h') arg3 = 0; // wh + else if (c1=='p' && c2=='i') arg3 = 3; // pi + else if (c1=='i') { + if (c2>='0' && c2<='9') arg3 = 19 + c2 - '0'; // i0...i9 + else if (c2=='m') arg3 = 4; // im + else if (c2=='M') arg3 = 5; // iM + else if (c2=='a') arg3 = 6; // ia + else if (c2=='v') arg3 = 7; // iv + else if (c2=='s') arg3 = 8; // is + else if (c2=='p') arg3 = 9; // ip + else if (c2=='c') arg3 = 10; // ic + } else if (c2=='m') { + if (c1=='x') arg3 = 11; // xm + else if (c1=='y') arg3 = 12; // ym + else if (c1=='z') arg3 = 13; // zm + else if (c1=='c') arg3 = 14; // cm + } else if (c2=='M') { + if (c1=='x') arg3 = 15; // xM + else if (c1=='y') arg3 = 16; // yM + else if (c1=='z') arg3 = 17; // zM + else if (c1=='c') arg3 = 18; // cM + } + } else if (variable_name[1] && variable_name[2] && !variable_name[3]) { // Three-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + if (c1=='w' && c2=='h' && c3=='d') arg3 = 1; // whd + } else if (variable_name[1] && variable_name[2] && variable_name[3] && + !variable_name[4]) { // Four-chars variable + c1 = variable_name[0]; + c2 = variable_name[1]; + c3 = variable_name[2]; + c4 = variable_name[3]; + if (c1=='w' && c2=='h' && c3=='d' && c4=='s') arg3 = 2; // whds + } else if (!std::strcmp(variable_name,"interpolation")) arg3 = 29; // interpolation + else if (!std::strcmp(variable_name,"boundary")) arg3 = 30; // boundary + + arg1 = ~0U; + arg2 = compile(s + 1,se,depth1,0); + if (is_const) _cimg_mp_check_constant(arg2,2,0); + + if (arg3!=~0U) // One-char variable, or variable in reserved_labels + arg1 = reserved_label[arg3]; + else // Multi-char variable name : check for existing variable with same name + cimglist_for(variable_def,i) + if (!std::strcmp(variable_name,variable_def[i])) { arg1 = variable_pos[i]; break; } + + if (arg1==~0U) { // Create new variable + if (_cimg_mp_is_vector(arg2)) { // Vector variable + arg1 = is_comp_vector(arg2)?arg2:vector_copy(arg2); + set_variable_vector(arg1); + } else { // Scalar variable + if (is_const) arg1 = arg2; + else { + arg1 = _cimg_mp_is_comp(arg2)?arg2:scalar1(mp_copy,arg2); + memtype[arg1] = -1; + } + } + + if (arg3!=~0U) reserved_label[arg3] = arg1; + else { + if (variable_def._width>=variable_pos._width) variable_pos.resize(-200,1,1,1,0); + variable_pos[variable_def._width] = arg1; + variable_name.move_to(variable_def); + } + + } else { // Variable already exists -> assign a new value + if (is_const || _cimg_mp_is_constant(arg1)) { + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Invalid assignment of %sconst variable '%s'%s, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"already-defined ":"non-", + variable_name._data, + !_cimg_mp_is_constant(arg1) && is_const?" as a new const variable":"", + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + _cimg_mp_check_type(arg2,2,_cimg_mp_is_vector(arg1)?3:1,_cimg_mp_vector_size(arg1)); + if (_cimg_mp_is_vector(arg1)) { // Vector + if (_cimg_mp_is_vector(arg2)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_vector_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_vector_size(arg1),arg2). + move_to(code); + } else // Scalar + CImg::vector((ulongT)mp_copy,arg1,arg2).move_to(code); + } + _cimg_mp_return(arg1); + } + + // Assign lvalue (variable name was not valid for a direct assignment). + arg1 = ~0U; + is_sth = (bool)std::strchr(variable_name,'?'); // Contains_ternary_operator? + if (is_sth) break; // Do nothing and make ternary operator prioritary over assignment + + if (l_variable_name>2 && (std::strchr(variable_name,'(') || std::strchr(variable_name,'['))) { + ref.assign(7); + arg1 = compile(ss,s,depth1,ref); // Lvalue slot + arg2 = compile(s + 1,se,depth1,0); // Value to assign + + if (*ref==1) { // Vector value (scalar): V[k] = scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)mp_vector_set_off,arg2,arg3,(ulongT)_cimg_mp_vector_size(arg3),arg4,arg2). + move_to(code); + _cimg_mp_return(arg2); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] = scalar + _cimg_mp_check_type(arg2,2,1,0); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg2,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg2,arg3).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) = scalar + _cimg_mp_check_type(arg2,2,1,0); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg2,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg2,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] = value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_s:mp_list_set_Ioff_s), + arg2,p1,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg2,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Joff_s:mp_set_Ioff_s), + arg2,arg3).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg2,arg3).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) = value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_s:mp_list_set_Ixyz_s), + arg2,p1,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg2,p1,arg3,arg4,arg5).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg2); + if (_cimg_mp_is_scalar(arg2)) + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_s:mp_set_Ixyz_s), + arg2,arg3,arg4,arg5).move_to(code); + else + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg2,arg3,arg4,arg5).move_to(code); + } + _cimg_mp_return(arg2); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V = value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + if (_cimg_mp_is_vector(arg2)) // From vector + CImg::vector((ulongT)mp_vector_copy,arg1,arg2,(ulongT)_cimg_mp_vector_size(arg1)). + move_to(code); + else // From scalar + CImg::vector((ulongT)mp_vector_init,arg1,1,(ulongT)_cimg_mp_vector_size(arg1),arg2). + move_to(code); + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s = scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)mp_copy,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + } + + // No assignment expressions match -> error + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg1!=~0U && _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // 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 (**=,//=,^^=) + _cimg_mp_op(*ps=='*'?"Operator '**='":*ps=='/'?"Operator '//='":"Operator '^^='"); + + ref.assign(7); + arg1 = compile(ss,ns,depth1,ref); // Vector slot + arg2 = compile(s + 1,se,depth1,0); // Right operand + if (*ps!='*') { + _cimg_mp_check_type(arg1,2,2,2); + _cimg_mp_check_type(arg2,2,2,2); + } + if (_cimg_mp_is_vector(arg2)) { // Complex **= complex or Matrix **= matrix + if (*ps=='*') { + if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2) + CImg::vector((ulongT)mp_complex_mul,arg1,arg1,arg2).move_to(code); + else { + _cimg_mp_check_matrix_square(arg2,2); + p3 = _cimg_mp_vector_size(arg1); + p2 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg2)); + p1 = p3/p2; + if (p1*p2!=p3) { + *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: Types of left-hand and right-hand operands " + "('%s' and '%s') do not match, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + CImg::vector((ulongT)mp_matrix_mul,arg1,arg1,arg2,p1,p2,p2).move_to(code); + } + } else if (*ps=='/') + CImg::vector((ulongT)mp_complex_div_vv,arg1,arg1,arg2).move_to(code); + else + CImg::vector((ulongT)mp_complex_pow_vv,arg1,arg1,arg2).move_to(code); + } else { // Complex **= scalar + if (*ps=='*') self_vector_s(arg1,mp_self_mul,arg2); + else if (*ps=='/') self_vector_s(arg1,mp_self_div,arg2); + else CImg::vector((ulongT)mp_complex_pow_vs,arg1,arg1,arg2).move_to(code); + } + + // Write computed value back in image if necessary. + if (*ref==4) { // Image value (vector): I/J[_#ind,off] **= value + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3).move_to(code); + } + + } else if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) **= value + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5).move_to(code); + } + } + + _cimg_mp_return(arg1); + } + + for (s = se2, ps = se3, ns = ps - 1; s>ss1; --s, --ps, --ns) // Here, ns = ps - 1 + if (*s=='=' && (*ps=='+' || *ps=='-' || *ps=='*' || *ps=='/' || *ps=='%' || + *ps=='&' || *ps=='^' || *ps=='|' || + (*ps=='>' && *ns=='>') || (*ps=='<' && *ns=='<')) && + level[s - expr._data]==clevel) { // Self-operators (+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=) + switch (*ps) { + case '+' : op = mp_self_add; _cimg_mp_op("Operator '+='"); break; + case '-' : op = mp_self_sub; _cimg_mp_op("Operator '-='"); break; + case '*' : op = mp_self_mul; _cimg_mp_op("Operator '*='"); break; + case '/' : op = mp_self_div; _cimg_mp_op("Operator '/='"); break; + case '%' : op = mp_self_modulo; _cimg_mp_op("Operator '%='"); break; + case '<' : op = mp_self_bitwise_left_shift; _cimg_mp_op("Operator '<<='"); break; + case '>' : op = mp_self_bitwise_right_shift; _cimg_mp_op("Operator '>>='"); break; + case '&' : op = mp_self_bitwise_and; _cimg_mp_op("Operator '&='"); break; + case '|' : op = mp_self_bitwise_or; _cimg_mp_op("Operator '|='"); break; + default : op = mp_self_pow; _cimg_mp_op("Operator '^='"); break; + } + s1 = *ps=='>' || *ps=='<'?ns:ps; + + ref.assign(7); + arg1 = compile(ss,s1,depth1,ref); // Variable slot + arg2 = compile(s + 1,se,depth1,0); // Value to apply + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_variable(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k] += scalar + _cimg_mp_check_type(arg2,2,1,0); + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_vector_size(arg3),arg4,arg1). + move_to(code); + _cimg_mp_return(arg1); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off] += scalar + _cimg_mp_check_type(arg2,2,1,0); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c) += scalar + _cimg_mp_check_type(arg2,2,1,0); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off] += value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c) += value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + if (_cimg_mp_is_scalar(arg2)) self_vector_s(arg1,op,arg2); else self_vector_v(arg1,op,arg2); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5).move_to(code); + } else { + if (!imgout) _cimg_mp_return(arg1); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5).move_to(code); + } + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V += value + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + if (_cimg_mp_is_vector(arg2)) self_vector_v(arg1,op,arg2); // Vector += vector + else self_vector_s(arg1,op,arg2); // Vector += scalar + _cimg_mp_return(arg1); + } + + if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s += scalar + _cimg_mp_check_type(arg2,2,1,0); + CImg::vector((ulongT)op,arg1,arg2).move_to(code); + _cimg_mp_return(arg1); + } + + variable_name.assign(ss,(unsigned int)(s - ss)).back() = 0; + cimg::strpare(variable_name,' ',false,true); + *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: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + for (s = ss1; s::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='|' && *ns=='|' && level[s - expr._data]==clevel) { // Logical or ('||') + _cimg_mp_op("Operator '||'"); + arg1 = compile(ss,s,depth1,0); + _cimg_mp_check_type(arg1,1,1,0); + if (arg1>0 && arg1<=16) _cimg_mp_return(1); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] || mem[arg2]); + if (!arg1) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_or,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + _cimg_mp_return(pos); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='&' && *ns=='&' && level[s - expr._data]==clevel) { // Logical and ('&&') + _cimg_mp_op("Operator '&&'"); + arg1 = compile(ss,s,depth1,0); + _cimg_mp_check_type(arg1,1,1,0); + if (!arg1) _cimg_mp_return(0); + p2 = code._width; + arg2 = compile(s + 2,se,depth1,0); + _cimg_mp_check_type(arg2,2,1,0); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(mem[arg1] && mem[arg2]); + if (arg1>0 && arg1<=16) _cimg_mp_return(arg2); + pos = scalar(); + CImg::vector((ulongT)mp_logical_and,pos,arg1,arg2,code._width - p2). + move_to(code,p2); + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='|' && level[s - expr._data]==clevel) { // Bitwise or ('|') + _cimg_mp_op("Operator '|'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,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_or,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_vector2_sv(mp_bitwise_or,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((ulongT)mem[arg1] | (ulongT)mem[arg2]); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + _cimg_mp_scalar2(mp_bitwise_or,arg1,arg2); + } + + for (s = se2; s>ss; --s) + if (*s=='&' && level[s - expr._data]==clevel) { // Bitwise and ('&') + _cimg_mp_op("Operator '&'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,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_and,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_bitwise_and,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((ulongT)mem[arg1] & (ulongT)mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_bitwise_and,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='!' && *ns=='=' && level[s - expr._data]==clevel) { // Not equal to ('!=') + _cimg_mp_op("Operator '!='"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,depth1,0); + p1 = _cimg_mp_vector_size(arg1); + p2 = _cimg_mp_vector_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(1); + _cimg_mp_scalar6(mp_vector_neq,arg1,p1,arg2,p2,11,1); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]!=mem[arg2]); + _cimg_mp_scalar2(mp_neq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='=' && *ns=='=' && level[s - expr._data]==clevel) { // Equal to ('==') + _cimg_mp_op("Operator '=='"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,depth1,0); + p1 = _cimg_mp_vector_size(arg1); + p2 = _cimg_mp_vector_size(arg2); + if (p1 || p2) { + if (p1 && p2 && p1!=p2) _cimg_mp_return(0); + _cimg_mp_scalar6(mp_vector_eq,arg1,p1,arg2,p2,11,1); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]==mem[arg2]); + _cimg_mp_scalar2(mp_eq,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='=' && level[s - expr._data]==clevel) { // Less or equal than ('<=') + _cimg_mp_op("Operator '<='"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,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_lte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]<=mem[arg2]); + _cimg_mp_scalar2(mp_lte,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='=' && level[s - expr._data]==clevel) { // Greater or equal than ('>=') + _cimg_mp_op("Operator '>='"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,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_gte,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gte,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gte,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>=mem[arg2]); + _cimg_mp_scalar2(mp_gte,arg1,arg2); + } + + for (s = se2, ns = se1, ps = se3; s>ss; --s, --ns, --ps) + if (*s=='<' && *ns!='<' && *ps!='<' && level[s - expr._data]==clevel) { // Less than ('<') + _cimg_mp_op("Operator '<'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,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_lt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_lt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_lt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]ss; --s, --ns, --ps) + if (*s=='>' && *ns!='>' && *ps!='>' && level[s - expr._data]==clevel) { // Greather than ('>') + _cimg_mp_op("Operator '>'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,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_gt,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_gt,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_gt,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]>mem[arg2]); + _cimg_mp_scalar2(mp_gt,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='<' && *ns=='<' && level[s - expr._data]==clevel) { // Left bit shift ('<<') + _cimg_mp_op("Operator '<<'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,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_left_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_left_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_left_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]<<(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_left_shift,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='>' && *ns=='>' && level[s - expr._data]==clevel) { // Right bit shift ('>>') + _cimg_mp_op("Operator '>>'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,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_right_shift,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_vector2_vs(mp_bitwise_right_shift,arg1,arg2); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) + _cimg_mp_vector2_sv(mp_bitwise_right_shift,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant((longT)mem[arg1]>>(unsigned int)mem[arg2]); + if (!arg1) _cimg_mp_return(0); + if (!arg2) _cimg_mp_return(arg1); + _cimg_mp_scalar2(mp_bitwise_right_shift,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='+' && (*ns!='+' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Addition ('+') + _cimg_mp_op("Operator '+'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,depth1,0); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (!arg1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_add,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_add,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_add,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] + mem[arg2]); + if (code) { // Try to spot linear case 'a*b + c'. + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_linear_add,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_increment,arg1); + if (arg1==1) _cimg_mp_scalar1(mp_increment,arg2); + _cimg_mp_scalar2(mp_add,arg1,arg2); + } + + for (ns = se1, s = se2, ps = pexpr._data + (se3 - expr._data); s>ss; --ns, --s, --ps) + if (*s=='-' && (*ns!='-' || ns!=se1) && *ps!='-' && *ps!='+' && *ps!='*' && *ps!='/' && *ps!='%' && + *ps!='&' && *ps!='|' && *ps!='^' && *ps!='!' && *ps!='~' && *ps!='#' && + (*ps!='e' || !(ps - pexpr._data>ss - expr._data && (*(ps - 1)=='.' || (*(ps - 1)>='0' && + *(ps - 1)<='9')))) && + level[s - expr._data]==clevel) { // Subtraction ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,depth1,0); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + if (!arg2) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_sub,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_sub,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + if (!arg1) _cimg_mp_vector1_v(mp_minus,arg2); + _cimg_mp_vector2_sv(mp_sub,arg1,arg2); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1] - mem[arg2]); + if (!arg1) _cimg_mp_scalar1(mp_minus,arg2); + if (code) { // Try to spot linear cases 'a*b - c' and 'c - a*b'. + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)(arg3==arg1?mp_linear_sub_left:mp_linear_sub_right), + arg3,arg4,arg5,arg3==arg1?arg2:arg1).move_to(code); + _cimg_mp_return(arg3); + } + } + if (arg2==1) _cimg_mp_scalar1(mp_decrement,arg1); + _cimg_mp_scalar2(mp_sub,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='*' && *ns=='*' && level[s - expr._data]==clevel) { // Complex/matrix multiplication ('**') + _cimg_mp_op("Operator '**'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,depth1,0); + if (arg2==1) _cimg_mp_return(arg1); + if (arg1==1) _cimg_mp_return(arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + if (_cimg_mp_vector_size(arg1)==2 && _cimg_mp_vector_size(arg2)==2) { // Complex multiplication + pos = vector(2); + CImg::vector((ulongT)mp_complex_mul,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } else { // Particular case of matrix multiplication + p1 = _cimg_mp_vector_size(arg1); + p2 = _cimg_mp_vector_size(arg2); + arg4 = p1/p2; + if (arg4*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: Types of left-hand and right-hand operands " + "('%s' and '%s') do not match, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s_type(arg1)._data,s_type(arg2)._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,p2,1).move_to(code); + _cimg_mp_return(pos); + } + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='/' && *ns=='/' && level[s - expr._data]==clevel) { // Complex division ('//') + _cimg_mp_op("Operator '//'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,depth1,0); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_vv,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + pos = vector(2); + CImg::vector((ulongT)mp_complex_div_sv,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='*' && level[s - expr._data]==clevel) { // Multiplication ('*') + _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::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); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_mul,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_mul,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_mul,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]*mem[arg2]); + + if (code) { // Try to spot double multiplication 'a*b*c'. + CImg &pop = code.back(); + if (pop[0]==(ulongT)mp_mul && _cimg_mp_is_comp(pop[1]) && (pop[1]==arg1 || pop[1]==arg2)) { + arg3 = (unsigned int)pop[1]; + arg4 = (unsigned int)pop[2]; + arg5 = (unsigned int)pop[3]; + code.remove(); + CImg::vector((ulongT)mp_mul2,arg3,arg4,arg5,arg3==arg2?arg1:arg2).move_to(code); + _cimg_mp_return(arg3); + } + } + if (!arg1 || !arg2) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_mul,arg1,arg2); + } + + for (s = se2; s>ss; --s) if (*s=='/' && level[s - expr._data]==clevel) { // Division ('/') + _cimg_mp_op("Operator '/'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,depth1,0); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_div,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_div,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_div,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) _cimg_mp_constant(mem[arg1]/mem[arg2]); + if (!arg1) _cimg_mp_return(0); + _cimg_mp_scalar2(mp_div,arg1,arg2); + } + + for (s = se2, ns = se1; s>ss; --s, --ns) + if (*s=='%' && *ns!='^' && level[s - expr._data]==clevel) { // Modulo ('%') + _cimg_mp_op("Operator '%'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,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_modulo,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_modulo,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_modulo,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(cimg::mod(mem[arg1],mem[arg2])); + _cimg_mp_scalar2(mp_modulo,arg1,arg2); + } + + if (se1>ss) { + if (*ss=='+' && (*ss1!='+' || (ss2='0' && *ss2<='9'))) { // Unary plus ('+') + _cimg_mp_op("Operator '+'"); + _cimg_mp_return(compile(ss1,se,depth1,0)); + } + + if (*ss=='-' && (*ss1!='-' || (ss2='0' && *ss2<='9'))) { // Unary minus ('-') + _cimg_mp_op("Operator '-'"); + arg1 = compile(ss1,se,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_minus,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(-mem[arg1]); + _cimg_mp_scalar1(mp_minus,arg1); + } + + if (*ss=='!') { // Logical not ('!') + _cimg_mp_op("Operator '!'"); + arg1 = compile(ss1,se,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_logical_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(!mem[arg1]); + _cimg_mp_scalar1(mp_logical_not,arg1); + } + + if (*ss=='~') { // Bitwise not ('~') + _cimg_mp_op("Operator '~'"); + arg1 = compile(ss1,se,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_bitwise_not,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(~(unsigned int)mem[arg1]); + _cimg_mp_scalar1(mp_bitwise_not,arg1); + } + } + + for (s = se3, ns = se2; s>ss; --s, --ns) + if (*s=='^' && *ns=='^' && level[s - expr._data]==clevel) { // Complex power ('^^') + _cimg_mp_op("Operator '^^'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 2,se,depth1,0); + _cimg_mp_check_type(arg1,1,3,2); + _cimg_mp_check_type(arg2,2,3,2); + pos = vector(2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) { + CImg::vector((ulongT)mp_complex_pow_vv,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) { + CImg::vector((ulongT)mp_complex_pow_vs,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) { + CImg::vector((ulongT)mp_complex_pow_sv,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + CImg::vector((ulongT)mp_complex_pow_ss,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + + for (s = se2; s>ss; --s) + if (*s=='^' && level[s - expr._data]==clevel) { // Power ('^') + _cimg_mp_op("Operator '^'"); + arg1 = compile(ss,s,depth1,0); + arg2 = compile(s + 1,se,depth1,0); + _cimg_mp_check_type(arg2,2,3,_cimg_mp_vector_size(arg1)); + if (arg2==1) _cimg_mp_return(arg1); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_vv(mp_pow,arg1,arg2); + if (_cimg_mp_is_vector(arg1) && _cimg_mp_is_scalar(arg2)) _cimg_mp_vector2_vs(mp_pow,arg1,arg2); + if (_cimg_mp_is_scalar(arg1) && _cimg_mp_is_vector(arg2)) _cimg_mp_vector2_sv(mp_pow,arg1,arg2); + if (_cimg_mp_is_constant(arg1) && _cimg_mp_is_constant(arg2)) + _cimg_mp_constant(std::pow(mem[arg1],mem[arg2])); + switch (arg2) { + case 0 : _cimg_mp_return(1); + case 2 : _cimg_mp_scalar1(mp_sqr,arg1); + case 3 : _cimg_mp_scalar1(mp_pow3,arg1); + case 4 : _cimg_mp_scalar1(mp_pow4,arg1); + default : + if (_cimg_mp_is_constant(arg2)) { + if (mem[arg2]==0.5) { _cimg_mp_scalar1(mp_sqrt,arg1); } + else if (mem[arg2]==0.25) { _cimg_mp_scalar1(mp_pow0_25,arg1); } + } + _cimg_mp_scalar2(mp_pow,arg1,arg2); + } + } + + is_sth = ss1ss && (*se1=='+' || *se1=='-') && *se2==*se1)) { // Pre/post-decrement and increment + if ((is_sth && *ss=='+') || (!is_sth && *se1=='+')) { + _cimg_mp_op("Operator '++'"); + op = mp_self_increment; + } else { + _cimg_mp_op("Operator '--'"); + op = mp_self_decrement; + } + ref.assign(7); + arg1 = is_sth?compile(ss2,se,depth1,ref):compile(ss,se2,depth1,ref); // Variable slot + + // Apply operator on a copy to prevent modifying a constant or a variable. + if (*ref && (_cimg_mp_is_constant(arg1) || _cimg_mp_is_vector(arg1) || _cimg_mp_is_variable(arg1))) { + if (_cimg_mp_is_vector(arg1)) arg1 = vector_copy(arg1); + else arg1 = scalar1(mp_copy,arg1); + } + + if (is_sth) pos = arg1; // Determine return indice, depending on pre/post action + else { + if (_cimg_mp_is_vector(arg1)) pos = vector_copy(arg1); + else pos = scalar1(mp_copy,arg1); + } + + if (*ref==1) { // Vector value (scalar): V[k]++ + arg3 = ref[1]; // Vector slot + arg4 = ref[2]; // Index + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1,1).move_to(code); + CImg::vector((ulongT)mp_vector_set_off,arg1,arg3,(ulongT)_cimg_mp_vector_size(arg3),arg4,arg1). + move_to(code); + _cimg_mp_return(pos); + } + + if (*ref==2) { // Image value (scalar): i/j[_#ind,off]++ + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_joff:mp_list_set_ioff), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_joff:mp_set_ioff), + arg1,arg3).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==3) { // Image value (scalar): i/j(_#ind,_x,_y,_z,_c)++ + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + arg6 = ref[6]; // C + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + CImg::vector((ulongT)op,arg1).move_to(code); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_jxyzc:mp_list_set_ixyzc), + arg1,p1,arg3,arg4,arg5,arg6).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_jxyzc:mp_set_ixyzc), + arg1,arg3,arg4,arg5,arg6).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==4) { // Image value (vector): I/J[_#ind,off]++ + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // Offset + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Joff_v:mp_list_set_Ioff_v), + arg1,p1,arg3).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Joff_v:mp_set_Ioff_v), + arg1,arg3).move_to(code); + } + _cimg_mp_return(pos); + } + + if (*ref==5) { // Image value (vector): I/J(_#ind,_x,_y,_z,_c)++ + is_parallelizable = false; + p1 = ref[1]; // Index + is_relative = (bool)ref[2]; + arg3 = ref[3]; // X + arg4 = ref[4]; // Y + arg5 = ref[5]; // Z + if (is_sth && p_ref) std::memcpy(p_ref,ref,ref._width*sizeof(unsigned int)); + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + if (p1!=~0U) { + if (!listout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_list_set_Jxyz_v:mp_list_set_Ixyz_v), + arg1,p1,arg3,arg4,arg5).move_to(code); + } else { + if (!imgout) _cimg_mp_return(pos); + CImg::vector((ulongT)(is_relative?mp_set_Jxyz_v:mp_set_Ixyz_v), + arg1,arg3,arg4,arg5).move_to(code); + } + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_vector(arg1)) { // Vector variable: V++ + self_vector_s(arg1,op==mp_self_increment?mp_self_add:mp_self_sub,1); + _cimg_mp_return(pos); + } + + if (_cimg_mp_is_variable(arg1)) { // Scalar variable: s++ + CImg::vector((ulongT)op,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (is_sth) variable_name.assign(ss2,(unsigned int)(se - ss1)); + else variable_name.assign(ss,(unsigned int)(se1 - ss)); + variable_name.back() = 0; + cimg::strpare(variable_name,' ',false,true); + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Invalid %slvalue '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + _cimg_mp_is_constant(arg1)?"const ":"", + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Array-like access to vectors and image values 'i/j/I/J[_#ind,offset,_boundary]' and 'vector[offset]'. + 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 + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0::vector((ulongT)(is_relative?mp_list_Joff:mp_list_Ioff), + pos,p1,arg1,arg2==~0U?_cimg_mp_boundary:arg2).move_to(code); + } else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Joff:mp_Ioff), + pos,arg1,arg2==~0U?_cimg_mp_boundary:arg2).move_to(code); + } + _cimg_mp_return(pos); + } + + if ((*ss=='i' || *ss=='j') && *ss1=='[' && + (reserved_label[*ss]==~0U || !_cimg_mp_is_vector(reserved_label[*ss]))) { // Image value as a scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s0ss && (*s0!='[' || level[s0 - expr._data]!=clevel)) --s0; + if (s0>ss) { // Vector value + arg1 = compile(ss,s0,depth1,0); + if (_cimg_mp_is_scalar(arg1)) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Array brackets used on non-vector variable '%s', " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + + } + s1 = s0 + 1; while (s1 sub-vector extraction + p1 = _cimg_mp_vector_size(arg1); + arg2 = compile(++s0,s1,depth1,0); // Starting indice + arg3 = compile(++s1,se1,depth1,0); // Length + _cimg_mp_check_constant(arg3,2,3); + arg3 = (unsigned int)mem[arg3]; + pos = vector(arg3); + CImg::vector((ulongT)mp_vector_crop,pos,arg1,p1,arg2,arg3).move_to(code); + _cimg_mp_return(pos); + } + + // One argument -> vector value reference + arg2 = compile(++s0,se1,depth1,0); + if (_cimg_mp_is_constant(arg2)) { // Constant index + nb = (int)mem[arg2]; + if (nb>=0 && nb<(int)_cimg_mp_vector_size(arg1)) _cimg_mp_return(arg1 + 1 + nb); + variable_name.assign(ss,(unsigned int)(s0 - ss)).back() = 0; + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Out-of-bounds reference '%s[%d]' " + "(vector '%s' has dimension %u), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data,nb, + variable_name._data,_cimg_mp_vector_size(arg1), + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + if (p_ref) { + *p_ref = 1; + p_ref[1] = arg1; + p_ref[2] = arg2; + if (_cimg_mp_is_comp(arg2)) memtype[arg2] = -2; // Prevent from being used in further optimization + } + pos = scalar3(mp_vector_off,arg1,_cimg_mp_vector_size(arg1),arg2); + memtype[pos] = -2; // Prevent from being used in further optimization + _cimg_mp_return(pos); + } + } + + // 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 + _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 + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + if (s1::vector((ulongT)(is_relative?mp_list_Jxyz:mp_list_Ixyz), + pos,p1,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5).move_to(code); + else { + need_input_copy = true; + CImg::vector((ulongT)(is_relative?mp_Jxyz:mp_Ixyz), + pos,arg1,arg2,arg3, + arg4==~0U?_cimg_mp_interpolation:arg4, + arg5==~0U?_cimg_mp_boundary:arg5).move_to(code); + } + _cimg_mp_return(pos); + } + + // i/j(_#ind,_x,_y,_z,_c,_interpolation,_boundary) + if ((*ss=='i' || *ss=='j') && *ss1=='(') { // Image value as scalar + if (*ss2=='#') { // Index specified + s0 = ss3; while (s01) { + arg2 = arg1 + 1; + if (p2>2) { + arg3 = arg2 + 1; + if (p2>3) arg4 = arg3 + 1; + } + } + if (s1::vector((ulongT)mp_arg,0,0,p2,arg1,arg2).move_to(_opcode); + for (s = ++s2; s::vector(arg3).move_to(_opcode); + ++p3; + s = ns; + } + (_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (_cimg_mp_is_constant(arg1)) { + p3-=1; // Number of args + arg1 = (unsigned int)(mem[arg1]<0?mem[arg1] + p3:mem[arg1]); + if (arg1::vector((ulongT)mp_break,_cimg_mp_slot_nan).move_to(code); + _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::vector((ulongT)mp_breakpoint,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return(_cimg_mp_slot_nan); + } + } + break; + + case 'c' : + if (!std::strncmp(ss,"cabs(",5)) { // Complex absolute value + _cimg_mp_op("Function 'cabs()'"); + arg1 = compile(ss5,se1,depth1,0); + _cimg_mp_check_type(arg1,0,2,2); + _cimg_mp_scalar2(mp_complex_abs,arg1 + 1,arg1 + 2); + } + + if (!std::strncmp(ss,"carg(",5)) { // Complex argument + _cimg_mp_op("Function 'carg()'"); + arg1 = compile(ss5,se1,depth1,0); + _cimg_mp_check_type(arg1,0,2,2); + _cimg_mp_scalar2(mp_atan2,arg1 + 2,arg1 + 1); + } + + if (!std::strncmp(ss,"cbrt(",5)) { // Cubic root + _cimg_mp_op("Function 'cbrt()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cbrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::cbrt(mem[arg1])); + _cimg_mp_scalar1(mp_cbrt,arg1); + } + + if (!std::strncmp(ss,"cconj(",6)) { // Complex conjugate + _cimg_mp_op("Function 'cconj()'"); + arg1 = compile(ss6,se1,depth1,0); + _cimg_mp_check_type(arg1,0,2,2); + pos = vector(2); + CImg::vector((ulongT)mp_complex_conj,pos,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cexp(",5)) { // Complex exponential + _cimg_mp_op("Function 'cexp()'"); + arg1 = compile(ss5,se1,depth1,0); + _cimg_mp_check_type(arg1,0,2,2); + pos = vector(2); + CImg::vector((ulongT)mp_complex_exp,pos,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"clog(",5)) { // Complex logarithm + _cimg_mp_op("Function 'clog()'"); + arg1 = compile(ss5,se1,depth1,0); + _cimg_mp_check_type(arg1,0,2,2); + pos = vector(2); + CImg::vector((ulongT)mp_complex_log,pos,arg1).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"continue(",9)) { // Complex absolute value + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_continue,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return(_cimg_mp_slot_nan); + } + } + + if (!std::strncmp(ss,"copy(",5)) { // Memory copy + _cimg_mp_op("Function 'copy()'"); + ref.assign(14); + s1 = ss5; while (s1(1,22).move_to(code); + code.back().get_shared_rows(0,7).fill((ulongT)mp_memcopy,p1,arg1,arg2,arg3,arg4,arg5,arg6); + code.back().get_shared_rows(8,21).fill(ref); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"cos(",4)) { // Cosine + _cimg_mp_op("Function 'cos()'"); + arg1 = compile(ss4,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cos,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cos(mem[arg1])); + _cimg_mp_scalar1(mp_cos,arg1); + } + + if (!std::strncmp(ss,"cosh(",5)) { // Hyperbolic cosine + _cimg_mp_op("Function 'cosh()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_cosh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::cosh(mem[arg1])); + _cimg_mp_scalar1(mp_cosh,arg1); + } + + if (!std::strncmp(ss,"crop(",5)) { // Image crop + _cimg_mp_op("Function 'crop()'"); + if (*ss5=='#') { // Index specified + s0 = ss6; while (s0::sequence(_cimg_mp_vector_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_vector_size(arg1)); + opcode.resize(1,std::min(opcode._height,4U),1,1,0).move_to(_opcode); + is_sth = true; + } else { + _cimg_mp_check_type(arg1,pos + 1,1,0); + CImg::vector(arg1).move_to(_opcode); + } + s = ns; + } + (_opcode>'y').move_to(opcode); + + arg1 = 0; arg2 = (p1!=~0U); + switch (opcode._height) { + case 0 : case 1 : + CImg::vector(0,0,0,0,~0U,~0U,~0U,~0U,0).move_to(opcode); + break; + case 2 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,_cimg_mp_boundary).move_to(opcode); + arg1 = arg2?3:2; + break; + case 3 : + CImg::vector(*opcode,0,0,0,opcode[1],~0U,~0U,~0U,opcode[2]).move_to(opcode); + arg1 = arg2?3:2; + break; + case 4 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,_cimg_mp_boundary). + move_to(opcode); + arg1 = (is_sth?2:1) + arg2; + break; + case 5 : + CImg::vector(*opcode,opcode[1],0,0,opcode[2],opcode[3],~0U,~0U,opcode[4]). + move_to(opcode); + arg1 = (is_sth?2:1) + arg2; + break; + case 6 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + _cimg_mp_boundary).move_to(opcode); + arg1 = (is_sth?2:4) + arg2; + break; + case 7 : + CImg::vector(*opcode,opcode[1],opcode[2],0,opcode[3],opcode[4],opcode[5],~0U, + opcode[6]).move_to(opcode); + arg1 = (is_sth?2:4) + arg2; + break; + case 8 : + CImg::vector(*opcode,opcode[1],opcode[2],opcode[3],opcode[4],opcode[5],opcode[6], + opcode[7],_cimg_mp_boundary).move_to(opcode); + arg1 = (is_sth?2:5) + arg2; + break; + case 9 : + arg1 = (is_sth?2:5) + arg2; + break; + default : // Error -> too much arguments + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Too much arguments specified, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + (ss - 4)>expr._data?"...":"", + (ss - 4)>expr._data?ss - 4:expr._data, + se<&expr.back()?"...":""); + } + + _cimg_mp_check_type((unsigned int)*opcode,arg2 + 1,1,0); + _cimg_mp_check_type((unsigned int)opcode[1],arg2 + 1 + (is_sth?0:1),1,0); + _cimg_mp_check_type((unsigned int)opcode[2],arg2 + 1 + (is_sth?0:2),1,0); + _cimg_mp_check_type((unsigned int)opcode[3],arg2 + 1 + (is_sth?0:3),1,0); + if (opcode[4]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[4],arg1,3); + opcode[4] = (ulongT)mem[opcode[4]]; + } + if (opcode[5]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[5],arg1 + 1,3); + opcode[5] = (ulongT)mem[opcode[5]]; + } + if (opcode[6]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[6],arg1 + 2,3); + opcode[6] = (ulongT)mem[opcode[6]]; + } + if (opcode[7]!=(ulongT)~0U) { + _cimg_mp_check_constant((unsigned int)opcode[7],arg1 + 3,3); + opcode[7] = (ulongT)mem[opcode[7]]; + } + _cimg_mp_check_type((unsigned int)opcode[8],arg1 + 4,1,0); + + if (opcode[4]==(ulongT)~0U || opcode[5]==(ulongT)~0U || + opcode[6]==(ulongT)~0U || opcode[7]==(ulongT)~0U) { + if (p1!=~0U) { + _cimg_mp_check_constant(p1,1,1); + p1 = (unsigned int)cimg::mod((int)mem[p1],listin.width()); + } + const CImg &img = p1!=~0U?listin[p1]:imgin; + if (!img) + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Cannot crop empty image when " + "some xyzc-coordinates are unspecified, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + (ss - 4)>expr._data?"...":"", + (ss - 4)>expr._data?ss - 4:expr._data, + se<&expr.back()?"...":""); + if (opcode[4]==(ulongT)~0U) opcode[4] = (ulongT)img._width; + if (opcode[5]==(ulongT)~0U) opcode[5] = (ulongT)img._height; + if (opcode[6]==(ulongT)~0U) opcode[6] = (ulongT)img._depth; + if (opcode[7]==(ulongT)~0U) opcode[7] = (ulongT)img._spectrum; + } + + pos = vector((unsigned int)(opcode[4]*opcode[5]*opcode[6]*opcode[7])); + CImg::vector((ulongT)mp_crop, + pos,p1, + *opcode,opcode[1],opcode[2],opcode[3], + opcode[4],opcode[5],opcode[6],opcode[7], + opcode[8]).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cross(",6)) { // Cross product + _cimg_mp_op("Function 'cross()'"); + s1 = ss6; while (s1::vector((ulongT)mp_cross,pos,arg1,arg2).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"cut(",4)) { // Cut + _cimg_mp_op("Function 'cut()'"); + s1 = ss4; while (s1val2?val2:val); + } + _cimg_mp_scalar3(mp_cut,arg1,arg2,arg3); + } + break; + + case 'd' : + if (!std::strncmp(ss,"date(",5)) { // Date and file date + _cimg_mp_op("Function 'date()'"); + s1 = ss5; while (s1::string(ss6,true,true).unroll('y'),true); + cimg::strpare(variable_name,' ',false,true); + ((CImg::vector((ulongT)mp_debug,arg1,0,code._width - p1), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code,p1); + *se1 = ')'; + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"display(",8)) { // Display memory + _cimg_mp_op("Function 'display()'"); + if (pexpr[se2 - expr._data]=='(') { // no arguments? + CImg::vector((ulongT)mp_display_memory,_cimg_mp_slot_nan).move_to(code); + _cimg_mp_return(_cimg_mp_slot_nan); + } + s1 = ss8; while (s1::string(ss8,true,true).unroll('y'),true); + cimg::strpare(variable_name,' ',false,true); + if (_cimg_mp_is_vector(arg1)) + ((CImg::vector((ulongT)mp_vector_print,arg1,0,(ulongT)_cimg_mp_vector_size(arg1)), + variable_name)>'y').move_to(opcode); + else + ((CImg::vector((ulongT)mp_print,arg1,0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + + ((CImg::vector((ulongT)mp_display,arg1,0,(ulongT)_cimg_mp_vector_size(arg1), + arg2,arg3,arg4,arg5), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *s1 = c1; + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"det(",4)) { // Matrix determinant + _cimg_mp_op("Function 'det()'"); + arg1 = compile(ss4,se1,depth1,0); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1)); + _cimg_mp_scalar2(mp_det,arg1,p1); + } + + if (!std::strncmp(ss,"diag(",5)) { // Diagonal matrix + _cimg_mp_op("Function 'diag()'"); + arg1 = compile(ss5,se1,depth1,0); + _cimg_mp_check_type(arg1,1,2,0); + p1 = _cimg_mp_vector_size(arg1); + pos = vector(p1*p1); + CImg::vector((ulongT)mp_diag,pos,arg1,p1).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"dot(",4)) { // Dot product + _cimg_mp_op("Function 'dot()'"); + s1 = ss4; while (s1::vector((ulongT)mp_dowhile,p1,p2,arg2 - arg1,code._width - arg2,_cimg_mp_vector_size(p1), + p1>=arg6 && !_cimg_mp_is_constant(p1), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p1); + } + + if (!std::strncmp(ss,"draw(",5)) { // Draw image + _cimg_mp_op("Function 'draw()'"); + is_parallelizable = false; + if (*ss5=='#') { // Index specified + s0 = ss6; while (s01) { + arg3 = arg2 + 1; + if (p2>2) { + arg4 = arg3 + 1; + if (p2>3) arg5 = arg4 + 1; + } + } + ++s0; + is_sth = true; + } else { + if (s0::vector((ulongT)mp_draw,arg1,(ulongT)_cimg_mp_vector_size(arg1),p1,arg2,arg3,arg4,arg5, + 0,0,0,0,1,(ulongT)~0U,0,1).move_to(opcode); + + arg2 = arg3 = arg4 = arg5 = ~0U; + p2 = p1!=~0U?0:1; + if (s0::vector((ulongT)mp_matrix_eig,pos,arg1,p1).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"exp(",4)) { // Exponential + _cimg_mp_op("Function 'exp()'"); + arg1 = compile(ss4,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_exp,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::exp(mem[arg1])); + _cimg_mp_scalar1(mp_exp,arg1); + } + + if (!std::strncmp(ss,"eye(",4)) { // Identity matrix + _cimg_mp_op("Function 'eye()'"); + arg1 = compile(ss4,se1,depth1,0); + _cimg_mp_check_constant(arg1,1,3); + p1 = (unsigned int)mem[arg1]; + pos = vector(p1*p1); + CImg::vector((ulongT)mp_eye,pos,p1).move_to(code); + _cimg_mp_return(pos); + } + break; + + case 'f' : + if (!std::strncmp(ss,"fact(",5)) { // Factorial + _cimg_mp_op("Function 'fact()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_factorial,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::factorial(mem[arg1])); + _cimg_mp_scalar1(mp_factorial,arg1); + } + + if (!std::strncmp(ss,"fibo(",5)) { // Fibonacci + _cimg_mp_op("Function 'fibo()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_fibonacci,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::fibonacci(mem[arg1])); + _cimg_mp_scalar1(mp_fibonacci,arg1); + } + + if (!std::strncmp(ss,"find(",5)) { // Find + _cimg_mp_op("Function 'find()'"); + + // First argument: data to look at. + s0 = ss5; while (s0::vector((ulongT)mp_for,p3,(ulongT)_cimg_mp_vector_size(p3),p2,arg2 - arg1,arg3 - arg2, + arg4 - arg3,code._width - arg4, + p3>=arg6 && !_cimg_mp_is_constant(p3), + p2>=arg6 && !_cimg_mp_is_constant(p2)).move_to(code,arg1); + _cimg_mp_return(p3); + } + break; + + case 'g' : + if (!std::strncmp(ss,"gauss(",6)) { // Gaussian function + _cimg_mp_op("Function 'gauss()'"); + s1 = ss6; while (s1::vector((ulongT)mp_if,pos,arg1,arg2,arg3, + p3 - p2,code._width - p3,arg4).move_to(code,p2); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"init(",5)) { // Init + _cimg_mp_op("Function 'init()'"); + if (ss0!=expr._data || code.width()) { // (only allowed as the first instruction) + *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: Init invokation not done at the " + "beginning of expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + arg1 = compile(ss5,se1,depth1,p_ref); + init_size = code.width(); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"int(",4)) { // Integer cast + _cimg_mp_op("Function 'int()'"); + arg1 = compile(ss4,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_int,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant((longT)mem[arg1]); + _cimg_mp_scalar1(mp_int,arg1); + } + + if (!std::strncmp(ss,"inv(",4)) { // Matrix/scalar inversion + _cimg_mp_op("Function 'inv()'"); + arg1 = compile(ss4,se1,depth1,0); + 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::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 + + if (!std::strncmp(ss,"isbool(",7)) { // Is boolean? + _cimg_mp_op("Function 'isbool()'"); + if (ss7==se1) _cimg_mp_return(0); + arg1 = compile(ss7,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isbool,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return(mem[arg1]==0.0 || mem[arg1]==1.0); + _cimg_mp_scalar1(mp_isbool,arg1); + } + + if (!std::strncmp(ss,"isdir(",6)) { // Is directory? + _cimg_mp_op("Function 'isdir()'"); + *se1 = 0; + is_sth = cimg::is_directory(ss6); + *se1 = ')'; + _cimg_mp_return(is_sth?1U:0U); + } + + if (!std::strncmp(ss,"isfile(",7)) { // Is file? + _cimg_mp_op("Function 'isfile()'"); + *se1 = 0; + is_sth = cimg::is_file(ss7); + *se1 = ')'; + _cimg_mp_return(is_sth?1U:0U); + } + + if (!std::strncmp(ss,"isin(",5)) { // Is in sequence/vector? + if (ss5>=se1) _cimg_mp_return(0); + _cimg_mp_op("Function 'isin()'"); + pos = scalar(); + CImg::vector((ulongT)mp_isin,pos,0).move_to(_opcode); + for (s = ss5; s::sequence(_cimg_mp_vector_size(arg1),arg1 + 1, + arg1 + (ulongT)_cimg_mp_vector_size(arg1)). + move_to(_opcode); + else CImg::vector(arg1).move_to(_opcode); + s = ns; + } + (_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"isinf(",6)) { // Is infinite? + _cimg_mp_op("Function 'isinf()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isinf,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_inf(mem[arg1])); + _cimg_mp_scalar1(mp_isinf,arg1); + } + + if (!std::strncmp(ss,"isint(",6)) { // Is integer? + _cimg_mp_op("Function 'isint()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isint,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)(cimg::mod(mem[arg1],1.0)==0)); + _cimg_mp_scalar1(mp_isint,arg1); + } + + if (!std::strncmp(ss,"isnan(",6)) { // Is NaN? + _cimg_mp_op("Function 'isnan()'"); + if (ss6==se1) _cimg_mp_return(0); + arg1 = compile(ss6,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_isnan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_return((unsigned int)cimg::type::is_nan(mem[arg1])); + _cimg_mp_scalar1(mp_isnan,arg1); + } + + if (!std::strncmp(ss,"isval(",6)) { // Is value? + _cimg_mp_op("Function 'isval()'"); + val = 0; + if (cimg_sscanf(ss6,"%lf%c%c",&val,&sep,&end)==2 && sep==')') _cimg_mp_return(1); + _cimg_mp_return(0); + } + + } + break; + + case 'l' : + if (!std::strncmp(ss,"log(",4)) { // Natural logarithm + _cimg_mp_op("Function 'log()'"); + arg1 = compile(ss4,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log(mem[arg1])); + _cimg_mp_scalar1(mp_log,arg1); + } + + if (!std::strncmp(ss,"log2(",5)) { // Base-2 logarithm + _cimg_mp_op("Function 'log2()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log2,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::log2(mem[arg1])); + _cimg_mp_scalar1(mp_log2,arg1); + } + + if (!std::strncmp(ss,"log10(",6)) { // Base-10 logarithm + _cimg_mp_op("Function 'log10()'"); + arg1 = compile(ss6,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_log10,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::log10(mem[arg1])); + _cimg_mp_scalar1(mp_log10,arg1); + } + + if (!std::strncmp(ss,"lowercase(",10)) { // Lower case + _cimg_mp_op("Function 'lowercase()'"); + arg1 = compile(ss + 10,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_lowercase,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::lowercase(mem[arg1])); + _cimg_mp_scalar1(mp_lowercase,arg1); + } + break; + + case 'm' : + if (!std::strncmp(ss,"mul(",4)) { // Matrix multiplication + _cimg_mp_op("Function 'mul()'"); + s1 = ss4; while (s1expr._data?ss - 4:expr._data; + 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 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, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_matrix_mul,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + _cimg_mp_return(pos); + } + break; + + case 'n' : + if (!std::strncmp(ss,"narg(",5)) { // Number of arguments + _cimg_mp_op("Function 'narg()'"); + if (ss5>=se1) _cimg_mp_return(0); + arg1 = 0; + for (s = ss5; s::vector((ulongT)mp_norm0,pos,0).move_to(_opcode); break; + case 1 : + CImg::vector((ulongT)mp_norm1,pos,0).move_to(_opcode); break; + case 2 : + CImg::vector((ulongT)mp_norm2,pos,0).move_to(_opcode); break; + case ~0U : + CImg::vector((ulongT)mp_norminf,pos,0).move_to(_opcode); break; + default : + CImg::vector((ulongT)mp_normp,pos,0,(ulongT)(arg1==~0U?-1:(int)arg1)). + move_to(_opcode); + } + for ( ; s::sequence(_cimg_mp_vector_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_vector_size(arg2)). + move_to(_opcode); + else CImg::vector(arg2).move_to(_opcode); + s = ns; + } + + (_opcode>'y').move_to(opcode); + if (arg1>0 && opcode._height==4) // Special case with one argument and p>=1 + _cimg_mp_scalar1(mp_abs,opcode[3]); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return(pos); + } + break; + + case 'p' : + if (!std::strncmp(ss,"permut(",7)) { // Number of permutations + _cimg_mp_op("Function 'permut()'"); + s1 = ss7; while (s1expr._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::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::string(s,true,true).unroll('y'),true); + cimg::strpare(variable_name,' ',false,true); + if (_cimg_mp_is_vector(pos)) // Vector + ((CImg::vector((ulongT)mp_vector_print,pos,0,(ulongT)_cimg_mp_vector_size(pos)), + variable_name)>'y').move_to(opcode); + else // Scalar + ((CImg::vector((ulongT)mp_print,pos,0), + variable_name)>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + *ns = c1; s = ns; + } + _cimg_mp_return(pos); + } + break; + + case 'r' : + if (!std::strncmp(ss,"resize(",7)) { // Vector resize + _cimg_mp_op("Function 'resize()'"); + s1 = ss7; while (s1::vector((ulongT)mp_vector_resize,pos,arg2,arg1,(ulongT)_cimg_mp_vector_size(arg1), + arg3,arg4).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"reverse(",8)) { // Vector reverse + _cimg_mp_op("Function 'reverse()'"); + arg1 = compile(ss8,se1,depth1,0); + if (!_cimg_mp_is_vector(arg1)) _cimg_mp_return(arg1); + p1 = _cimg_mp_vector_size(arg1); + pos = vector(p1); + CImg::vector((ulongT)mp_vector_reverse,pos,arg1,p1).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"rol(",4) || !std::strncmp(ss,"ror(",4)) { // Bitwise rotation + _cimg_mp_op(ss[2]=='l'?"Function 'rol()'":"Function 'ror()'"); + s1 = ss4; while (s11) { + arg2 = arg1 + 1; + if (p2>2) arg3 = arg2 + 1; + } + arg4 = compile(++s1,se1,depth1,0); + } else { + s2 = s1 + 1; while (s2::vector((ulongT)mp_rot3d,pos,arg1,arg2,arg3,arg4).move_to(code); + } else { // 2d rotation + _cimg_mp_check_type(arg1,1,1,0); + pos = vector(4); + CImg::vector((ulongT)mp_rot2d,pos,arg1).move_to(code); + } + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"round(",6)) { // Value rounding + _cimg_mp_op("Function 'round()'"); + s1 = ss6; while (s1::vector((ulongT)mp_single,arg1,code._width - p1).move_to(code,p1); + _cimg_mp_return(arg1); + } + + if (!std::strncmp(ss,"sinh(",5)) { // Hyperbolic sine + _cimg_mp_op("Function 'sinh()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sinh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sinh(mem[arg1])); + _cimg_mp_scalar1(mp_sinh,arg1); + } + + if (!std::strncmp(ss,"size(",5)) { // Vector size. + _cimg_mp_op("Function 'size()'"); + arg1 = compile(ss5,se1,depth1,0); + _cimg_mp_constant(_cimg_mp_is_scalar(arg1)?0:_cimg_mp_vector_size(arg1)); + } + + if (!std::strncmp(ss,"solve(",6)) { // Solve linear system + _cimg_mp_op("Function 'solve()'"); + s1 = ss6; while (s1expr._data?ss - 4:expr._data; + 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 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, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg4*p3); + CImg::vector((ulongT)mp_solve,pos,arg1,arg2,arg4,arg5,p3).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sort(",5)) { // Sort vector + _cimg_mp_op("Function 'sort()'"); + s1 = ss6; while (s1expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Invalid specified chunk size (%u) for first argument " + "('%s'), in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + arg3,s_type(arg1)._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(p1); + CImg::vector((ulongT)mp_sort,pos,arg1,p1,arg2,arg3).move_to(code); + _cimg_mp_return(pos); + } + + if (!std::strncmp(ss,"sqr(",4)) { // Square + _cimg_mp_op("Function 'sqr()'"); + arg1 = compile(ss4,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqr,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(cimg::sqr(mem[arg1])); + _cimg_mp_scalar1(mp_sqr,arg1); + } + + if (!std::strncmp(ss,"sqrt(",5)) { // Square root + _cimg_mp_op("Function 'sqrt()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_sqrt,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::sqrt(mem[arg1])); + _cimg_mp_scalar1(mp_sqrt,arg1); + } + + if (!std::strncmp(ss,"stod(",5)) { // String to double + _cimg_mp_op("Function 'stod()'"); + s1 = ss5; while (s1expr._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::vector((ulongT)mp_matrix_svd,pos,arg1,p2,p3).move_to(code); + _cimg_mp_return(pos); + } + break; + + case 't' : + if (!std::strncmp(ss,"tan(",4)) { // Tangent + _cimg_mp_op("Function 'tan()'"); + arg1 = compile(ss4,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tan,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tan(mem[arg1])); + _cimg_mp_scalar1(mp_tan,arg1); + } + + if (!std::strncmp(ss,"tanh(",5)) { // Hyperbolic tangent + _cimg_mp_op("Function 'tanh()'"); + arg1 = compile(ss5,se1,depth1,0); + if (_cimg_mp_is_vector(arg1)) _cimg_mp_vector1_v(mp_tanh,arg1); + if (_cimg_mp_is_constant(arg1)) _cimg_mp_constant(std::tanh(mem[arg1])); + _cimg_mp_scalar1(mp_tanh,arg1); + } + + if (!std::strncmp(ss,"trace(",6)) { // Matrix trace + _cimg_mp_op("Function 'trace()'"); + arg1 = compile(ss6,se1,depth1,0); + _cimg_mp_check_matrix_square(arg1,1); + p1 = (unsigned int)std::sqrt((float)_cimg_mp_vector_size(arg1)); + _cimg_mp_scalar2(mp_trace,arg1,p1); + } + + if (!std::strncmp(ss,"transp(",7)) { // Matrix transpose + _cimg_mp_op("Function 'transp()'"); + s1 = ss7; while (s1expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Size of first argument ('%s') does not match " + "second argument 'nb_cols=%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(p3*p2); + CImg::vector((ulongT)mp_transp,pos,arg1,p2,p3).move_to(code); + _cimg_mp_return(pos); + } + break; + + case 'u' : + if (*ss1=='(') { // Random value with uniform distribution + _cimg_mp_op("Function 'u()'"); + if (*ss2==')') _cimg_mp_scalar2(mp_u,0,1); + s1 = ss2; while (s1ss6 && *s0==',') ++s0; + s1 = s0; while (s1s0) { + *s1 = 0; + arg2 = arg3 = ~0U; + if (s0[0]=='w' && s0[1]=='h' && !s0[2]) arg1 = reserved_label[arg3 = 0]; + else if (s0[0]=='w' && s0[1]=='h' && s0[2]=='d' && !s0[3]) arg1 = reserved_label[arg3 = 1]; + else if (s0[0]=='w' && s0[1]=='h' && s0[2]=='d' && s0[3]=='s' && !s0[4]) + arg1 = reserved_label[arg3 = 2]; + else if (s0[0]=='p' && s0[1]=='i' && !s0[2]) arg1 = reserved_label[arg3 = 3]; + else if (s0[0]=='i' && s0[1]=='m' && !s0[2]) arg1 = reserved_label[arg3 = 4]; + else if (s0[0]=='i' && s0[1]=='M' && !s0[2]) arg1 = reserved_label[arg3 = 5]; + else if (s0[0]=='i' && s0[1]=='a' && !s0[2]) arg1 = reserved_label[arg3 = 6]; + else if (s0[0]=='i' && s0[1]=='v' && !s0[2]) arg1 = reserved_label[arg3 = 7]; + else if (s0[0]=='i' && s0[1]=='s' && !s0[2]) arg1 = reserved_label[arg3 = 8]; + else if (s0[0]=='i' && s0[1]=='p' && !s0[2]) arg1 = reserved_label[arg3 = 9]; + else if (s0[0]=='i' && s0[1]=='c' && !s0[2]) arg1 = reserved_label[arg3 = 10]; + else if (s0[0]=='x' && s0[1]=='m' && !s0[2]) arg1 = reserved_label[arg3 = 11]; + else if (s0[0]=='y' && s0[1]=='m' && !s0[2]) arg1 = reserved_label[arg3 = 12]; + else if (s0[0]=='z' && s0[1]=='m' && !s0[2]) arg1 = reserved_label[arg3 = 13]; + else if (s0[0]=='c' && s0[1]=='m' && !s0[2]) arg1 = reserved_label[arg3 = 14]; + else if (s0[0]=='x' && s0[1]=='M' && !s0[2]) arg1 = reserved_label[arg3 = 15]; + else if (s0[0]=='y' && s0[1]=='M' && !s0[2]) arg1 = reserved_label[arg3 = 16]; + else if (s0[0]=='z' && s0[1]=='M' && !s0[2]) arg1 = reserved_label[arg3 = 17]; + else if (s0[0]=='c' && s0[1]=='M' && !s0[2]) arg1 = reserved_label[arg3 = 18]; + else if (s0[0]=='i' && s0[1]>='0' && s0[1]<='9' && !s0[2]) + arg1 = reserved_label[arg3 = 19 + s0[1] - '0']; + else if (!std::strcmp(s0,"interpolation")) arg1 = reserved_label[arg3 = 29]; + else if (!std::strcmp(s0,"boundary")) arg1 = reserved_label[arg3 = 30]; + else if (s0[1]) { // Multi-char variable + cimglist_for(variable_def,i) if (!std::strcmp(s0,variable_def[i])) { + arg1 = variable_pos[i]; arg2 = i; break; + } + } else arg1 = reserved_label[arg3 = *s0]; // Single-char variable + + if (arg1!=~0U) { + if (arg2==~0U) { if (arg3!=~0U) reserved_label[arg3] = ~0U; } + else { + variable_def.remove(arg2); + if (arg20) || + !std::strncmp(ss,"vector(",7) || + (!std::strncmp(ss,"vector",6) && ss7::sequence(arg4,arg3 + 1,arg3 + arg4).move_to(_opcode); + arg2+=arg4; + } else { CImg::vector(arg3).move_to(_opcode); ++arg2; } + s = ns; + } + if (arg1==~0U) arg1 = arg2; + _cimg_mp_check_vector0(arg1); + pos = vector(arg1); + _opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + _cimg_mp_return(pos); + } + break; + + case 'w' : + if (!std::strncmp(ss,"whiledo",7) && (*ss7=='(' || (*ss7 && *ss7<=' ' && *ss8=='('))) { // While...do + _cimg_mp_op("Function 'whiledo()'"); + s1 = ss8; while (s1::vector((ulongT)mp_whiledo,pos,arg1,p2 - p1,code._width - p2,arg2, + pos>=arg6 && !_cimg_mp_is_constant(pos), + arg1>=arg6 && !_cimg_mp_is_constant(arg1)).move_to(code,p1); + _cimg_mp_return(pos); + } + break; + + case 'x' : + if (!std::strncmp(ss,"xor(",4)) { // Xor + _cimg_mp_op("Function 'xor()'"); + s1 = ss4; while (s1::vector((ulongT)op,pos,0).move_to(_opcode); + for (s = std::strchr(ss,'(') + 1; s::sequence(_cimg_mp_vector_size(arg2),arg2 + 1, + arg2 + (ulongT)_cimg_mp_vector_size(arg2)). + move_to(_opcode); + else CImg::vector(arg2).move_to(_opcode); + is_sth&=_cimg_mp_is_constant(arg2); + s = ns; + } + (_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + if (is_sth) _cimg_mp_constant(op(*this)); + opcode.move_to(code); + _cimg_mp_return(pos); + } + + // No corresponding built-in function -> Look for a user-defined macro call. + s0 = strchr(ss,'('); + if (s0) { + variable_name.assign(ss,(unsigned int)(s0 - ss + 1)).back() = 0; + + // Count number of specified arguments. + p1 = 0; + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { + while (*s && *s<=' ') ++s; + if (*s==')' && !p1) break; + ns = s; while (ns _expr = macro_body[l]; // Expression to be substituted + + p1 = 1; // Indice of current parsed argument + for (s = s0 + 1; s<=se1; ++p1, s = ns + 1) { // Parse function arguments + while (*s && *s<=' ') ++s; + if (*s==')' && p1==1) break; // Function has no arguments + if (p1>p2) { ++p1; break; } + ns = s; while (ns _pexpr(_expr._width); + ns = _pexpr._data; + for (ps = _expr._data, c1 = ' '; *ps; ++ps) { + if (*ps!=' ') c1 = *ps; + *(ns++) = c1; + } + *ns = 0; + + CImg _level = get_level(_expr); + expr.swap(_expr); + pexpr.swap(_pexpr); + level.swap(_level); + s0 = user_macro; + user_macro = macro_def[l]; + pos = compile(expr._data,expr._data + expr._width - 1,depth1,p_ref); + user_macro = s0; + level.swap(_level); + pexpr.swap(_pexpr); + expr.swap(_expr); + _cimg_mp_return(pos); + } + + if (arg3) { // Macro name matched but number of arguments does not + CImg sig_nargs(arg3); + arg1 = 0; + cimglist_for(macro_def,l) if (!std::strcmp(macro_def[l],variable_name)) + sig_nargs[arg1++] = (unsigned int)macro_def[l].back(); + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + if (sig_nargs._width>1) { + sig_nargs.sort(); + arg1 = sig_nargs.back(); + --sig_nargs._width; + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %s or %u arguments), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,sig_nargs.value_string()._data,arg1, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Function '%s()': Number of specified arguments (%u) " + "does not match macro declaration (defined for %u argument%s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,variable_name._data, + p1,*sig_nargs,*sig_nargs!=1?"s":"", + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + } // if (se1==')') + + // Char / string initializer. + if (*se1=='\'' && + ((se1>ss && *ss=='\'') || + (se1>ss1 && *ss=='_' && *ss1=='\''))) { + if (*ss=='_') { _cimg_mp_op("Char initializer"); s1 = ss2; } + else { _cimg_mp_op("String initializer"); s1 = ss1; } + arg1 = (unsigned int)(se1 - s1); // Original string length. + if (arg1) { + CImg(s1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + if (*ss=='_') { + if (arg1==1) _cimg_mp_constant(*variable_name); + *se = saved_char; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s: Literal %s contains more than one character, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op, + ss1, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(_opcode); + std::memcpy((char*)_opcode[1]._data,variable_name,arg1); + (_opcode>'y').move_to(code); + _cimg_mp_return(pos); + } + + // Vector initializer [ ... ]. + if (*ss=='[' && *se1==']') { + _cimg_mp_op("Vector initializer"); + s1 = ss1; while (s1s1 && *s2<=' ') --s2; + if (s2>s1 && *s1=='\'' && *s2=='\'') { // Vector values provided as a string + arg1 = (unsigned int)(s2 - s1 - 1); // Original string length. + if (arg1) { + CImg(s1 + 1,arg1 + 1).move_to(variable_name).back() = 0; + cimg::strunescape(variable_name); + arg1 = (unsigned int)std::strlen(variable_name); + } + if (!arg1) _cimg_mp_return(0); // Empty string -> 0 + pos = vector(arg1); + CImg::vector((ulongT)mp_string_init,pos,arg1).move_to(_opcode); + CImg(1,arg1/sizeof(ulongT) + (arg1%sizeof(ulongT)?1:0)).move_to(_opcode); + std::memcpy((char*)_opcode[1]._data,variable_name,arg1); + (_opcode>'y').move_to(code); + } else { // Vector values provided as list of items + arg1 = 0; // Number of specified values. + if (*ss1!=']') for (s = ss1; s::sequence(arg3,arg2 + 1,arg2 + arg3).move_to(_opcode); + arg1+=arg3; + } else { CImg::vector(arg2).move_to(_opcode); ++arg1; } + s = ns; + } + _cimg_mp_check_vector0(arg1); + pos = vector(arg1); + _opcode.insert(CImg::vector((ulongT)mp_vector_init,pos,0,arg1),0); + (_opcode>'y').move_to(opcode); + opcode[2] = opcode._height; + opcode.move_to(code); + } + _cimg_mp_return(pos); + } + + // Variables related to the input list of images. + if (*ss1=='#' && ss2::vector((ulongT)mp_list_Ixyz, + pos,p1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z, + 0,_cimg_mp_boundary).move_to(code); + _cimg_mp_return(pos); + case 'R' : // R#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,0, + 0,_cimg_mp_boundary); + case 'G' : // G#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,1, + 0,_cimg_mp_boundary); + case 'B' : // B#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,2, + 0,_cimg_mp_boundary); + case 'A' : // A#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,3, + 0,_cimg_mp_boundary); + } + } + + if (*ss1 && *ss2=='#' && ss3::vector(listin[p1].median()).move_to(list_median[p1]); + _cimg_mp_constant(*list_median[p1]); + } + _cimg_mp_scalar1(mp_list_median,arg1); + } + if (*ss1>='0' && *ss1<='9') { // i0#ind...i9#ind + if (!listin) _cimg_mp_return(0); + _cimg_mp_scalar7(mp_list_ixyzc,arg1,_cimg_mp_slot_x,_cimg_mp_slot_y,_cimg_mp_slot_z,*ss1 - '0', + 0,_cimg_mp_boundary); + } + switch (*ss1) { + case 'm' : arg2 = 0; break; // im#ind + case 'M' : arg2 = 1; break; // iM#ind + case 'a' : arg2 = 2; break; // ia#ind + case 'v' : arg2 = 3; break; // iv#ind + case 's' : arg2 = 12; break; // is#ind + case 'p' : arg2 = 13; break; // ip#ind + } + } else if (*ss1=='m') switch (*ss) { + case 'x' : arg2 = 4; break; // xm#ind + case 'y' : arg2 = 5; break; // ym#ind + case 'z' : arg2 = 6; break; // zm#ind + case 'c' : arg2 = 7; break; // cm#ind + } else if (*ss1=='M') switch (*ss) { + case 'x' : arg2 = 8; break; // xM#ind + case 'y' : arg2 = 9; break; // yM#ind + case 'z' : arg2 = 10; break; // zM#ind + case 'c' : arg2 = 11; break; // cM#ind + } + if (arg2!=~0U) { + if (!listin) _cimg_mp_return(0); + if (_cimg_mp_is_constant(arg1)) { + if (!list_stats) list_stats.assign(listin._width); + if (!list_stats[p1]) list_stats[p1].assign(1,14,1,1,0).fill(listin[p1].get_stats(),false); + _cimg_mp_constant(list_stats(p1,arg2)); + } + _cimg_mp_scalar2(mp_list_stats,arg1,arg2); + } + } + + if (*ss=='w' && *ss1=='h' && *ss2=='d' && *ss3=='#' && ss4 error. + is_sth = true; // is_valid_variable_name + if (*variable_name>='0' && *variable_name<='9') is_sth = false; + else for (ns = variable_name._data; *ns; ++ns) + if (!is_varchar(*ns)) { is_sth = false; break; } + + *se = saved_char; + c1 = *se1; + cimg::strellipsize(variable_name,64); + s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + if (is_sth) + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Undefined variable '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + s1 = std::strchr(ss,'('); + s_op = s1 && c1==')'?"function call":"item"; + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: Unrecognized %s '%s' in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function, + s_op,variable_name._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + + // Evaluation procedure. + double operator()(const double x, const double y, const double z, const double c) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = p_code_begin; p_code &op = *p_code; + opcode._data = op._data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + return *result; + } + + // Evaluation procedure (return output values in vector 'output'). + template + void operator()(const double x, const double y, const double z, const double c, t *const output) { + mem[_cimg_mp_slot_x] = x; mem[_cimg_mp_slot_y] = y; mem[_cimg_mp_slot_z] = z; mem[_cimg_mp_slot_c] = c; + for (p_code = p_code_begin; p_code &op = *p_code; + opcode._data = op._data; + const ulongT target = opcode[1]; + mem[target] = _cimg_mp_defunc(*this); + } + if (result_dim) { + const double *ptrs = result + 1; + t *ptrd = output; + for (unsigned int k = 0; k s_type(const unsigned int arg) const { + CImg res; + if (_cimg_mp_is_vector(arg)) { // Vector + CImg::string("vectorXXXXXXXXXXXXXXXX").move_to(res); + std::sprintf(res._data + 6,"%u",_cimg_mp_vector_size(arg)); + } else CImg::string("scalar").move_to(res); + return res; + } + + // 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::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=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; + } + + // Insert code instructions for processing scalars. + unsigned int scalar() { // Insert new scalar in memory. + if (mempos>=mem._width) { mem.resize(-200,1,1,1,0); memtype.resize(mem._width,1,1,1,0); } + return mempos++; + } + + unsigned int scalar0(const mp_func op) { + const unsigned int pos = scalar(); + CImg::vector((ulongT)op,pos).move_to(code); + return pos; + } + + unsigned int scalar1(const mp_func op, const unsigned int arg1) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1) && op!=mp_copy?arg1:scalar(); + CImg::vector((ulongT)op,pos,arg1).move_to(code); + return pos; + } + + unsigned int scalar2(const mp_func op, const unsigned int arg1, const unsigned int arg2) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2:scalar(); + CImg::vector((ulongT)op,pos,arg1,arg2).move_to(code); + return pos; + } + + unsigned int scalar3(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3:scalar(); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3).move_to(code); + return pos; + } + + unsigned int scalar4(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4:scalar(); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4).move_to(code); + return pos; + } + + unsigned int scalar5(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5:scalar(); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5).move_to(code); + return pos; + } + + unsigned int scalar6(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6:scalar(); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6).move_to(code); + return pos; + } + + unsigned int scalar7(const mp_func op, + const unsigned int arg1, const unsigned int arg2, const unsigned int arg3, + const unsigned int arg4, const unsigned int arg5, const unsigned int arg6, + const unsigned int arg7) { + const unsigned int pos = + arg1>_cimg_mp_slot_c && _cimg_mp_is_comp(arg1)?arg1: + arg2>_cimg_mp_slot_c && _cimg_mp_is_comp(arg2)?arg2: + arg3>_cimg_mp_slot_c && _cimg_mp_is_comp(arg3)?arg3: + arg4>_cimg_mp_slot_c && _cimg_mp_is_comp(arg4)?arg4: + arg5>_cimg_mp_slot_c && _cimg_mp_is_comp(arg5)?arg5: + arg6>_cimg_mp_slot_c && _cimg_mp_is_comp(arg6)?arg6: + arg7>_cimg_mp_slot_c && _cimg_mp_is_comp(arg7)?arg7:scalar(); + CImg::vector((ulongT)op,pos,arg1,arg2,arg3,arg4,arg5,arg6,arg7).move_to(code); + return pos; + } + + // Return a string that defines the calling function + the user-defined function scope. + CImg calling_function_s() const { + CImg res; + const unsigned int + l1 = calling_function?(unsigned int)std::strlen(calling_function):0U, + l2 = user_macro?(unsigned int)std::strlen(user_macro):0U; + if (l2) { + res.assign(l1 + l2 + 48); + cimg_snprintf(res,res._width,"%s(): When substituting function '%s()'",calling_function,user_macro); + } else { + res.assign(l1 + l2 + 4); + cimg_snprintf(res,res._width,"%s()",calling_function); + } + return res; + } + + // Return true if specified argument can be a part of an allowed variable name. + bool is_varchar(const char c) const { + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; + } + + // Insert code instructions for processing vectors. + 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); + bool is_tmp = true; + while (siz-->0) if (*(ptr++)) { is_tmp = false; break; } + return is_tmp; + } + + void set_variable_vector(const unsigned int arg) { + unsigned int siz = _cimg_mp_vector_size(arg); + int *ptr = memtype.data(arg + 1); + while (siz-->0) *(ptr++) = -1; + } + + unsigned int vector(const unsigned int siz) { // Insert new vector of specified size in memory + if (mempos + siz>=mem._width) { + mem.resize(2*mem._width + siz,1,1,1,0); + memtype.resize(mem._width,1,1,1,0); + } + const unsigned int pos = mempos++; + mem[pos] = cimg::type::nan(); + memtype[pos] = siz + 1; + mempos+=siz; + return pos; + } + + unsigned int vector(const unsigned int siz, const double value) { // Insert new initialized vector + const unsigned int pos = vector(siz); + double *ptr = &mem[pos] + 1; + for (unsigned int i = 0; i::vector((ulongT)mp_vector_copy,pos,arg,siz).move_to(code); + return pos; + } + + void self_vector_s(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_vector_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_s,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1).move_to(code[code._width - 1 - siz + k]); + } + } + + void self_vector_v(const unsigned int pos, const mp_func op, const unsigned int arg1) { + const unsigned int siz = _cimg_mp_vector_size(pos); + if (siz>24) CImg::vector((ulongT)mp_self_map_vector_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + } + + unsigned int vector1_v(const mp_func op, const unsigned int arg1) { + const unsigned int + siz = _cimg_mp_vector_size(arg1), + pos = is_comp_vector(arg1)?arg1:vector(siz); + if (siz>24) CImg::vector((ulongT)mp_vector_map_v,pos,siz,(ulongT)op,arg1).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + 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_comp_vector(arg1)?arg1:is_comp_vector(arg2)?arg2:vector(siz); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + 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_comp_vector(arg1)?arg1:vector(siz); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vs,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + 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_comp_vector(arg2)?arg2:vector(siz); + if (siz>24) CImg::vector((ulongT)mp_vector_map_sv,pos,siz,(ulongT)op,arg1,arg2).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1,arg2 + k).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + unsigned int vector3_vss(const mp_func op, const unsigned int arg1, const unsigned int arg2, + const unsigned int arg3) { + const unsigned int + siz = _cimg_mp_vector_size(arg1), + pos = is_comp_vector(arg1)?arg1:vector(siz); + if (siz>24) CImg::vector((ulongT)mp_vector_map_vss,pos,siz,(ulongT)op,arg1,arg2,arg3).move_to(code); + else { + code.insert(siz); + for (unsigned int k = 1; k<=siz; ++k) + CImg::vector((ulongT)op,pos + k,arg1 + k,arg2,arg3).move_to(code[code._width - 1 - siz + k]); + } + return pos; + } + + // Check if a memory slot is a positive integer constant scalar value. + // 'mode' can be: + // { 0=constant | 1=integer constant | 2=positive integer constant | 3=strictly-positive integer constant } + void check_constant(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,1,0); + if (!(_cimg_mp_is_constant(arg) && + (!mode || (double)(int)mem[arg]==mem[arg]) && + (mode<2 || mem[arg]>=(mode==3)))) { + const char *s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ": + n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth ": + n_arg==9?"Ninth ":"One of the "; + *se = saved_char; + char *const s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') is not a%s constant, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_arg?"argument":"Argument",s_type(arg)._data, + !mode?"":mode==1?"n integer": + mode==2?" positive integer":" strictly positive integer", + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check a matrix is square. + void check_matrix_square(const unsigned int arg, const unsigned int n_arg, + char *const ss, char *const se, const char saved_char) { + _cimg_mp_check_type(arg,n_arg,2,0); + const unsigned int + siz = _cimg_mp_vector_size(arg), + n = (unsigned int)std::sqrt((float)siz); + if (n*n!=siz) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand "; + else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ":"One "; + *se = saved_char; + char *const s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s%s %s%s (of type '%s') " + "cannot be considered as a square matrix, in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"), + s_type(arg)._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check type compatibility for one argument. + // Bits of 'mode' tells what types are allowed: + // { 1 = scalar | 2 = vectorN }. + // If 'N' is not zero, it also restricts the vectors to be of size N only. + void check_type(const unsigned int arg, const unsigned int n_arg, + const unsigned int mode, const unsigned int N, + char *const ss, char *const se, const char saved_char) { + const bool + is_scalar = _cimg_mp_is_scalar(arg), + is_vector = _cimg_mp_is_vector(arg) && (!N || _cimg_mp_vector_size(arg)==N); + bool cond = false; + if (mode&1) cond|=is_scalar; + if (mode&2) cond|=is_vector; + if (!cond) { + const char *s_arg; + if (*s_op!='F') s_arg = !n_arg?"":n_arg==1?"Left-hand ":"Right-hand "; + else s_arg = !n_arg?"":n_arg==1?"First ":n_arg==2?"Second ":n_arg==3?"Third ": + n_arg==4?"Fourth ":n_arg==5?"Fifth ":n_arg==6?"Sixth ":n_arg==7?"Seventh ":n_arg==8?"Eighth": + n_arg==9?"Ninth":"One of the "; + CImg sb_type(32); + if (mode==1) cimg_snprintf(sb_type,sb_type._width,"'scalar'"); + else if (mode==2) { + if (N) cimg_snprintf(sb_type,sb_type._width,"'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'vector'"); + } else { + if (N) cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector%u'",N); + else cimg_snprintf(sb_type,sb_type._width,"'scalar' or 'vector'"); + } + *se = saved_char; + char *const s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s%s %s%s has invalid type '%s' (should be %s), " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s_arg,*s_op=='F'?(*s_arg?"argument":"Argument"):(*s_arg?"operand":"Operand"), + s_type(arg)._data,sb_type._data, + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check is listin is not empty. + void check_list(const bool is_out, + char *const ss, char *const se, const char saved_char) { + if ((!is_out && !listin) || (is_out && !listout)) { + *se = saved_char; + char *const s0 = ss - 4>expr._data?ss - 4:expr._data; + cimg::strellipsize(s0,64); + throw CImgArgumentException("[_cimg_math_parser] " + "CImg<%s>::%s: %s%s Invalid call with an empty image list, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Check a vector is not 0-dimensional, or with unknown dimension at compile time. + void check_vector0(const unsigned int dim, + char *const ss, char *const se, const char saved_char) { + char *s0 = 0; + if (!dim) { + *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%s Invalid construction of a 0-dimensional vector, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } else if (dim==~0U) { + *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%s Invalid construction of a vector with dynamic size, " + "in expression '%s%s%s'.", + pixel_type(),_cimg_mp_calling_function,s_op,*s_op?":":"", + s0!=expr._data?"...":"",s0,se<&expr.back()?"...":""); + } + } + + // Evaluation functions, known by the parser. + // Defining these functions 'static' ensures that sizeof(mp_func)==sizeof(ulongT), + // so we can store pointers to them directly in the opcode vectors. +#ifdef _mp_arg +#undef _mp_arg +#endif +#define _mp_arg(x) mp.mem[mp.opcode[x]] + + static double mp_abs(_cimg_math_parser& mp) { + return cimg::abs(_mp_arg(2)); + } + + static double mp_add(_cimg_math_parser& mp) { + return _mp_arg(2) + _mp_arg(3); + } + + static double mp_acos(_cimg_math_parser& mp) { + return std::acos(_mp_arg(2)); + } + + static double mp_arg(_cimg_math_parser& mp) { + const int _ind = (int)_mp_arg(4); + const unsigned int + nb_args = (unsigned int)mp.opcode[2] - 4, + ind = _ind<0?_ind + nb_args:(unsigned int)_ind, + siz = (unsigned int)mp.opcode[3]; + if (siz>0) { + if (ind>=nb_args) std::memset(&_mp_arg(1) + 1,0,siz*sizeof(double)); + else std::memcpy(&_mp_arg(1) + 1,&_mp_arg(ind + 4) + 1,siz*sizeof(double)); + return cimg::type::nan(); + } + if (ind>=nb_args) return 0; + return _mp_arg(ind + 4); + } + + static double mp_argmin(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + unsigned int argval = 0; + for (unsigned int i = 4; ival) { val = _val; argval = i - 3; } + } + return (double)argval; + } + + static double mp_asin(_cimg_math_parser& mp) { + return std::asin(_mp_arg(2)); + } + + static double mp_atan(_cimg_math_parser& mp) { + return std::atan(_mp_arg(2)); + } + + static double mp_atan2(_cimg_math_parser& mp) { + return std::atan2(_mp_arg(2),_mp_arg(3)); + } + + static double mp_bitwise_and(_cimg_math_parser& mp) { + return (double)((ulongT)_mp_arg(2) & (ulongT)_mp_arg(3)); + } + + static double mp_bitwise_left_shift(_cimg_math_parser& mp) { + return (double)((longT)_mp_arg(2)<<(unsigned int)_mp_arg(3)); + } + + static double mp_bitwise_not(_cimg_math_parser& mp) { + // Limit result to 32bits such that it can be entirely represented as a 'double'. + return (double)~(unsigned int)_mp_arg(2); + } + + static double mp_bitwise_or(_cimg_math_parser& mp) { + return (double)((ulongT)_mp_arg(2) | (ulongT)_mp_arg(3)); + } + + static double mp_bitwise_right_shift(_cimg_math_parser& mp) { + 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::nan(); + } + + static double mp_breakpoint(_cimg_math_parser& mp) { + cimg_abort_test(); + cimg::unused(mp); + return cimg::type::nan(); + } + + static double mp_cbrt(_cimg_math_parser& mp) { + return cimg::cbrt(_mp_arg(2)); + } + + static double mp_complex_abs(_cimg_math_parser& mp) { + return cimg::_hypot(_mp_arg(2),_mp_arg(3)); + } + + static double mp_complex_conj(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + double *ptrd = &_mp_arg(1) + 1; + *(ptrd++) = *(ptrs++); + *ptrd = -*(ptrs); + return cimg::type::nan(); + } + + static double mp_complex_div_sv(_cimg_math_parser& mp) { + const double + *ptr2 = &_mp_arg(3) + 1, + r1 = _mp_arg(2), + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = r1*r2/denom; + *ptrd = -r1*i2/denom; + return cimg::type::nan(); + } + + static double mp_complex_div_vv(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + const double denom = r2*r2 + i2*i2; + *(ptrd++) = (r1*r2 + i1*i2)/denom; + *ptrd = (r2*i1 - r1*i2)/denom; + return cimg::type::nan(); + } + + static double mp_complex_exp(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1, r = *(ptrs++), i = *(ptrs), er = std::exp(r); + *(ptrd++) = er*std::cos(i); + *(ptrd++) = er*std::sin(i); + return cimg::type::nan(); + } + + static double mp_complex_log(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1, r = *(ptrs++), i = *(ptrs); + *(ptrd++) = 0.5*std::log(r*r + i*i); + *(ptrd++) = std::atan2(i,r); + return cimg::type::nan(); + } + + static double mp_complex_mul(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1, + r1 = *(ptr1++), i1 = *ptr1, + r2 = *(ptr2++), i2 = *ptr2; + double *ptrd = &_mp_arg(1) + 1; + *(ptrd++) = r1*r2 - i1*i2; + *(ptrd++) = r1*i2 + r2*i1; + return cimg::type::nan(); + } + + static void _mp_complex_pow(const double r1, const double i1, + const double r2, const double i2, + double *ptrd) { + double ro, io; + if (cimg::abs(i2)<1e-15) { // Exponent is real + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) { + if (cimg::abs(r2)<1e-15) { ro = 1; io = 0; } + else ro = io = 0; + } else { + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2), + phio = r2*phi1; + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + } else { // Exponent is complex + if (cimg::abs(r1)<1e-15 && cimg::abs(i1)<1e-15) ro = io = 0; + const double + mod1_2 = r1*r1 + i1*i1, + phi1 = std::atan2(i1,r1), + modo = std::pow(mod1_2,0.5*r2)*std::exp(-i2*phi1), + phio = r2*phi1 + 0.5*i2*std::log(mod1_2); + ro = modo*std::cos(phio); + io = modo*std::sin(phio); + } + *(ptrd++) = ro; + *ptrd = io; + } + + static double mp_complex_pow_ss(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_sv(_cimg_math_parser& mp) { + const double val1 = _mp_arg(2), *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(val1,0,ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vs(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, val2 = _mp_arg(3); + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],val2,0,ptrd); + return cimg::type::nan(); + } + + static double mp_complex_pow_vv(_cimg_math_parser& mp) { + const double *ptr1 = &_mp_arg(2) + 1, *ptr2 = &_mp_arg(3) + 1; + double *ptrd = &_mp_arg(1) + 1; + _mp_complex_pow(ptr1[0],ptr1[1],ptr2[0],ptr2[1],ptrd); + return cimg::type::nan(); + } + + static double mp_continue(_cimg_math_parser& mp) { + mp.break_type = 2; + mp.p_code = mp.p_break - 1; + return cimg::type::nan(); + } + + static double mp_cos(_cimg_math_parser& mp) { + return std::cos(_mp_arg(2)); + } + + static double mp_cosh(_cimg_math_parser& mp) { + return std::cosh(_mp_arg(2)); + } + + static double mp_crop(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const int x = (int)_mp_arg(3), y = (int)_mp_arg(4), z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const unsigned int + dx = (unsigned int)mp.opcode[7], + dy = (unsigned int)mp.opcode[8], + dz = (unsigned int)mp.opcode[9], + dc = (unsigned int)mp.opcode[10]; + const bool boundary_conditions = (bool)_mp_arg(11); + unsigned int ind = (unsigned int)mp.opcode[2]; + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + const CImg &img = ind==~0U?mp.imgin:mp.listin[ind]; + if (!img) std::memset(ptrd,0,dx*dy*dz*dc*sizeof(double)); + else CImg(ptrd,dx,dy,dz,dc,true) = img.get_crop(x,y,z,c, + x + dx - 1,y + dy - 1, + z + dz - 1,c + dc - 1, + boundary_conditions); + return cimg::type::nan(); + } + + static double mp_cross(_cimg_math_parser& mp) { + CImg + vout(&_mp_arg(1) + 1,1,3,1,1,true), + v1(&_mp_arg(2) + 1,1,3,1,1,true), + v2(&_mp_arg(3) + 1,1,3,1,1,true); + (vout = v1).cross(v2); + return cimg::type::nan(); + } + + static double mp_cut(_cimg_math_parser& mp) { + double val = _mp_arg(2), cmin = _mp_arg(3), cmax = _mp_arg(4); + return valcmax?cmax:val; + } + + static double mp_debug(_cimg_math_parser& mp) { + CImg expr(mp.opcode[2] - 4); + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(expr); + const ulongT g_target = mp.opcode[1]; + +#ifndef cimg_use_openmp + const unsigned int n_thread = 0; +#else + const unsigned int n_thread = omp_get_thread_num(); +#endif + cimg_pragma_openmp(critical) + { + std::fprintf(cimg::output(), + "\n[_cimg_math_parser] %p[thread #%u]:%*c" + "Start debugging expression '%s', code length %u -> mem[%u] (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)mp.opcode[3],(unsigned int)g_target,mp.mem._width); + std::fflush(cimg::output()); + mp.debug_indent+=3; + } + const CImg *const p_end = (++mp.p_code) + mp.opcode[3]; + CImg _op; + for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + + _op.assign(1,op._height - 1); + const ulongT *ptrs = op._data + 1; + for (ulongT *ptrd = _op._data, *const ptrde = _op._data + _op._height; ptrd mem[%u] = %g", + (void*)&mp,n_thread,mp.debug_indent,' ', + (void*)mp.opcode._data,(void*)*mp.opcode,_op.value_string().data(), + (unsigned int)target,mp.mem[target]); + std::fflush(cimg::output()); + } + } + cimg_pragma_openmp(critical) + { + mp.debug_indent-=3; + std::fprintf(cimg::output(), + "\n[_cimg_math_parser] %p[thread #%u]:%*c" + "End debugging expression '%s' -> mem[%u] = %g (memsize: %u)", + (void*)&mp,n_thread,mp.debug_indent,' ', + expr._data,(unsigned int)g_target,mp.mem[g_target],mp.mem._width); + std::fflush(cimg::output()); + } + --mp.p_code; + return mp.mem[g_target]; + } + + static double mp_decrement(_cimg_math_parser& mp) { + return _mp_arg(2) - 1; + } + + static double mp_det(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + return CImg(ptrs,k,k,1,1,true).det(); + } + + static double mp_diag(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int k = (unsigned int)mp.opcode[3]; + CImg(ptrd,k,k,1,1,true) = CImg(ptrs,1,k,1,1,true).get_diagonal(); + return cimg::type::nan(); + } + + static double mp_display_memory(_cimg_math_parser& mp) { + cimg::unused(mp); + std::fputc('\n',cimg::output()); + mp.mem.display("[_cimg_math_parser] Memory snapshot"); + return cimg::type::nan(); + } + + static double mp_display(_cimg_math_parser& mp) { + const unsigned int + _siz = (unsigned int)mp.opcode[3], + siz = _siz?_siz:1; + const double *const ptr = &_mp_arg(1) + (_siz?1:0); + const int + w = (int)_mp_arg(4), + h = (int)_mp_arg(5), + d = (int)_mp_arg(6), + s = (int)_mp_arg(7); + CImg img; + if (w>0 && h>0 && d>0 && s>0) { + if ((unsigned int)w*h*d*s<=siz) img.assign(ptr,w,h,d,s,true); + else img.assign(ptr,siz).resize(w,h,d,s,-1); + } else img.assign(ptr,1,siz,1,1,true); + + CImg expr(mp.opcode[2] - 8); + const ulongT *ptrs = mp.opcode._data + 8; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + ((CImg::string("[_cimg_math_parser] ",false,true),expr)>'x').move_to(expr); + cimg::strellipsize(expr); + std::fputc('\n',cimg::output()); + img.display(expr._data); + return cimg::type::nan(); + } + + static double mp_div(_cimg_math_parser& mp) { + return _mp_arg(2)/_mp_arg(3); + } + + static double mp_dot(_cimg_math_parser& mp) { + const unsigned int siz = (unsigned int)mp.opcode[4]; + return CImg(&_mp_arg(2) + 1,1,siz,1,1,true). + dot(CImg(&_mp_arg(3) + 1,1,siz,1,1,true)); + } + + static double mp_dowhile(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_body = ++mp.p_code, + *const p_cond = p_body + mp.opcode[3], + *const p_end = p_cond + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_body; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + for (mp.p_code = p_cond; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (mp.mem[mem_cond]); + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_draw(_cimg_math_parser& mp) { + const int x = (int)_mp_arg(4), y = (int)_mp_arg(5), z = (int)_mp_arg(6), c = (int)_mp_arg(7); + unsigned int ind = (unsigned int)mp.opcode[3]; + + if (ind!=~0U) ind = (unsigned int)cimg::mod((int)_mp_arg(3),mp.listin.width()); + CImg &img = ind==~0U?mp.imgout:mp.listout[ind]; + unsigned int + dx = (unsigned int)mp.opcode[8], + dy = (unsigned int)mp.opcode[9], + dz = (unsigned int)mp.opcode[10], + dc = (unsigned int)mp.opcode[11]; + dx = dx==~0U?img._width:(unsigned int)_mp_arg(8); + dy = dy==~0U?img._height:(unsigned int)_mp_arg(9); + dz = dz==~0U?img._depth:(unsigned int)_mp_arg(10); + dc = dc==~0U?img._spectrum:(unsigned int)_mp_arg(11); + + const ulongT sizS = mp.opcode[2]; + if (sizS<(ulongT)dx*dy*dz*dc) + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Function 'draw()': " + "Sprite dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + CImg S(&_mp_arg(1) + 1,dx,dy,dz,dc,true); + const float opacity = (float)_mp_arg(12); + + if (img) { + if (mp.opcode[13]!=~0U) { // Opacity mask specified + const ulongT sizM = mp.opcode[14]; + if (sizM<(ulongT)dx*dy*dz) + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Function 'draw()': " + "Mask dimension (%lu values) and specified sprite geometry (%u,%u,%u,%u) " + "(%lu values) do not match.", + mp.imgin.pixel_type(),sizS,dx,dy,dz,dc,(ulongT)dx*dy*dz*dc); + const CImg M(&_mp_arg(13) + 1,dx,dy,dz,(unsigned int)(sizM/(dx*dy*dz)),true); + img.draw_image(x,y,z,c,S,M,opacity,(float)_mp_arg(15)); + } else img.draw_image(x,y,z,c,S,opacity); + } + return cimg::type::nan(); + } + + static double mp_eq(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)==_mp_arg(3)); + } + + static double mp_exp(_cimg_math_parser& mp) { + return std::exp(_mp_arg(2)); + } + + static double mp_eye(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int k = (unsigned int)mp.opcode[2]; + CImg(ptrd,k,k,1,1,true).identity_matrix(); + return cimg::type::nan(); + } + + static double mp_factorial(_cimg_math_parser& mp) { + return cimg::factorial(_mp_arg(2)); + } + + static double mp_fibonacci(_cimg_math_parser& mp) { + return cimg::fibonacci((int)_mp_arg(2)); + } + + static double mp_find(_cimg_math_parser& mp) { + const bool is_forward = (bool)_mp_arg(5); + const ulongT siz = (ulongT)mp.opcode[3]; + longT ind = (longT)(mp.opcode[6]!=_cimg_mp_slot_nan?_mp_arg(6):is_forward?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const double + *const ptrb = &_mp_arg(2) + 1, + *const ptre = ptrb + siz, + val = _mp_arg(4), + *ptr = ptrb + ind; + + // Forward search + if (is_forward) { + while (ptr=ptrb && *ptr!=val) --ptr; + return ptr=(longT)siz1) return -1.; + const double + *const ptr1b = &_mp_arg(2) + 1, + *const ptr1e = ptr1b + siz1, + *const ptr2b = &_mp_arg(4) + 1, + *const ptr2e = ptr2b + siz2, + *ptr1 = ptr1b + ind, + *p1 = 0, + *p2 = 0; + + // Forward search. + if (is_forward) { + do { + while (ptr1=ptr1b && *ptr1!=*ptr2b) --ptr1; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b); + return p2 + *const p_init = ++mp.p_code, + *const p_cond = p_init + mp.opcode[4], + *const p_body = p_cond + mp.opcode[5], + *const p_post = p_body + mp.opcode[6], + *const p_end = p_post + mp.opcode[7]; + const unsigned int vsiz = (unsigned int)mp.opcode[2]; + bool is_cond = false; + if (mp.opcode[8]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[9]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + + for (mp.p_code = p_init; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + + if (!mp.break_type) do { + for (mp.p_code = p_cond; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) { + for (mp.p_code = p_body; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + + for (mp.p_code = p_post; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_g(_cimg_math_parser& mp) { + cimg::unused(mp); + return cimg::grand(); + } + + static double mp_gauss(_cimg_math_parser& mp) { + const double x = _mp_arg(2), s = _mp_arg(3); + return std::exp(-x*x/(2*s*s))/std::sqrt(2*s*s*cimg::PI); + } + + static double mp_gt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>_mp_arg(3)); + } + + static double mp_gte(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)>=_mp_arg(3)); + } + + static double mp_i(_cimg_math_parser& mp) { + return (double)mp.imgin.atXYZC((int)mp.mem[_cimg_mp_slot_x],(int)mp.mem[_cimg_mp_slot_y], + (int)mp.mem[_cimg_mp_slot_z],(int)mp.mem[_cimg_mp_slot_c],(T)0); + } + + static double mp_if(_cimg_math_parser& mp) { + const bool is_cond = (bool)_mp_arg(2); + const ulongT + mem_left = mp.opcode[3], + mem_right = mp.opcode[4]; + const CImg + *const p_right = ++mp.p_code + mp.opcode[5], + *const p_end = p_right + mp.opcode[6]; + const unsigned int vtarget = (unsigned int)mp.opcode[1], vsiz = (unsigned int)mp.opcode[7]; + if (is_cond) for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + else for (mp.p_code = p_right; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.p_code==mp.p_break) --mp.p_code; + else mp.p_code = p_end - 1; + if (vsiz) std::memcpy(&mp.mem[vtarget] + 1,&mp.mem[is_cond?mem_left:mem_right] + 1,sizeof(double)*vsiz); + return mp.mem[is_cond?mem_left:mem_right]; + } + + static double mp_increment(_cimg_math_parser& mp) { + return _mp_arg(2) + 1; + } + + static double mp_int(_cimg_math_parser& mp) { + return (double)(longT)_mp_arg(2); + } + + static double mp_ioff(_cimg_math_parser& mp) { + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3); + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off<0 || off>=whds) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) return (double)img[cimg::mod(off,whds)]; + return 0; + case 1 : // Neumann boundary + if (img) return (double)(off<0?*img:img.back()); + return 0; + default : // Dirichet boundary + return 0; + } + return (double)img[off]; + } + + static double mp_isbool(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return (double)(val==0.0 || val==1.0); + } + + static double mp_isin(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + const double val = _mp_arg(3); + for (unsigned int i = 4; i::is_inf(_mp_arg(2)); + } + + static double mp_isint(_cimg_math_parser& mp) { + return (double)(cimg::mod(_mp_arg(2),1.0)==0); + } + + static double mp_isnan(_cimg_math_parser& mp) { + return (double)cimg::type::is_nan(_mp_arg(2)); + } + + static double mp_ixyzc(_cimg_math_parser& mp) { + const unsigned int + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.imgin; + const double + x = _mp_arg(2), y = _mp_arg(3), + z = _mp_arg(4), c = _mp_arg(5); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + return (double)img.atXYZC(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + cimg::mod((int)c,img.spectrum())); + if (boundary_conditions==1) + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c); + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()), + cimg::mod((float)c,(float)img.spectrum())); + if (boundary_conditions==1) + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c); + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,(T)0); + } + } + + static double mp_joff(_cimg_math_parser& mp) { + const unsigned int + boundary_conditions = (unsigned int)_mp_arg(3); + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const CImg &img = mp.imgin; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + if (off<0 || off>=whds) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) return (double)img[cimg::mod(off,whds)]; + return 0; + case 1 : // Neumann boundary + if (img) return (double)(off<0?*img:img.back()); + return 0; + default : // Dirichet boundary + return 0; + } + return (double)img[off]; + } + + static double mp_jxyzc(_cimg_math_parser& mp) { + const unsigned int + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), + z = oz + _mp_arg(4), c = oc + _mp_arg(5); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + return (double)img.atXYZC(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + cimg::mod((int)c,img.spectrum())); + if (boundary_conditions==1) + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c); + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()), + cimg::mod((float)c,(float)img.spectrum())); + if (boundary_conditions==1) + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c); + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,(T)0); + } + } + + static double mp_kth(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 4); + double *p = vals.data(); + for (unsigned int i = 4; i &img = mp.listin[indi]; + const bool is_forward = (bool)_mp_arg(4); + const ulongT siz = (ulongT)img.size(); + longT ind = (longT)(mp.opcode[5]!=_cimg_mp_slot_nan?_mp_arg(5):is_forward?0:siz - 1); + if (ind<0 || ind>=(longT)siz) return -1.; + const T + *const ptrb = img.data(), + *const ptre = img.end(), + *ptr = ptrb + ind; + const double val = _mp_arg(3); + + // Forward search + if (is_forward) { + while (ptr=ptrb && (double)*ptr!=val) --ptr; + return ptr &img = mp.listin[indi]; + const bool is_forward = (bool)_mp_arg(5); + const ulongT + siz1 = (ulongT)img.size(), + siz2 = (ulongT)mp.opcode[4]; + longT ind = (longT)(mp.opcode[6]!=_cimg_mp_slot_nan?_mp_arg(6):is_forward?0:siz1 - 1); + if (ind<0 || ind>=(longT)siz1) return -1.; + const T + *const ptr1b = img.data(), + *const ptr1e = ptr1b + siz1, + *ptr1 = ptr1b + ind, + *p1 = 0; + const double + *const ptr2b = &_mp_arg(3) + 1, + *const ptr2e = ptr2b + siz2, + *p2 = 0; + + // Forward search. + if (is_forward) { + do { + while (ptr1=ptr1b && *ptr1!=*ptr2b) --ptr1; + p1 = ptr1 + 1; + p2 = ptr2b + 1; + while (p1=ptr1b); + return p2 &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off<0 || off>=whds) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) return (double)img[cimg::mod(off,whds)]; + return 0; + case 1 : // Neumann boundary + if (img) return (double)(off<0?*img:img.back()); + return 0; + default : // Dirichet boundary + return 0; + } + return (double)img[off]; + } + + static double mp_list_is_shared(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._is_shared; + } + + static double mp_list_ixyzc(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(7), + boundary_conditions = (unsigned int)_mp_arg(8); + const CImg &img = mp.listin[ind]; + const double + x = _mp_arg(3), y = _mp_arg(4), + z = _mp_arg(5), c = _mp_arg(6); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + return (double)img.atXYZC(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + cimg::mod((int)c,img.spectrum())); + if (boundary_conditions==1) + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c); + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()), + cimg::mod((float)c,(float)img.spectrum())); + if (boundary_conditions==1) + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c); + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,(T)0); + } + } + + static double mp_list_joff(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4); + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const CImg &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + if (off<0 || off>=whds) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) return (double)img[cimg::mod(off,whds)]; + return 0; + case 1 : // Neumann boundary + if (img) return (double)(off<0?*img:img.back()); + return 0; + default : // Dirichet boundary + return 0; + } + return (double)img[off]; + } + + static double mp_list_jxyzc(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(7), + boundary_conditions = (unsigned int)_mp_arg(8); + const CImg &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), + z = oz + _mp_arg(5), c = oc + _mp_arg(6); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + return (double)img.atXYZC(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + cimg::mod((int)c,img.spectrum())); + if (boundary_conditions==1) + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c); + return (double)img.atXYZC((int)x,(int)y,(int)z,(int)c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + return (double)img.linear_atXYZC(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()), + cimg::mod((float)c,(float)img.spectrum())); + if (boundary_conditions==1) + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c); + return (double)img.linear_atXYZC((float)x,(float)y,(float)z,(float)c,(T)0); + } + } + + static double mp_list_median(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + if (!mp.list_median) mp.list_median.assign(mp.listin._width); + if (!mp.list_median[ind]) CImg::vector(mp.listin[ind].median()).move_to(mp.list_median[ind]); + return *mp.list_median[ind]; + } + + static double mp_list_set_ioff(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), y = (int)_mp_arg(4), + z = (int)_mp_arg(5), c = (int)_mp_arg(6); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(3)), y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)), c = (int)(oc + _mp_arg(6)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Ixyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const int + x = (int)_mp_arg(3), + y = (int)_mp_arg(4), + z = (int)_mp_arg(5); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_set_Joff_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.listout[ind]; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_list_set_Jxyz_s(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + CImg &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.listout[ind]; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(3)), + y = (int)(oy + _mp_arg(4)), + z = (int)(oz + _mp_arg(5)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_list_spectrum(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._spectrum; + } + + static double mp_list_stats(_cimg_math_parser& mp) { + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + k = (unsigned int)_mp_arg(3); + if (!mp.list_stats) mp.list_stats.assign(mp.listin._width); + if (!mp.list_stats[ind]) mp.list_stats[ind].assign(1,14,1,1,0).fill(mp.listin[ind].get_stats(),false); + return mp.list_stats(ind,k); + } + + static double mp_list_wh(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height; + } + + static double mp_list_whd(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth; + } + + static double mp_list_whds(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width*mp.listin[ind]._height*mp.listin[ind]._depth*mp.listin[ind]._spectrum; + } + + static double mp_list_width(_cimg_math_parser& mp) { + const unsigned int ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()); + return (double)mp.listin[ind]._width; + } + + static double mp_list_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4); + const CImg &img = mp.listin[ind]; + const longT + off = (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off<0 || off>=whd) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) { + ptrs = &img[cimg::mod(off,whd)]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + case 1 : // Neumann boundary + if (img) { + ptrs = off<0?img._data:&img.back(); + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + default : // Dirichet boundary + std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + } + ptrs = &img[off]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + } + + static double mp_list_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.listin[ind]; + const double x = _mp_arg(3), y = _mp_arg(4), z = _mp_arg(5); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()),c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,(T)0); + } + return cimg::type::nan(); + } + + static double mp_list_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + boundary_conditions = (unsigned int)_mp_arg(4); + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], oz = (int)mp.mem[_cimg_mp_slot_z]; + const CImg &img = mp.listin[ind]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(3), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off<0 || off>=whd) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) { + ptrs = &img[cimg::mod(off,whd)]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + case 1 : // Neumann boundary + if (img) { + ptrs = off<0?img._data:&img.back(); + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + default : // Dirichet boundary + std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + } + ptrs = &img[off]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + } + + static double mp_list_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + ind = (unsigned int)cimg::mod((int)_mp_arg(2),mp.listin.width()), + interpolation = (unsigned int)_mp_arg(6), + boundary_conditions = (unsigned int)_mp_arg(7); + const CImg &img = mp.listin[ind]; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(3), y = oy + _mp_arg(4), z = oz + _mp_arg(5); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()),c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,(T)0); + } + return cimg::type::nan(); + } + + static double mp_log(_cimg_math_parser& mp) { + return std::log(_mp_arg(2)); + } + + static double mp_log10(_cimg_math_parser& mp) { + return std::log10(_mp_arg(2)); + } + + static double mp_log2(_cimg_math_parser& mp) { + return cimg::log2(_mp_arg(2)); + } + + static double mp_logical_and(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (!val_left) { mp.p_code = p_end - 1; return 0; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_logical_not(_cimg_math_parser& mp) { + return (double)!_mp_arg(2); + } + + static double mp_logical_or(_cimg_math_parser& mp) { + const bool val_left = (bool)_mp_arg(2); + const CImg *const p_end = ++mp.p_code + mp.opcode[4]; + if (val_left) { mp.p_code = p_end - 1; return 1; } + const ulongT mem_right = mp.opcode[3]; + for ( ; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + --mp.p_code; + return (double)(bool)mp.mem[mem_right]; + } + + static double mp_lowercase(_cimg_math_parser& mp) { + return cimg::lowercase(_mp_arg(2)); + } + + static double mp_lt(_cimg_math_parser& mp) { + return (double)(_mp_arg(2)<_mp_arg(3)); + } + + static double mp_lte(_cimg_math_parser& mp) { + 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 val, vec; + CImg(ptr1,k,k,1,1,true).symmetric_eigen(val,vec); + CImg(ptrd,1,k,1,1,true) = val; + CImg(ptrd + k,k,k,1,1,true) = vec.get_transpose(); + return cimg::type::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(ptrd,k,k,1,1,true) = CImg(ptr1,k,k,1,1,true).get_invert(); + return cimg::type::nan(); + } + + static double mp_matrix_mul(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr1,l,k,1,1,true)*CImg(ptr2,m,l,1,1,true); + return cimg::type::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(ptrd,l,k,1,1,true) = CImg(ptr1,k,l,1,1,true).get_pseudoinvert(); + return cimg::type::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 U, S, V; + CImg(ptr1,k,l,1,1,true).SVD(U,S,V); + CImg(ptrd,k,l,1,1,true) = U; + CImg(ptrd + k*l,1,k,1,1,true) = S; + CImg(ptrd + k*l + k,k,k,1,1,true) = V; + return cimg::type::nan(); + } + + static double mp_max(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i=mp.mem.width()) + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds variable pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %u).", + mp.imgin.pixel_type(),siz,inc,off,eoff,mp.mem._width - 1); + return &mp.mem[off]; + } + + static float* _mp_memcopy_float(_cimg_math_parser& mp, const ulongT *const p_ref, + const longT siz, const long inc) { + const unsigned ind = (unsigned int)p_ref[1]; + const CImg &img = ind==~0U?mp.imgin:mp.listin[cimg::mod((int)mp.mem[ind],mp.listin.width())]; + const bool is_relative = (bool)p_ref[2]; + int ox, oy, oz, oc; + longT off = 0; + if (is_relative) { + ox = (int)mp.mem[_cimg_mp_slot_x]; + oy = (int)mp.mem[_cimg_mp_slot_y]; + oz = (int)mp.mem[_cimg_mp_slot_z]; + oc = (int)mp.mem[_cimg_mp_slot_c]; + off = img.offset(ox,oy,oz,oc); + } + if ((*p_ref)%2) { + const int + x = (int)mp.mem[p_ref[3]], + y = (int)mp.mem[p_ref[4]], + z = (int)mp.mem[p_ref[5]], + c = *p_ref==5?0:(int)mp.mem[p_ref[6]]; + off+=img.offset(x,y,z,c); + } else off+=(longT)mp.mem[p_ref[3]]; + const longT eoff = off + (siz - 1)*inc; + if (off<0 || eoff>=(longT)img.size()) + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Function 'copy()': " + "Out-of-bounds image pointer " + "(length: %ld, increment: %ld, offset start: %ld, " + "offset end: %ld, offset max: %lu).", + mp.imgin.pixel_type(),siz,inc,off,eoff,img.size() - 1); + return (float*)&img[off]; + } + + static double mp_memcopy(_cimg_math_parser& mp) { + longT siz = (longT)_mp_arg(4); + const longT inc_d = (longT)_mp_arg(5), inc_s = (longT)_mp_arg(6); + const float + _opacity = (float)_mp_arg(7), + opacity = (float)cimg::abs(_opacity), + omopacity = 1 - std::max(_opacity,0.0f); + if (siz>0) { + const bool + is_doubled = mp.opcode[8]<=1, + is_doubles = mp.opcode[15]<=1; + if (is_doubled && is_doubles) { // (double*) <- (double*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(double)); + else std::memmove(ptrd,ptrs,siz*sizeof(double)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,double) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } else if (is_doubled && !is_doubles) { // (double*) <- (float*) + double *ptrd = _mp_memcopy_double(mp,(unsigned int)mp.opcode[2],&mp.opcode[8],siz,inc_d); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s); + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + _opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else if (!is_doubled && is_doubles) { // (float*) <- (double*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d); + const double *ptrs = _mp_memcopy_double(mp,(unsigned int)mp.opcode[3],&mp.opcode[15],siz,inc_s); + if (_opacity>=1) while (siz-->0) { *ptrd = (float)*ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = (float)(omopacity**ptrd + opacity**ptrs); ptrd+=inc_d; ptrs+=inc_s; } + } else { // (float*) <- (float*) + float *ptrd = _mp_memcopy_float(mp,&mp.opcode[8],siz,inc_d); + const float *ptrs = _mp_memcopy_float(mp,&mp.opcode[15],siz,inc_s); + if (inc_d==1 && inc_s==1 && _opacity>=1) { + if (ptrs + siz - 1ptrd + siz - 1) std::memcpy(ptrd,ptrs,siz*sizeof(float)); + else std::memmove(ptrd,ptrs,siz*sizeof(float)); + } else { + if (ptrs + (siz - 1)*inc_sptrd + (siz - 1)*inc_d) { + if (_opacity>=1) while (siz-->0) { *ptrd = *ptrs; ptrd+=inc_d; ptrs+=inc_s; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**ptrs; ptrd+=inc_d; ptrs+=inc_s; } + } else { // Overlapping buffers + CImg buf((unsigned int)siz); + cimg_for(buf,ptr,float) { *ptr = *ptrs; ptrs+=inc_s; } + ptrs = buf; + if (_opacity>=1) while (siz-->0) { *ptrd = *(ptrs++); ptrd+=inc_d; } + else while (siz-->0) { *ptrd = omopacity**ptrd + opacity**(ptrs++); ptrd+=inc_d; } + } + } + } + } + return _mp_arg(1); + } + + static double mp_min(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; ires) res = val; + } + return res; + } + + static double mp_normp(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + if (i_end==4) return cimg::abs(_mp_arg(3)); + const double p = (double)mp.opcode[3]; + double res = 0; + for (unsigned int i = 4; i0?res:0.0; + } + + static double mp_permutations(_cimg_math_parser& mp) { + return cimg::permutations(_mp_arg(2),_mp_arg(3),(bool)_mp_arg(4)); + } + + static double mp_pow(_cimg_math_parser& mp) { + const double v = _mp_arg(2), p = _mp_arg(3); + return std::pow(v,p); + } + + static double mp_pow0_25(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return std::sqrt(std::sqrt(val)); + } + + static double mp_pow3(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val; + } + + static double mp_pow4(_cimg_math_parser& mp) { + const double val = _mp_arg(2); + return val*val*val*val; + } + + static double mp_print(_cimg_math_parser& mp) { + const double val = _mp_arg(1); + cimg_pragma_openmp(critical) + { + CImg expr(mp.opcode[2] - 3); + const ulongT *ptrs = mp.opcode._data + 3; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(expr); + cimg::mutex(6); + std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = %g",expr._data,val); + std::fflush(cimg::output()); + cimg::mutex(6,0); + } + return val; + } + + static double mp_prod(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + double val = _mp_arg(3); + for (unsigned int i = 4; i::nan(); + } + + static double mp_rot3d(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const float x = (float)_mp_arg(2), y = (float)_mp_arg(3), z = (float)_mp_arg(4), theta = (float)_mp_arg(5); + CImg(ptrd,3,3,1,1,true) = CImg::rotation_matrix(x,y,z,theta); + return cimg::type::nan(); + } + + static double mp_round(_cimg_math_parser& mp) { + return cimg::round(_mp_arg(2),_mp_arg(3),(int)_mp_arg(4)); + } + + static double mp_self_add(_cimg_math_parser& mp) { + return _mp_arg(1)+=_mp_arg(2); + } + + static double mp_self_bitwise_and(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((ulongT)val & (ulongT)_mp_arg(2)); + } + + static double mp_self_bitwise_left_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val<<(unsigned int)_mp_arg(2)); + } + + static double mp_self_bitwise_or(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((ulongT)val | (ulongT)_mp_arg(2)); + } + + static double mp_self_bitwise_right_shift(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = (double)((longT)val>>(unsigned int)_mp_arg(2)); + } + + static double mp_self_decrement(_cimg_math_parser& mp) { + return --_mp_arg(1); + } + + static double mp_self_increment(_cimg_math_parser& mp) { + return ++_mp_arg(1); + } + + static double mp_self_map_vector_s(_cimg_math_parser& mp) { // Vector += scalar + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2]; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode[2] = mp.opcode[4]; // Scalar argument. + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1]; + while (siz-->0) { target = ptrd++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_map_vector_v(_cimg_math_parser& mp) { // Vector += vector + unsigned int + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &target = mp.opcode[1], &argument = mp.opcode[2]; + while (siz-->0) { target = ptrd++; argument = ptrs++; (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_self_mul(_cimg_math_parser& mp) { + return _mp_arg(1)*=_mp_arg(2); + } + + static double mp_self_div(_cimg_math_parser& mp) { + return _mp_arg(1)/=_mp_arg(2); + } + + static double mp_self_modulo(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = cimg::mod(val,_mp_arg(2)); + } + + static double mp_self_pow(_cimg_math_parser& mp) { + double &val = _mp_arg(1); + return val = std::pow(val,_mp_arg(2)); + } + + static double mp_self_sub(_cimg_math_parser& mp) { + return _mp_arg(1)-=_mp_arg(2); + } + + static double mp_set_ioff(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + x = (int)_mp_arg(2), y = (int)_mp_arg(3), + z = (int)_mp_arg(4), c = (int)_mp_arg(5); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whds = (longT)img.size(); + const double val = _mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], + oz = mp.mem[_cimg_mp_slot_z], oc = mp.mem[_cimg_mp_slot_c]; + const int + x = (int)(ox + _mp_arg(2)), y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)), c = (int)(oc + _mp_arg(5)); + const double val = _mp_arg(1); + if (x>=0 && x=0 && y=0 && z=0 && c &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Ixyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const int + x = (int)_mp_arg(2), + y = (int)_mp_arg(3), + z = (int)_mp_arg(4); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_set_Joff_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T val = (T)_mp_arg(1); + if (off>=0 && off &img = mp.imgout; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z], oc = (int)mp.mem[_cimg_mp_slot_c]; + const longT + off = img.offset(ox,oy,oz,oc) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const double *ptrs = &_mp_arg(1) + 1; + if (off>=0 && off::nan(); + } + + static double mp_set_Jxyz_s(_cimg_math_parser& mp) { + CImg &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const T val = (T)_mp_arg(1); + if (x>=0 && x=0 && y=0 && z &img = mp.imgout; + const double ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z]; + const int + x = (int)(ox + _mp_arg(2)), + y = (int)(oy + _mp_arg(3)), + z = (int)(oz + _mp_arg(4)); + const double *ptrs = &_mp_arg(1) + 1; + if (x>=0 && x=0 && y=0 && z::nan(); + } + + static double mp_sign(_cimg_math_parser& mp) { + return cimg::sign(_mp_arg(2)); + } + + static double mp_sin(_cimg_math_parser& mp) { + return std::sin(_mp_arg(2)); + } + + static double mp_sinc(_cimg_math_parser& mp) { + return cimg::sinc(_mp_arg(2)); + } + + static double mp_single(_cimg_math_parser& mp) { + const double res = _mp_arg(1); + cimg_pragma_openmp(critical) + { + for (const CImg *const p_end = ++mp.p_code + mp.opcode[2]; + mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + } + --mp.p_code; + return res; + } + + static double mp_sinh(_cimg_math_parser& mp) { + return std::sinh(_mp_arg(2)); + } + + static double mp_solve(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(3) + 1; + const unsigned int + k = (unsigned int)mp.opcode[4], + l = (unsigned int)mp.opcode[5], + m = (unsigned int)mp.opcode[6]; + CImg(ptrd,m,k,1,1,true) = CImg(ptr2,m,l,1,1,true).get_solve(CImg(ptr1,k,l,1,1,true)); + return cimg::type::nan(); + } + + static double mp_sort(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int + siz = (unsigned int)mp.opcode[3], + chunk_siz = (unsigned int)mp.opcode[5]; + const bool is_increasing = (bool)_mp_arg(4); + CImg(ptrd,chunk_siz,siz/chunk_siz,1,1,true) = CImg(ptrs,chunk_siz,siz/chunk_siz,1,1,true). + get_sort(is_increasing,chunk_siz>1?'y':0); + return cimg::type::nan(); + } + + static double mp_sqr(_cimg_math_parser& mp) { + return cimg::sqr(_mp_arg(2)); + } + + static double mp_sqrt(_cimg_math_parser& mp) { + return std::sqrt(_mp_arg(2)); + } + + static double mp_std(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i0) mp.mem[ptrd++] = (double)*(ptrs++); + return cimg::type::nan(); + } + + static double mp_stod(_cimg_math_parser& mp) { + const double *ptrs = &_mp_arg(2); + const unsigned int siz = (unsigned int)_mp_arg(3); + const bool is_strict = (bool)_mp_arg(4); + if (!siz) return *ptrs>='0' && *ptrs<='9'?*ptrs - '0':cimg::type::nan(); + CImg ss(siz + 1); + double val = cimg::type::nan(); + char sep; + for (unsigned i = 0; i::inf(); err = 1; } + else if (!cimg::strcasecmp(s,"nan")) { val = cimg::type::nan(); err = 1; } + if (err==1 && !is_positive) val = -val; + } +#endif + if (is_strict && err!=1) return cimg::type::nan(); + return val; + } + + static double mp_sub(_cimg_math_parser& mp) { + return _mp_arg(2) - _mp_arg(3); + } + + 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 = 4; i(ptrs,k,k,1,1,true).trace(); + } + + static double mp_transp(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const double *ptrs = &_mp_arg(2) + 1; + const unsigned int + k = (unsigned int)mp.opcode[3], + l = (unsigned int)mp.opcode[4]; + CImg(ptrd,l,k,1,1,true) = CImg(ptrs,k,l,1,1,true).get_transpose(); + return cimg::type::nan(); + } + + static double mp_u(_cimg_math_parser& mp) { + return cimg::rand(_mp_arg(2),_mp_arg(3)); + } + + static double mp_uppercase(_cimg_math_parser& mp) { + return cimg::uppercase(_mp_arg(2)); + } + + static double mp_variance(_cimg_math_parser& mp) { + const unsigned int i_end = (unsigned int)mp.opcode[2]; + CImg vals(i_end - 3); + double *p = vals.data(); + for (unsigned int i = 3; i::nan(); + } + + static double mp_vector_crop(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const longT + length = (longT)mp.opcode[3], + start = (longT)_mp_arg(4), + sublength = (longT)mp.opcode[5]; + if (start<0 || start + sublength>length) + throw CImgArgumentException("[_cimg_math_parser] CImg<%s>: Value accessor '[]': " + "Out-of-bounds sub-vector request " + "(length: %ld, start: %ld, sub-length: %ld).", + mp.imgin.pixel_type(),length,start,sublength); + std::memcpy(ptrd,ptrs + start,sublength*sizeof(double)); + return cimg::type::nan(); + } + + static double mp_vector_init(_cimg_math_parser& mp) { + unsigned int + ptrs = 4U, + ptrd = (unsigned int)mp.opcode[1] + 1, + siz = (unsigned int)mp.opcode[3]; + switch (mp.opcode[2] - 4) { + case 0 : std::memset(mp.mem._data + ptrd,0,siz*sizeof(double)); break; // 0 values given + case 1 : { const double val = _mp_arg(ptrs); while (siz-->0) mp.mem[ptrd++] = val; } break; + default : while (siz-->0) { mp.mem[ptrd++] = _mp_arg(ptrs++); if (ptrs>=mp.opcode[2]) ptrs = 4U; } + } + return cimg::type::nan(); + } + + static double mp_vector_eq(_cimg_math_parser& mp) { + const double + *ptr1 = &_mp_arg(2) + 1, + *ptr2 = &_mp_arg(4) + 1; + unsigned int p1 = (unsigned int)mp.opcode[3], p2 = (unsigned int)mp.opcode[5], n; + const int N = (int)_mp_arg(6); + const bool case_sensitive = (bool)_mp_arg(7); + bool still_equal = true; + double value; + if (!N) return true; + + // Compare all values. + if (N<0) { + if (p1>0 && p2>0) { // Vector == vector + if (p1!=p2) return false; + if (case_sensitive) + while (still_equal && p1--) still_equal = *(ptr1++)==*(ptr2++); + else + while (still_equal && p1--) + still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p1--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && p2--) still_equal = *(ptr2++)==value; + return still_equal; + } else { // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + else return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + } + + // Compare only first N values. + if (p1>0 && p2>0) { // Vector == vector + n = cimg::min((unsigned int)N,p1,p2); + if (case_sensitive) + while (still_equal && n--) still_equal = *(ptr1++)==(*ptr2++); + else + while (still_equal && n--) still_equal = cimg::lowercase(*(ptr1++))==cimg::lowercase(*(ptr2++)); + return still_equal; + } else if (p1>0 && !p2) { // Vector == scalar + n = std::min((unsigned int)N,p1); + value = _mp_arg(4); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr1++)==value; + return still_equal; + } else if (!p1 && p2>0) { // Scalar == vector + n = std::min((unsigned int)N,p2); + value = _mp_arg(2); + if (!case_sensitive) value = cimg::lowercase(value); + while (still_equal && n--) still_equal = *(ptr2++)==value; + return still_equal; + } // Scalar == scalar + if (case_sensitive) return _mp_arg(2)==_mp_arg(4); + return cimg::lowercase(_mp_arg(2))==cimg::lowercase(_mp_arg(4)); + } + + static double mp_vector_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + return off>=0 && off<(int)siz?mp.mem[ptr + off]:cimg::type::nan(); + } + + static double mp_vector_map_sv(_cimg_math_parser& mp) { // Operator(scalar,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(4); + l_opcode[2] = mp.opcode[4]; // Scalar argument1 + l_opcode.swap(mp.opcode); + ulongT &argument2 = mp.opcode[3]; + while (siz-->0) { argument2 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_v(_cimg_math_parser& mp) { // Operator(vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,3); + l_opcode.swap(mp.opcode); + ulongT &argument = mp.opcode[2]; + while (siz-->0) { argument = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vs(_cimg_math_parser& mp) { // Operator(vector,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vss(_cimg_math_parser& mp) { // Operator(vector,scalar,scalar) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs = (unsigned int)mp.opcode[4] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,5); + l_opcode[3] = mp.opcode[5]; // Scalar argument2 + l_opcode[4] = mp.opcode[6]; // Scalar argument3 + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2]; + while (siz-->0) { argument1 = ptrs++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_map_vv(_cimg_math_parser& mp) { // Operator(vector,vector) + unsigned int + siz = (unsigned int)mp.opcode[2], + ptrs1 = (unsigned int)mp.opcode[4] + 1, + ptrs2 = (unsigned int)mp.opcode[5] + 1; + double *ptrd = &_mp_arg(1) + 1; + mp_func op = (mp_func)mp.opcode[3]; + CImg l_opcode(1,4); + l_opcode.swap(mp.opcode); + ulongT &argument1 = mp.opcode[2], &argument2 = mp.opcode[3]; + while (siz-->0) { argument1 = ptrs1++; argument2 = ptrs2++; *(ptrd++) = (*op)(mp); } + l_opcode.swap(mp.opcode); + return cimg::type::nan(); + } + + static double mp_vector_neq(_cimg_math_parser& mp) { + return !mp_vector_eq(mp); + } + + static double mp_vector_print(_cimg_math_parser& mp) { + cimg_pragma_openmp(critical) + { + CImg expr(mp.opcode[2] - 4); + const ulongT *ptrs = mp.opcode._data + 4; + cimg_for(expr,ptrd,char) *ptrd = (char)*(ptrs++); + cimg::strellipsize(expr); + unsigned int + ptr = (unsigned int)mp.opcode[1] + 1, + siz0 = (unsigned int)mp.opcode[3], + siz = siz0; + cimg::mutex(6); + std::fprintf(cimg::output(),"\n[_cimg_math_parser] %s = [ ",expr._data); + 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); + } + return cimg::type::nan(); + } + + static double mp_vector_resize(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[2], p2 = (unsigned int)mp.opcode[4]; + const int + interpolation = (int)_mp_arg(5), + boundary = (int)_mp_arg(6); + if (p2) { // Resize vector + const double *const ptrs = &_mp_arg(3) + 1; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p2,1,1,1,true). + get_resize(p1,1,1,1,interpolation,boundary); + } else { // Resize scalar + const double value = _mp_arg(3); + CImg(ptrd,p1,1,1,1,true) = CImg(1,1,1,1,value).resize(p1,1,1,1,interpolation,boundary); + } + return cimg::type::nan(); + } + + static double mp_vector_reverse(_cimg_math_parser& mp) { + double *const ptrd = &_mp_arg(1) + 1; + const double *const ptrs = &_mp_arg(2) + 1; + const unsigned int p1 = (unsigned int)mp.opcode[3]; + CImg(ptrd,p1,1,1,1,true) = CImg(ptrs,p1,1,1,1,true).get_mirror('x'); + return cimg::type::nan(); + } + + static double mp_vector_set_off(_cimg_math_parser& mp) { + const unsigned int + ptr = (unsigned int)mp.opcode[2] + 1, + siz = (unsigned int)mp.opcode[3]; + const int off = (int)_mp_arg(4); + if (off>=0 && off<(int)siz) mp.mem[ptr + off] = _mp_arg(5); + return _mp_arg(5); + } + + static double mp_whiledo(_cimg_math_parser& mp) { + const ulongT + mem_body = mp.opcode[1], + mem_cond = mp.opcode[2]; + const CImg + *const p_cond = ++mp.p_code, + *const p_body = p_cond + mp.opcode[3], + *const p_end = p_body + mp.opcode[4]; + const unsigned int vsiz = (unsigned int)mp.opcode[5]; + bool is_cond = false; + if (mp.opcode[6]) { // Set default value for result and condition if necessary + if (vsiz) CImg(&mp.mem[mem_body] + 1,vsiz,1,1,1,true).fill(cimg::type::nan()); + else mp.mem[mem_body] = cimg::type::nan(); + } + if (mp.opcode[7]) mp.mem[mem_cond] = 0; + const unsigned int _break_type = mp.break_type; + mp.break_type = 0; + do { + for (mp.p_code = p_cond; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; + is_cond = (bool)mp.mem[mem_cond]; + if (is_cond && !mp.break_type) // Evaluate body + for (mp.p_code = p_body; mp.p_code &op = *mp.p_code; + mp.opcode._data = op._data; + const ulongT target = mp.opcode[1]; + mp.mem[target] = _cimg_mp_defunc(mp); + } + if (mp.break_type==1) break; else if (mp.break_type==2) mp.break_type = 0; + } while (is_cond); + + mp.break_type = _break_type; + mp.p_code = p_end - 1; + return mp.mem[mem_body]; + } + + static double mp_Ioff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int boundary_conditions = (unsigned int)_mp_arg(3); + const CImg &img = mp.imgin; + const longT + off = (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off<0 || off>=whd) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) { + ptrs = &img[cimg::mod(off,whd)]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + case 1 : // Neumann boundary + if (img) { + ptrs = off<0?img._data:&img[whd - 1]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + default : // Dirichet boundary + std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + } + ptrs = &img[off]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + } + + static double mp_Ixyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6); + const CImg &img = mp.imgin; + const double x = _mp_arg(2), y = _mp_arg(3), z = _mp_arg(4); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()),c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,(T)0); + } + return cimg::type::nan(); + } + + static double mp_Joff(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int boundary_conditions = (unsigned int)_mp_arg(3); + const CImg &img = mp.imgin; + const int + ox = (int)mp.mem[_cimg_mp_slot_x], + oy = (int)mp.mem[_cimg_mp_slot_y], + oz = (int)mp.mem[_cimg_mp_slot_z]; + const longT + off = img.offset(ox,oy,oz) + (longT)_mp_arg(2), + whd = (longT)img.width()*img.height()*img.depth(); + const T *ptrs; + if (off<0 || off>=whd) + switch (boundary_conditions) { + case 2 : // Periodic boundary + if (img) { + ptrs = &img[cimg::mod(off,whd)]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + case 1 : // Neumann boundary + if (img) { + ptrs = off<0?img._data:&img[whd - 1]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + } else std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + default : // Dirichet boundary + std::memset(ptrd,0,img._spectrum*sizeof(double)); + return cimg::type::nan(); + } + ptrs = &img[off]; + cimg_forC(img,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return cimg::type::nan(); + } + + static double mp_Jxyz(_cimg_math_parser& mp) { + double *ptrd = &_mp_arg(1) + 1; + const unsigned int + interpolation = (unsigned int)_mp_arg(5), + boundary_conditions = (unsigned int)_mp_arg(6); + const CImg &img = mp.imgin; + const double + ox = mp.mem[_cimg_mp_slot_x], oy = mp.mem[_cimg_mp_slot_y], oz = mp.mem[_cimg_mp_slot_z], + x = ox + _mp_arg(2), y = oy + _mp_arg(3), z = oz + _mp_arg(4); + if (interpolation==0) { // Nearest neighbor interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ(cimg::mod((int)x,img.width()), + cimg::mod((int)y,img.height()), + cimg::mod((int)z,img.depth()), + c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.atXYZ((int)x,(int)y,(int)z,c,(T)0); + } else { // Linear interpolation + if (boundary_conditions==2) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ(cimg::mod((float)x,(float)img.width()), + cimg::mod((float)y,(float)img.height()), + cimg::mod((float)z,(float)img.depth()),c); + else if (boundary_conditions==1) + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c); + else + cimg_forC(img,c) + *(ptrd++) = (double)img.linear_atXYZ((float)x,(float)y,(float)z,c,(T)0); + } + return cimg::type::nan(); + } + +#undef _mp_arg + + }; // struct _cimg_math_parser {} + + //! Compute the square value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square value \f$I_{(x,y,z,c)}^2\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqr().normalize(0,255)).display(); + \endcode + \image html ref_sqr.jpg + **/ + CImg& sqr() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(val*val); }; + return *this; + } + + //! Compute the square value of each pixel value \newinstance. + CImg get_sqr() const { + return CImg(*this,false).sqr(); + } + + //! Compute the square root of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its square root \f$\sqrt{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg img("reference.jpg"); + (img,img.get_sqrt().normalize(0,255)).display(); + \endcode + \image html ref_sqrt.jpg + **/ + CImg& sqrt() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::sqrt((double)*ptrd); + return *this; + } + + //! Compute the square root of each pixel value \newinstance. + CImg get_sqrt() const { + return CImg(*this,false).sqrt(); + } + + //! Compute the exponential of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its exponential \f$e^{I_{(x,y,z,c)}}\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& exp() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=4096)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::exp((double)*ptrd); + return *this; + } + + //! Compute the exponential of each pixel value \newinstance. + CImg get_exp() const { + return CImg(*this,false).exp(); + } + + //! Compute the logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its logarithm + \f$\mathrm{log}_{e}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& log() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=262144)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::log((double)*ptrd); + return *this; + } + + //! Compute the logarithm of each pixel value \newinstance. + CImg get_log() const { + return CImg(*this,false).log(); + } + + //! Compute the base-2 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-2 logarithm + \f$\mathrm{log}_{2}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& log2() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=4096)) + cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::log2((double)*ptrd); + return *this; + } + + //! Compute the base-10 logarithm of each pixel value \newinstance. + CImg get_log2() const { + return CImg(*this,false).log2(); + } + + //! Compute the base-10 logarithm of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its base-10 logarithm + \f$\mathrm{log}_{10}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& log10() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=4096)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::log10((double)*ptrd); + return *this; + } + + //! Compute the base-10 logarithm of each pixel value \newinstance. + CImg get_log10() const { + return CImg(*this,false).log10(); + } + + //! Compute the absolute value of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its absolute value \f$|I_{(x,y,z,c)}|\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& abs() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=524288)) + cimg_rof(*this,ptrd,T) *ptrd = cimg::abs(*ptrd); + return *this; + } + + //! Compute the absolute value of each pixel value \newinstance. + CImg get_abs() const { + return CImg(*this,false).abs(); + } + + //! Compute the sign of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sign + \f$\mathrm{sign}(I_{(x,y,z,c)})\f$. + \note + - The sign is set to: + - \c 1 if pixel value is strictly positive. + - \c -1 if pixel value is strictly negative. + - \c 0 if pixel value is equal to \c 0. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& sign() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = cimg::sign(*ptrd); + return *this; + } + + //! Compute the sign of each pixel value \newinstance. + CImg get_sign() const { + return CImg(*this,false).sign(); + } + + //! Compute the cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its cosine \f$\cos(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& cos() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::cos((double)*ptrd); + return *this; + } + + //! Compute the cosine of each pixel value \newinstance. + CImg get_cos() const { + return CImg(*this,false).cos(); + } + + //! Compute the sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sine \f$\sin(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being in \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& sin() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::sin((double)*ptrd); + return *this; + } + + //! Compute the sine of each pixel value \newinstance. + CImg get_sin() const { + return CImg(*this,false).sin(); + } + + //! Compute the sinc of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its sinc + \f$\mathrm{sinc}(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& sinc() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=2048)) + cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::sinc((double)*ptrd); + return *this; + } + + //! Compute the sinc of each pixel value \newinstance. + CImg get_sinc() const { + return CImg(*this,false).sinc(); + } + + //! Compute the tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its tangent \f$\tan(I_{(x,y,z,c)})\f$. + \note + - Pixel values are regarded as being exin \e radian. + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& tan() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=2048)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::tan((double)*ptrd); + return *this; + } + + //! Compute the tangent of each pixel value \newinstance. + CImg get_tan() const { + return CImg(*this,false).tan(); + } + + //! Compute the hyperbolic cosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic cosine + \f$\mathrm{cosh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& cosh() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=2048)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::cosh((double)*ptrd); + return *this; + } + + //! Compute the hyperbolic cosine of each pixel value \newinstance. + CImg get_cosh() const { + return CImg(*this,false).cosh(); + } + + //! Compute the hyperbolic sine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic sine + \f$\mathrm{sinh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& sinh() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=2048)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::sinh((double)*ptrd); + return *this; + } + + //! Compute the hyperbolic sine of each pixel value \newinstance. + CImg get_sinh() const { + return CImg(*this,false).sinh(); + } + + //! Compute the hyperbolic tangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its hyperbolic tangent + \f$\mathrm{tanh}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& tanh() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=2048)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::tanh((double)*ptrd); + return *this; + } + + //! Compute the hyperbolic tangent of each pixel value \newinstance. + CImg get_tanh() const { + return CImg(*this,false).tanh(); + } + + //! Compute the arccosine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arccosine + \f$\mathrm{acos}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& acos() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::acos((double)*ptrd); + return *this; + } + + //! Compute the arccosine of each pixel value \newinstance. + CImg get_acos() const { + return CImg(*this,false).acos(); + } + + //! Compute the arcsine of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arcsine + \f$\mathrm{asin}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& asin() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::asin((double)*ptrd); + return *this; + } + + //! Compute the arcsine of each pixel value \newinstance. + CImg get_asin() const { + return CImg(*this,false).asin(); + } + + //! Compute the arctangent of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent + \f$\mathrm{atan}(I_{(x,y,z,c)})\f$. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + **/ + CImg& atan() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::atan((double)*ptrd); + return *this; + } + + //! Compute the arctangent of each pixel value \newinstance. + CImg get_atan() const { + return CImg(*this,false).atan(); + } + + //! Compute the arctangent2 of each pixel value. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its arctangent2 + \f$\mathrm{atan2}(I_{(x,y,z,c)})\f$. + \param img Image whose pixel values specify the second argument of the \c atan2() function. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img_x(100,100,1,1,"x-w/2",false), // Define an horizontal centered gradient, from '-width/2' to 'width/2'. + img_y(100,100,1,1,"y-h/2",false), // Define a vertical centered gradient, from '-height/2' to 'height/2'. + img_atan2 = img_y.get_atan2(img_x); // Compute atan2(y,x) for each pixel value. + (img_x,img_y,img_atan2).display(); + \endcode + **/ + template + CImg& atan2(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return atan2(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_atan2(const CImg& img) const { + return CImg(*this,false).atan2(img); + } + + //! In-place pointwise multiplication. + /** + Compute the pointwise multiplication between the image instance and the specified input image \c img. + \param img Input image, as the second operand of the multiplication. + \note + - Similar to operator+=(const CImg&), except that it performs a pointwise multiplication + instead of an addition. + - It does \e not perform a \e matrix multiplication. For this purpose, use operator*=(const CImg&) instead. + \par Example + \code + CImg + img("reference.jpg"), + shade(img.width,img.height(),1,1,"-(x-w/2)^2-(y-h/2)^2",false); + shade.normalize(0,1); + (img,shade,img.get_mul(shade)).display(); + \endcode + **/ + template + CImg& mul(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return mul(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_mul(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).mul(img); + } + + //! In-place pointwise division. + /** + Similar to mul(const CImg&), except that it performs a pointwise division instead of a multiplication. + **/ + template + CImg& div(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return div(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_div(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).div(img); + } + + //! Raise each pixel value to a specified power. + /** + Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by its power \f$I_{(x,y,z,c)}^p\f$. + \param p Exponent value. + \note + - The \inplace of this method statically casts the computed values to the pixel type \c T. + - The \newinstance returns a \c CImg image, if the pixel type \c T is \e not float-valued. + \par Example + \code + const CImg + img0("reference.jpg"), // Load reference color image. + img1 = (img0/255).pow(1.8)*=255, // Compute gamma correction, with gamma = 1.8. + img2 = (img0/255).pow(0.5)*=255; // Compute gamma correction, with gamma = 0.5. + (img0,img1,img2).display(); + \endcode + **/ + CImg& pow(const double p) { + if (is_empty()) return *this; + if (p==-4) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/(val*val*val*val)); } + return *this; + } + if (p==-3) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/(val*val*val)); } + return *this; + } + if (p==-2) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/(val*val)); } + return *this; + } + if (p==-1) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1.0/val); } + return *this; + } + if (p==-0.5) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = (T)(1/std::sqrt((double)val)); } + return *this; + } + if (p==0) return fill((T)1); + if (p==0.25) return sqrt().sqrt(); + if (p==0.5) return sqrt(); + if (p==1) return *this; + if (p==2) return sqr(); + if (p==3) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=262144)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = val*val*val; } + return *this; + } + if (p==4) { + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=131072)) + cimg_rof(*this,ptrd,T) { const T val = *ptrd; *ptrd = val*val*val*val; } + return *this; + } + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=1024)) + cimg_rof(*this,ptrd,T) *ptrd = (T)std::pow((double)*ptrd,p); + return *this; + } + + //! Raise each pixel value to a specified power \newinstance. + CImg get_pow(const double p) const { + return CImg(*this,false).pow(p); + } + + //! Raise each pixel value to a power, specified from an expression. + /** + Similar to operator+=(const char*), except it performs a pointwise exponentiation instead of an addition. + **/ + CImg& pow(const char *const expression) { + return pow((+*this)._fill(expression,true,true,0,0,"pow",this)); + } + + //! Raise each pixel value to a power, specified from an expression \newinstance. + CImg get_pow(const char *const expression) const { + return CImg(*this,false).pow(expression); + } + + //! Raise each pixel value to a power, pointwisely specified from another image. + /** + Similar to operator+=(const CImg& img), except that it performs an exponentiation instead of an addition. + **/ + template + CImg& pow(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return pow(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_pow(const CImg& img) const { + return CImg(*this,false).pow(img); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(unsigned int), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::rol(*ptrd,n); + return *this; + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const unsigned int n=1) const { + return (+*this).rol(n); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const char*), except that it performs a left rotation instead of a left shift. + **/ + CImg& rol(const char *const expression) { + return rol((+*this)._fill(expression,true,true,0,0,"rol",this)); + } + + //! Compute the bitwise left rotation of each pixel value \newinstance. + CImg get_rol(const char *const expression) const { + return (+*this).rol(expression); + } + + //! Compute the bitwise left rotation of each pixel value. + /** + Similar to operator<<=(const CImg&), except that it performs a left rotation instead of a left shift. + **/ + template + CImg& rol(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return rol(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_rol(const CImg& img) const { + return (+*this).rol(img); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(unsigned int), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const unsigned int n=1) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (T)cimg::ror(*ptrd,n); + return *this; + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const unsigned int n=1) const { + return (+*this).ror(n); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const char*), except that it performs a right rotation instead of a right shift. + **/ + CImg& ror(const char *const expression) { + return ror((+*this)._fill(expression,true,true,0,0,"ror",this)); + } + + //! Compute the bitwise right rotation of each pixel value \newinstance. + CImg get_ror(const char *const expression) const { + return (+*this).ror(expression); + } + + //! Compute the bitwise right rotation of each pixel value. + /** + Similar to operator>>=(const CImg&), except that it performs a right rotation instead of a right shift. + **/ + template + CImg& ror(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return ror(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg get_ror(const CImg& img) const { + return (+*this).ror(img); + } + + //! Pointwise min operator between instance image and a value. + /** + \param val Value used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& min(const T& val) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536)) + cimg_rof(*this,ptrd,T) *ptrd = std::min(*ptrd,val); + return *this; + } + + //! Pointwise min operator between instance image and a value \newinstance. + CImg get_min(const T& val) const { + return (+*this).min(val); + } + + //! Pointwise min operator between two images. + /** + \param img Image used as the reference argument of the min operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& min(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return min(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_min(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).min(img); + } + + //! Pointwise min operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{min}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& min(const char *const expression) { + return min((+*this)._fill(expression,true,true,0,0,"min",this)); + } + + //! Pointwise min operator between an image and an expression \newinstance. + CImg get_min(const char *const expression) const { + return CImg(*this,false).min(expression); + } + + //! Pointwise max operator between instance image and a value. + /** + \param val Value used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{val})\f$. + **/ + CImg& max(const T& val) { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536)) + cimg_rof(*this,ptrd,T) *ptrd = std::max(*ptrd,val); + return *this; + } + + //! Pointwise max operator between instance image and a value \newinstance. + CImg get_max(const T& val) const { + return (+*this).max(val); + } + + //! Pointwise max operator between two images. + /** + \param img Image used as the reference argument of the max operator. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{img}_{(x,y,z,c)})\f$. + **/ + template + CImg& max(const CImg& img) { + const ulongT siz = size(), isiz = img.size(); + if (siz && isiz) { + if (is_overlapped(img)) return max(+img); + T *ptrd = _data, *const ptre = _data + siz; + if (siz>isiz) for (ulongT n = siz/isiz; n; --n) + for (const t *ptrs = img._data, *ptrs_end = ptrs + isiz; ptrs + CImg<_cimg_Tt> get_max(const CImg& img) const { + return CImg<_cimg_Tt>(*this,false).max(img); + } + + //! Pointwise max operator between an image and an expression. + /** + \param expression Math formula as a C-string. + \note Replace each pixel value \f$I_{(x,y,z,c)}\f$ of the image instance by + \f$\mathrm{max}(I_{(x,y,z,c)},\mathrm{expr}_{(x,y,z,c)})\f$. + **/ + CImg& max(const char *const expression) { + return max((+*this)._fill(expression,true,true,0,0,"max",this)); + } + + //! Pointwise max operator between an image and an expression \newinstance. + CImg get_max(const char *const expression) const { + return CImg(*this,false).max(expression); + } + + //! Return a reference to the minimum pixel value. + /** + **/ + T& min() { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min; + cimg_for(*this,ptrs,T) if (*ptrsmax_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the maximum pixel value \const. + const T& max() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max; + cimg_for(*this,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + return *ptr_max; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value. + /** + \param[out] max_val Maximum pixel value. + **/ + template + T& min_max(t& max_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value as well as the maximum pixel value \const. + template + const T& min_max(t& max_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "min_max(): Empty instance.", + cimg_instance); + const T *ptr_min = _data; + T min_value = *ptr_min, max_value = min_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the maximum pixel value as well as the minimum pixel value. + /** + \param[out] min_val Minimum pixel value. + **/ + template + T& max_min(t& min_val) { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "max_min(): Empty instance.", + cimg_instance); + const T *ptr_max = _data; + T max_value = *ptr_max, min_value = max_value; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val arr(*this); + ulongT l = 0, ir = size() - 1; + for ( ; ; ) { + if (ir<=l + 1) { + if (ir==l + 1 && arr[ir]>1; + cimg::swap(arr[mid],arr[l + 1]); + if (arr[l]>arr[ir]) cimg::swap(arr[l],arr[ir]); + if (arr[l + 1]>arr[ir]) cimg::swap(arr[l + 1],arr[ir]); + if (arr[l]>arr[l + 1]) cimg::swap(arr[l],arr[l + 1]); + ulongT i = l + 1, j = ir; + const T pivot = arr[l + 1]; + for ( ; ; ) { + do ++i; while (arr[i]pivot); + if (j=k) ir = j - 1; + if (j<=k) l = i; + } + } + } + + //! Return the median pixel value. + /** + **/ + T median() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "median(): Empty instance.", + cimg_instance); + const ulongT s = size(); + switch (s) { + case 1 : return _data[0]; + case 2 : return cimg::median(_data[0],_data[1]); + case 3 : return cimg::median(_data[0],_data[1],_data[2]); + case 5 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4]); + case 7 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6]); + case 9 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8]); + case 13 : return cimg::median(_data[0],_data[1],_data[2],_data[3],_data[4],_data[5],_data[6],_data[7],_data[8], + _data[9],_data[10],_data[11],_data[12]); + } + const T res = kth_smallest(s>>1); + return (s%2)?res:(T)((res + kth_smallest((s>>1) - 1))/2); + } + + //! Return the product of all the pixel values. + /** + **/ + double product() const { + if (is_empty()) return 0; + double res = 1; + cimg_for(*this,ptrs,T) res*=(double)*ptrs; + return res; + } + + //! Return the sum of all the pixel values. + /** + **/ + double sum() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res; + } + + //! Return the average pixel value. + /** + **/ + double mean() const { + double res = 0; + cimg_for(*this,ptrs,T) res+=(double)*ptrs; + return res/size(); + } + + //! Return the variance of the pixel values. + /** + \param variance_method Method used to estimate the variance. Can be: + - \c 0: Second moment, computed as + \f$1/N \sum\limits_{k=1}^{N} (x_k - \bar x)^2 = + 1/N \left( \sum\limits_{k=1}^N x_k^2 - \left( \sum\limits_{k=1}^N x_k \right)^2 / N \right)\f$ + with \f$ \bar x = 1/N \sum\limits_{k=1}^N x_k \f$. + - \c 1: Best unbiased estimator, computed as \f$\frac{1}{N - 1} \sum\limits_{k=1}^{N} (x_k - \bar x)^2 \f$. + - \c 2: Least median of squares. + - \c 3: Least trimmed of squares. + **/ + double variance(const unsigned int variance_method=1) const { + double foo; + return variance_mean(variance_method,foo); + } + + //! Return the variance as well as the average of the pixel values. + /** + \param variance_method Method used to estimate the variance (see variance(const unsigned int) const). + \param[out] mean Average pixel value. + **/ + template + double variance_mean(const unsigned int variance_method, t& mean) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_mean(): Empty instance.", + cimg_instance); + + double variance = 0, average = 0; + const ulongT siz = size(); + switch (variance_method) { + case 0 : { // Least mean square (standard definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = (S2 - S*S/siz)/siz; + average = S; + } break; + case 1 : { // Least mean square (robust definition) + double S = 0, S2 = 0; + cimg_for(*this,ptrs,T) { const double val = (double)*ptrs; S+=val; S2+=val*val; } + variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + average = S; + } break; + case 2 : { // Least Median of Squares (MAD) + CImg buf(*this,false); + buf.sort(); + const ulongT siz2 = siz>>1; + const double med_i = (double)buf[siz2]; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; *ptrs = (Tfloat)cimg::abs(val - med_i); average+=val; + } + buf.sort(); + const double sig = (double)(1.4828*buf[siz2]); + variance = sig*sig; + } break; + default : { // Least trimmed of Squares + CImg buf(*this,false); + const ulongT siz2 = siz>>1; + cimg_for(buf,ptrs,Tfloat) { + const double val = (double)*ptrs; (*ptrs)=(Tfloat)((*ptrs)*val); average+=val; + } + buf.sort(); + double a = 0; + const Tfloat *ptrs = buf._data; + for (ulongT j = 0; j0?variance:0; + } + + //! Return estimated variance of the noise. + /** + \param variance_method Method used to compute the variance (see variance(const unsigned int) const). + \note Because of structures such as edges in images it is + recommanded to use a robust variance estimation. The variance of the + noise is estimated by computing the variance of the Laplacian \f$(\Delta + I)^2 \f$ scaled by a factor \f$c\f$ insuring \f$ c E[(\Delta I)^2]= + \sigma^2\f$ where \f$\sigma\f$ is the noise variance. + **/ + double variance_noise(const unsigned int variance_method=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "variance_noise(): Empty instance.", + cimg_instance); + + const ulongT siz = size(); + if (!siz || !_data) return 0; + if (variance_method>1) { // Compute a scaled version of the Laplacian. + CImg tmp(*this); + if (_depth==1) { + const double cste = 1.0/std::sqrt(20.0); // Depends on how the Laplacian is computed. + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=262144 && _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3(I,T); + cimg_for3x3(*this,x,y,0,c,I,T) { + tmp(x,y,c) = cste*((double)Inc + (double)Ipc + (double)Icn + + (double)Icp - 4*(double)Icc); + } + } + } else { + const double cste = 1.0/std::sqrt(42.0); // Depends on how the Laplacian is computed. + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=262144 && _spectrum>=2)) + cimg_forC(*this,c) { + CImg_3x3x3(I,T); + cimg_for3x3x3(*this,x,y,z,c,I,T) { + tmp(x,y,z,c) = cste*( + (double)Incc + (double)Ipcc + (double)Icnc + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + } + } + } + return tmp.variance(variance_method); + } + + // Version that doesn't need intermediate images. + double variance = 0, S = 0, S2 = 0; + if (_depth==1) { + const double cste = 1.0/std::sqrt(20.0); + CImg_3x3(I,T); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,T) { + const double val = cste*((double)Inc + (double)Ipc + + (double)Icn + (double)Icp - 4*(double)Icc); + S+=val; S2+=val*val; + } + } else { + const double cste = 1.0/std::sqrt(42.0); + CImg_3x3x3(I,T); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,T) { + const double val = cste * + ((double)Incc + (double)Ipcc + (double)Icnc + + (double)Icpc + + (double)Iccn + (double)Iccp - 6*(double)Iccc); + S+=val; S2+=val*val; + } + } + if (variance_method) variance = siz>1?(S2 - S*S/siz)/(siz - 1):0; + else variance = (S2 - S*S/siz)/siz; + return variance>0?variance:0; + } + + //! Compute the MSE (Mean-Squared Error) between two images. + /** + \param img Image used as the second argument of the MSE operator. + **/ + template + double MSE(const CImg& img) const { + if (img.size()!=size()) + throw CImgArgumentException(_cimg_instance + "MSE(): Instance and specified image (%u,%u,%u,%u,%p) have different dimensions.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + double vMSE = 0; + const t* ptr2 = img._data; + cimg_for(*this,ptr1,T) { + const double diff = (double)*ptr1 - (double)*(ptr2++); + vMSE+=diff*diff; + } + const ulongT siz = img.size(); + if (siz) vMSE/=siz; + return vMSE; + } + + //! Compute the PSNR (Peak Signal-to-Noise Ratio) between two images. + /** + \param img Image used as the second argument of the PSNR operator. + \param max_value Maximum theoretical value of the signal. + **/ + template + double PSNR(const CImg& img, const double max_value=255) const { + const double vMSE = (double)std::sqrt(MSE(img)); + return (vMSE!=0)?(double)(20*std::log10(max_value/vMSE)):(double)(cimg::type::max()); + } + + //! Evaluate math formula. + /** + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + double eval(const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,x,y,z,c,list_inputs,list_outputs); + } + + double _eval(CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression) return 0; + if (!expression[1]) switch (*expression) { // Single-char optimization. + case 'w' : return (double)_width; + case 'h' : return (double)_height; + case 'd' : return (double)_depth; + case 's' : return (double)_spectrum; + case 'r' : return (double)_is_shared; + } + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs); + return mp(x,y,z,c); + } + + //! Evaluate math formula. + /** + \param[out] output Contains values of output vector returned by the evaluated expression + (or is empty if the returned type is scalar). + \param expression Math formula, as a C-string. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \param list_inputs A list of input images attached to the specified math formula. + \param list_outputs A pointer to a list of output images attached to the specified math formula. + **/ + template + void eval(CImg &output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + _eval(output,this,expression,x,y,z,c,list_inputs,list_outputs); + } + + //! Evaluate math formula \const. + template + void eval(CImg& output, const char *const expression, + const double x=0, const double y=0, const double z=0, const double c=0, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + _eval(output,0,expression,x,y,z,c,list_inputs,list_outputs); + } + + template + void _eval(CImg& output, CImg *const img_output, const char *const expression, + const double x, const double y, const double z, const double c, + const CImgList *const list_inputs, CImgList *const list_outputs) const { + if (!expression) { output.assign(1); *output = 0; } + if (!expression[1]) switch (*expression) { // Single-char optimization. + case 'w' : output.assign(1); *output = (t)_width; + case 'h' : output.assign(1); *output = (t)_height; + case 'd' : output.assign(1); *output = (t)_depth; + case 's' : output.assign(1); *output = (t)_spectrum; + case 'r' : output.assign(1); *output = (t)_is_shared; + } + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'),"eval", + *this,img_output,list_inputs,list_outputs); + output.assign(1,std::max(1U,mp.result_dim)); + mp(x,y,z,c,output._data); + } + + //! Evaluate math formula on a set of variables. + /** + \param expression Math formula, as a C-string. + \param xyzc Set of values (x,y,z,c) used for the evaluation. + **/ + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _eval(this,expression,xyzc,list_inputs,list_outputs); + } + + //! Evaluate math formula on a set of variables \const. + template + CImg eval(const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return _eval(0,expression,xyzc,list_inputs,list_outputs); + } + + template + CImg _eval(CImg *const output, const char *const expression, const CImg& xyzc, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + CImg res(1,xyzc.size()/4); + if (!expression) return res.fill(0); + _cimg_math_parser mp(expression,"eval",*this,output,list_inputs,list_outputs); +#ifdef cimg_use_openmp + cimg_pragma_openmp(parallel if (res._height>=512)) + { + _cimg_math_parser + _mp = omp_get_thread_num()?mp:_cimg_math_parser(), + &lmp = omp_get_thread_num()?_mp:mp; + cimg_pragma_openmp(for) + for (unsigned int i = 0; i[min; max; mean; variance; xmin; ymin; zmin; cmin; xmax; ymax; zmax; cmax; sum; product]. + **/ + CImg get_stats(const unsigned int variance_method=1) const { + if (is_empty()) return CImg(); + const ulongT siz = size(); + const T *const odata = _data; + const T *pm = odata, *pM = odata; + double S = 0, S2 = 0, P = _data?1:0; + T m = *pm, M = m; + cimg_for(*this,ptrs,T) { + const T val = *ptrs; + const double _val = (double)val; + if (valM) { M = val; pM = ptrs; } + S+=_val; + S2+=_val*_val; + P*=_val; + } + const double + mean_value = S/siz, + _variance_value = variance_method==0?(S2 - S*S/siz)/siz: + (variance_method==1?(siz>1?(S2 - S*S/siz)/(siz - 1):0): + variance(variance_method)), + variance_value = _variance_value>0?_variance_value:0; + int + xm = 0, ym = 0, zm = 0, cm = 0, + xM = 0, yM = 0, zM = 0, cM = 0; + contains(*pm,xm,ym,zm,cm); + contains(*pM,xM,yM,zM,cM); + return CImg(1,14).fill((double)m,(double)M,mean_value,variance_value, + (double)xm,(double)ym,(double)zm,(double)cm, + (double)xM,(double)yM,(double)zM,(double)cM, + S,P); + } + + //! Compute statistics vector from the pixel values \inplace. + CImg& stats(const unsigned int variance_method=1) { + return get_stats(variance_method).move_to(*this); + } + + //@} + //------------------------------------- + // + //! \name Vector / Matrix Operations + //@{ + //------------------------------------- + + //! Compute norm of the image, viewed as a matrix. + /** + \param magnitude_type Norm type. Can be: + - \c -1: Linf-norm + - \c 0: L2-norm + - \c 1: L1-norm + **/ + double magnitude(const int magnitude_type=2) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "magnitude(): Empty instance.", + cimg_instance); + double res = 0; + switch (magnitude_type) { + case -1 : { + cimg_for(*this,ptrs,T) { const double val = (double)cimg::abs(*ptrs); if (val>res) res = val; } + } break; + case 1 : { + cimg_for(*this,ptrs,T) res+=(double)cimg::abs(*ptrs); + } break; + default : { + cimg_for(*this,ptrs,T) res+=(double)cimg::sqr(*ptrs); + res = (double)std::sqrt(res); + } + } + return res; + } + + //! Compute the trace of the image, viewed as a matrix. + /** + **/ + double trace() const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "trace(): Empty instance.", + cimg_instance); + double res = 0; + cimg_forX(*this,k) res+=(double)(*this)(k,k); + return res; + } + + //! Compute the determinant of the image, viewed as a matrix. + /** + **/ + double det() const { + if (is_empty() || _width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "det(): Instance is not a square matrix.", + cimg_instance); + + switch (_width) { + case 1 : return (double)((*this)(0,0)); + case 2 : return (double)((*this)(0,0))*(double)((*this)(1,1)) - (double)((*this)(0,1))*(double)((*this)(1,0)); + case 3 : { + const double + a = (double)_data[0], d = (double)_data[1], g = (double)_data[2], + b = (double)_data[3], e = (double)_data[4], h = (double)_data[5], + c = (double)_data[6], f = (double)_data[7], i = (double)_data[8]; + return i*a*e - a*h*f - i*b*d + b*g*f + c*d*h - c*g*e; + } + default : { + CImg lu(*this); + CImg indx; + bool d; + lu._LU(indx,d); + double res = d?(double)1:(double)-1; + cimg_forX(lu,i) res*=lu(i,i); + return res; + } + } + } + + //! Compute the dot product between instance and argument, viewed as matrices. + /** + \param img Image used as a second argument of the dot product. + **/ + template + double dot(const CImg& img) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "dot(): Empty instance.", + cimg_instance); + if (!img) + throw CImgArgumentException(_cimg_instance + "dot(): Empty specified image.", + cimg_instance); + + const ulongT nb = std::min(size(),img.size()); + double res = 0; + for (ulongT off = 0; off get_vector_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + CImg res; + if (res._height!=_spectrum) res.assign(1,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + const T *ptrs = data(x,y,z); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get (square) matrix-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \note - The spectrum() of the image must be a square. + **/ + CImg get_matrix_at(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) const { + const int n = (int)std::sqrt((double)_spectrum); + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(n,n); + T *ptrd = res._data; + cimg_forC(*this,c) { *(ptrd++) = *ptrs; ptrs+=whd; } + return res; + } + + //! Get tensor-valued pixel located at specified position. + /** + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + CImg get_tensor_at(const unsigned int x, const unsigned int y=0, const unsigned int z=0) const { + const T *ptrs = data(x,y,z,0); + const ulongT whd = (ulongT)_width*_height*_depth; + if (_spectrum==6) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd),*(ptrs + 3*whd),*(ptrs + 4*whd),*(ptrs + 5*whd)); + if (_spectrum==3) + return tensor(*ptrs,*(ptrs + whd),*(ptrs + 2*whd)); + return tensor(*ptrs); + } + + //! Set vector-valued pixel at specified position. + /** + \param vec Vector to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_vector_at(const CImg& vec, const unsigned int x, const unsigned int y=0, const unsigned int z=0) { + if (x<_width && y<_height && z<_depth) { + const t *ptrs = vec._data; + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = data(x,y,z); + for (unsigned int k = std::min((unsigned int)vec.size(),_spectrum); k; --k) { + *ptrd = (T)*(ptrs++); ptrd+=whd; + } + } + return *this; + } + + //! Set (square) matrix-valued pixel at specified position. + /** + \param mat Matrix to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_matrix_at(const CImg& mat, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + return set_vector_at(mat,x,y,z); + } + + //! Set tensor-valued pixel at specified position. + /** + \param ten Tensor to put on the instance image. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + **/ + template + CImg& set_tensor_at(const CImg& ten, const unsigned int x=0, const unsigned int y=0, const unsigned int z=0) { + T *ptrd = data(x,y,z,0); + const ulongT siz = (ulongT)_width*_height*_depth; + if (ten._height==2) { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[3]; + } + else { + *ptrd = (T)ten[0]; ptrd+=siz; + *ptrd = (T)ten[1]; ptrd+=siz; + *ptrd = (T)ten[2]; ptrd+=siz; + *ptrd = (T)ten[4]; ptrd+=siz; + *ptrd = (T)ten[5]; ptrd+=siz; + *ptrd = (T)ten[8]; + } + return *this; + } + + //! Unroll pixel values along axis \c y. + /** + \note Equivalent to \code unroll('y'); \endcode. + **/ + CImg& vector() { + return unroll('y'); + } + + //! Unroll pixel values along axis \c y \newinstance. + CImg get_vector() const { + return get_unroll('y'); + } + + //! Resize image to become a scalar square matrix. + /** + **/ + CImg& matrix() { + const ulongT siz = size(); + switch (siz) { + case 1 : break; + case 4 : _width = _height = 2; break; + case 9 : _width = _height = 3; break; + case 16 : _width = _height = 4; break; + case 25 : _width = _height = 5; break; + case 36 : _width = _height = 6; break; + case 49 : _width = _height = 7; break; + case 64 : _width = _height = 8; break; + case 81 : _width = _height = 9; break; + case 100 : _width = _height = 10; break; + default : { + ulongT i = 11, i2 = i*i; + while (i2 get_matrix() const { + return (+*this).matrix(); + } + + //! Resize image to become a symmetric tensor. + /** + **/ + CImg& tensor() { + return get_tensor().move_to(*this); + } + + //! Resize image to become a symmetric tensor \newinstance. + CImg get_tensor() const { + CImg res; + const ulongT siz = size(); + switch (siz) { + case 1 : break; + case 3 : + res.assign(2,2); + res(0,0) = (*this)(0); + res(1,0) = res(0,1) = (*this)(1); + res(1,1) = (*this)(2); + break; + case 6 : + res.assign(3,3); + res(0,0) = (*this)(0); + res(1,0) = res(0,1) = (*this)(1); + res(2,0) = res(0,2) = (*this)(2); + res(1,1) = (*this)(3); + res(2,1) = res(1,2) = (*this)(4); + res(2,2) = (*this)(5); + break; + default : + throw CImgInstanceException(_cimg_instance + "tensor(): Invalid instance size (does not define a 1x1, 2x2 or 3x3 tensor).", + cimg_instance); + } + return res; + } + + //! Resize image to become a diagonal matrix. + /** + \note Transform the image as a diagonal matrix so that each of its initial value becomes a diagonal coefficient. + **/ + CImg& diagonal() { + return get_diagonal().move_to(*this); + } + + //! Resize image to become a diagonal matrix \newinstance. + CImg get_diagonal() const { + if (is_empty()) return *this; + const unsigned int siz = (unsigned int)size(); + CImg res(siz,siz,1,1,0); + cimg_foroff(*this,off) res((unsigned int)off,(unsigned int)off) = (*this)[off]; + return res; + } + + //! Replace the image by an identity matrix. + /** + \note If the instance image is not square, it is resized to a square matrix using its maximum + dimension as a reference. + **/ + CImg& identity_matrix() { + return identity_matrix(std::max(_width,_height)).move_to(*this); + } + + //! Replace the image by an identity matrix \newinstance. + CImg get_identity_matrix() const { + return identity_matrix(std::max(_width,_height)); + } + + //! Fill image with a linear sequence of values. + /** + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + CImg& sequence(const T& a0, const T& a1) { + if (is_empty()) return *this; + const ulongT siz = size() - 1; + T* ptr = _data; + if (siz) { + const double delta = (double)a1 - (double)a0; + cimg_foroff(*this,l) *(ptr++) = (T)(a0 + delta*l/siz); + } else *ptr = a0; + return *this; + } + + //! Fill image with a linear sequence of values \newinstance. + CImg get_sequence(const T& a0, const T& a1) const { + return (+*this).sequence(a0,a1); + } + + //! Transpose the image, viewed as a matrix. + /** + \note Equivalent to \code permute_axes("yxzc"); \endcode + **/ + CImg& transpose() { + if (_width==1) { _width = _height; _height = 1; return *this; } + if (_height==1) { _height = _width; _width = 1; return *this; } + if (_width==_height) { + cimg_forYZC(*this,y,z,c) for (int x = y; x get_transpose() const { + return get_permute_axes("yxzc"); + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3d vectors. + /** + \param img Image used as the second argument of the cross product. + \note The first argument of the cross product is \c *this. + **/ + template + CImg& cross(const CImg& img) { + if (_width!=1 || _height<3 || img._width!=1 || img._height<3) + throw CImgInstanceException(_cimg_instance + "cross(): Instance and/or specified image (%u,%u,%u,%u,%p) are not 3d vectors.", + cimg_instance, + img._width,img._height,img._depth,img._spectrum,img._data); + + const T x = (*this)[0], y = (*this)[1], z = (*this)[2]; + (*this)[0] = (T)(y*img[2] - z*img[1]); + (*this)[1] = (T)(z*img[0] - x*img[2]); + (*this)[2] = (T)(x*img[1] - y*img[0]); + return *this; + } + + //! Compute the cross product between two \c 1x3 images, viewed as 3d vectors \newinstance. + template + CImg<_cimg_Tt> get_cross(const CImg& img) const { + return CImg<_cimg_Tt>(*this).cross(img); + } + + //! Invert the instance image, viewed as a matrix. + /** + \param use_LU Choose the inverting algorithm. Can be: + - \c true: LU-based matrix inversion. + - \c false: SVD-based matrix inversion. + **/ + CImg& invert(const bool use_LU=true) { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "invert(): Instance is not a square matrix.", + cimg_instance); +#ifdef cimg_use_lapack + int INFO = (int)use_LU, N = _width, LWORK = 4*N, *const IPIV = new int[N]; + Tfloat + *const lapA = new Tfloat[N*N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + else { + cimg::getri(N,lapA,IPIV,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "invert(): LAPACK function dgetri_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forXY(*this,k,l) (*this)(k,l) = (T)(lapA[k*N + l]); else fill(0); + delete[] IPIV; delete[] lapA; delete[] WORK; +#else + const double dete = _width>3?-1.0:det(); + if (dete!=0.0 && _width==2) { + const double + a = _data[0], c = _data[1], + b = _data[2], d = _data[3]; + _data[0] = (T)(d/dete); _data[1] = (T)(-c/dete); + _data[2] = (T)(-b/dete); _data[3] = (T)(a/dete); + } else if (dete!=0.0 && _width==3) { + const double + a = _data[0], d = _data[1], g = _data[2], + b = _data[3], e = _data[4], h = _data[5], + c = _data[6], f = _data[7], i = _data[8]; + _data[0] = (T)((i*e-f*h)/dete), _data[1] = (T)((g*f-i*d)/dete), _data[2] = (T)((d*h-g*e)/dete); + _data[3] = (T)((h*c-i*b)/dete), _data[4] = (T)((i*a-c*g)/dete), _data[5] = (T)((g*b-a*h)/dete); + _data[6] = (T)((b*f-e*c)/dete), _data[7] = (T)((d*c-a*f)/dete), _data[8] = (T)((a*e-d*b)/dete); + } else { + if (use_LU) { // LU-based inverse computation + CImg A(*this), indx, col(1,_width); + bool d; + A._LU(indx,d); + cimg_forX(*this,j) { + col.fill(0); + col(j) = 1; + col._solve(A,indx); + cimg_forX(*this,i) (*this)(j,i) = (T)col(i); + } + } else { // SVD-based inverse computation + CImg U(_width,_width), S(1,_width), V(_width,_width); + SVD(U,S,V,false); + U.transpose(); + cimg_forY(S,k) if (S[k]!=0) S[k]=1/S[k]; + S.diagonal(); + *this = V*S*U; + } + } +#endif + return *this; + } + + //! Invert the instance image, viewed as a matrix \newinstance. + CImg get_invert(const bool use_LU=true) const { + return CImg(*this,false).invert(use_LU); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix. + /** + **/ + CImg& pseudoinvert() { + return get_pseudoinvert().move_to(*this); + } + + //! Compute the Moore-Penrose pseudo-inverse of the instance image, viewed as a matrix \newinstance. + CImg get_pseudoinvert() const { + CImg U, S, V; + SVD(U,S,V); + const Tfloat tolerance = (sizeof(Tfloat)<=4?5.96e-8f:1.11e-16f)*std::max(_width,_height)*S.max(); + cimg_forX(V,x) { + const Tfloat s = S(x), invs = s>tolerance?1/s:0; + cimg_forY(V,y) V(x,y)*=invs; + } + return V*U.transpose(); + } + + //! Solve a system of linear equations. + /** + \param A Matrix of the linear system. + \note Solve \c AX=B where \c B=*this. + **/ + template + CImg& solve(const CImg& A) { + if (_depth!=1 || _spectrum!=1 || _height!=A._height || A._depth!=1 || A._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "solve(): Instance and specified matrix (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + if (A._width==A._height) { // Classical linear system + if (_width!=1) { + CImg res(_width,A._width); + cimg_forX(*this,i) res.draw_image(i,get_column(i).solve(A)); + return res.move_to(*this); + } +#ifdef cimg_use_lapack + char TRANS = 'N'; + int INFO, N = _height, LWORK = 4*N, *const IPIV = new int[N]; + Ttfloat + *const lapA = new Ttfloat[N*N], + *const lapB = new Ttfloat[N], + *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*N + l] = (Ttfloat)(A(k,l)); + cimg_forY(*this,i) lapB[i] = (Ttfloat)((*this)(i)); + cimg::getrf(N,lapA,IPIV,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrf_() returned error code %d.", + cimg_instance, + INFO); + + if (!INFO) { + cimg::getrs(TRANS,N,lapA,IPIV,lapB,INFO); + if (INFO) + cimg::warn(_cimg_instance + "solve(): LAPACK library function dgetrs_() returned error code %d.", + cimg_instance, + INFO); + } + if (!INFO) cimg_forY(*this,i) (*this)(i) = (T)(lapB[i]); else fill(0); + delete[] IPIV; delete[] lapA; delete[] lapB; delete[] WORK; +#else + CImg lu(A,false); + CImg indx; + bool d; + lu._LU(indx,d); + _solve(lu,indx); +#endif + } else { // Least-square solution for non-square systems. +#ifdef cimg_use_lapack + if (_width!=1) { + CImg res(_width,A._width); + cimg_forX(*this,i) res.draw_image(i,get_column(i).solve(A)); + return res.move_to(*this); + } + char TRANS = 'N'; + int INFO, N = A._width, M = A._height, LWORK = -1, LDA = M, LDB = M, NRHS = _width; + Ttfloat WORK_QUERY; + Ttfloat + * const lapA = new Ttfloat[M*N], + * const lapB = new Ttfloat[M*NRHS]; + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, &WORK_QUERY, LWORK, INFO); + LWORK = (int) WORK_QUERY; + Ttfloat *const WORK = new Ttfloat[LWORK]; + cimg_forXY(A,k,l) lapA[k*M + l] = (Ttfloat)(A(k,l)); + cimg_forXY(*this,k,l) lapB[k*M + l] = (Ttfloat)((*this)(k,l)); + cimg::sgels(TRANS, M, N, NRHS, lapA, LDA, lapB, LDB, WORK, LWORK, INFO); + if (INFO != 0) + cimg::warn(_cimg_instance + "solve(): LAPACK library function sgels() returned error code %d.", + cimg_instance, + INFO); + assign(NRHS, N); + if (!INFO) + cimg_forXY(*this,k,l) (*this)(k,l) = (T)lapB[k*M + l]; + else + assign(A.get_pseudoinvert()*(*this)); + delete[] lapA; delete[] lapB; delete[] WORK; +#else + assign(A.get_pseudoinvert()*(*this)); +#endif + } + return *this; + } + + //! Solve a system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve(const CImg& A) const { + return CImg<_cimg_Ttfloat>(*this,false).solve(A); + } + + template + CImg& _solve(const CImg& A, const CImg& indx) { + typedef _cimg_Ttfloat Ttfloat; + const int N = (int)size(); + int ii = -1; + Ttfloat sum; + for (int i = 0; i=0) for (int j = ii; j<=i - 1; ++j) sum-=A(j,i)*(*this)(j); + else if (sum!=0) ii = i; + (*this)(i) = (T)sum; + } + for (int i = N - 1; i>=0; --i) { + sum = (*this)(i); + for (int j = i + 1; j + CImg& solve_tridiagonal(const CImg& A) { + const unsigned int siz = (unsigned int)size(); + if (A._width!=3 || A._height!=siz) + throw CImgArgumentException(_cimg_instance + "solve_tridiagonal(): Instance and tridiagonal matrix " + "(%u,%u,%u,%u,%p) have incompatible dimensions.", + cimg_instance, + A._width,A._height,A._depth,A._spectrum,A._data); + typedef _cimg_Ttfloat Ttfloat; + const Ttfloat epsilon = 1e-4f; + CImg B = A.get_column(1), V(*this,false); + for (int i = 1; i<(int)siz; ++i) { + const Ttfloat m = A(0,i)/(B[i - 1]?B[i - 1]:epsilon); + B[i] -= m*A(2,i - 1); + V[i] -= m*V[i - 1]; + } + (*this)[siz - 1] = (T)(V[siz - 1]/(B[siz - 1]?B[siz - 1]:epsilon)); + for (int i = (int)siz - 2; i>=0; --i) (*this)[i] = (T)((V[i] - A(2,i)*(*this)[i + 1])/(B[i]?B[i]:epsilon)); + return *this; + } + + //! Solve a tridiagonal system of linear equations \newinstance. + template + CImg<_cimg_Ttfloat> get_solve_tridiagonal(const CImg& A) const { + return CImg<_cimg_Ttfloat>(*this,false).solve_tridiagonal(A); + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& eigen(CImg& val, CImg &vec) const { + if (is_empty()) { val.assign(); vec.assign(); } + else { + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + + if (val.size()<(ulongT)_width) val.assign(1,_width); + if (vec.size()<(ulongT)_width*_width) vec.assign(_width,_width); + switch (_width) { + case 1 : { val[0] = (t)(*this)[0]; vec[0] = (t)1; } break; + case 2 : { + const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a + d; + double f = e*e - 4*(a*d - b*c); + if (f<0) + cimg::warn(_cimg_instance + "eigen(): Complex eigenvalues found.", + cimg_instance); + + f = std::sqrt(f); + const double + l1 = 0.5*(e - f), + l2 = 0.5*(e + f), + b2 = b*b, + norm1 = std::sqrt(cimg::sqr(l2 - a) + b2), + norm2 = std::sqrt(cimg::sqr(l1 - a) + b2); + val[0] = (t)l2; + val[1] = (t)l1; + if (norm1>0) { vec(0,0) = (t)(b/norm1); vec(0,1) = (t)((l2 - a)/norm1); } else { vec(0,0) = 1; vec(0,1) = 0; } + if (norm2>0) { vec(1,0) = (t)(b/norm2); vec(1,1) = (t)((l1 - a)/norm2); } else { vec(1,0) = 1; vec(1,1) = 0; } + } break; + default : + throw CImgInstanceException(_cimg_instance + "eigen(): Eigenvalues computation of general matrices is limited " + "to 2x2 matrices.", + cimg_instance); + } + } + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a matrix. + /** + \return A list of two images [val; vec], whose meaning is similar as in eigen(CImg&,CImg&) const. + **/ + CImgList get_eigen() const { + CImgList res(2); + eigen(res[0],res[1]); + return res; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \param[out] val Vector of the estimated eigenvalues, in decreasing order. + \param[out] vec Matrix of the estimated eigenvectors, sorted by columns. + **/ + template + const CImg& symmetric_eigen(CImg& val, CImg& vec) const { + if (is_empty()) { val.assign(); vec.assign(); } + else { +#ifdef cimg_use_lapack + char JOB = 'V', UPLO = 'U'; + int N = _width, LWORK = 4*N, INFO; + Tfloat + *const lapA = new Tfloat[N*N], + *const lapW = new Tfloat[N], + *const WORK = new Tfloat[LWORK]; + cimg_forXY(*this,k,l) lapA[k*N + l] = (Tfloat)((*this)(k,l)); + cimg::syev(JOB,UPLO,N,lapA,lapW,WORK,LWORK,INFO); + if (INFO) + cimg::warn(_cimg_instance + "symmetric_eigen(): LAPACK library function dsyev_() returned error code %d.", + cimg_instance, + INFO); + + val.assign(1,N); + vec.assign(N,N); + if (!INFO) { + cimg_forY(val,i) val(i) = (T)lapW[N - 1 -i]; + cimg_forXY(vec,k,l) vec(k,l) = (T)(lapA[(N - 1 - k)*N + l]); + } else { val.fill(0); vec.fill(0); } + delete[] lapA; delete[] lapW; delete[] WORK; +#else + if (_width!=_height || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "eigen(): Instance is not a square matrix.", + cimg_instance); + + val.assign(1,_width); + if (vec._data) vec.assign(_width,_width); + if (_width<3) { + eigen(val,vec); + if (_width==2) { vec[1] = -vec[2]; vec[3] = vec[0]; } // Force orthogonality for 2x2 matrices. + return *this; + } + CImg V(_width,_width); + Tfloat M = 0, m = (Tfloat)min_max(M), maxabs = cimg::max((Tfloat)1.0f,cimg::abs(m),cimg::abs(M)); + (CImg(*this,false)/=maxabs).SVD(vec,val,V,false); + if (maxabs!=1) val*=maxabs; + + bool is_ambiguous = false; + float eig = 0; + cimg_forY(val,p) { // check for ambiguous cases. + if (val[p]>eig) eig = (float)val[p]; + t scal = 0; + cimg_forY(vec,y) scal+=vec(p,y)*V(p,y); + if (cimg::abs(scal)<0.9f) is_ambiguous = true; + if (scal<0) val[p] = -val[p]; + } + if (is_ambiguous) { + ++(eig*=2); + SVD(vec,val,V,false,40,eig); + val-=eig; + } + CImg permutations; // sort eigenvalues in decreasing order + CImg tmp(_width); + val.sort(permutations,false); + cimg_forY(vec,k) { + cimg_forY(permutations,y) tmp(y) = vec(permutations(y),k); + std::memcpy(vec.data(0,k),tmp._data,sizeof(t)*_width); + } +#endif + } + return *this; + } + + //! Compute eigenvalues and eigenvectors of the instance image, viewed as a symmetric matrix. + /** + \return A list of two images [val; vec], whose meaning are similar as in + symmetric_eigen(CImg&,CImg&) const. + **/ + CImgList get_symmetric_eigen() const { + CImgList res(2); + symmetric_eigen(res[0],res[1]); + return res; + } + + //! Sort pixel values and get sorting permutations. + /** + \param[out] permutations Permutation map used for the sorting. + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + **/ + template + CImg& sort(CImg& permutations, const bool is_increasing=true) { + permutations.assign(_width,_height,_depth,_spectrum); + if (is_empty()) return *this; + cimg_foroff(permutations,off) permutations[off] = (t)off; + return _quicksort(0,size() - 1,permutations,is_increasing,true); + } + + //! Sort pixel values and get sorting permutations \newinstance. + template + CImg get_sort(CImg& permutations, const bool is_increasing=true) const { + return (+*this).sort(permutations,is_increasing); + } + + //! Sort pixel values. + /** + \param is_increasing Tells if pixel values are sorted in an increasing (\c true) or decreasing (\c false) way. + \param axis Tells if the value sorting must be done along a specific axis. Can be: + - \c 0: All pixel values are sorted, independently on their initial position. + - \c 'x': Image columns are sorted, according to the first value in each column. + - \c 'y': Image rows are sorted, according to the first value in each row. + - \c 'z': Image slices are sorted, according to the first value in each slice. + - \c 'c': Image channels are sorted, according to the first value in each channel. + **/ + CImg& sort(const bool is_increasing=true, const char axis=0) { + if (is_empty()) return *this; + CImg perm; + switch (cimg::lowercase(axis)) { + case 0 : + _quicksort(0,size() - 1,perm,is_increasing,false); + break; + case 'x' : { + perm.assign(_width); + get_crop(0,0,0,0,_width - 1,0,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(perm[x],y,z,c); + } break; + case 'y' : { + perm.assign(_height); + get_crop(0,0,0,0,0,_height - 1,0,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,perm[y],z,c); + } break; + case 'z' : { + perm.assign(_depth); + get_crop(0,0,0,0,0,0,_depth - 1,0).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,perm[z],c); + } break; + case 'c' : { + perm.assign(_spectrum); + get_crop(0,0,0,0,0,0,0,_spectrum - 1).sort(perm,is_increasing); + CImg img(*this,false); + cimg_forXYZC(*this,x,y,z,c) (*this)(x,y,z,c) = img(x,y,z,perm[c]); + } break; + default : + throw CImgArgumentException(_cimg_instance + "sort(): Invalid specified axis '%c' " + "(should be { x | y | z | c }).", + cimg_instance,axis); + } + return *this; + } + + //! Sort pixel values \newinstance. + CImg get_sort(const bool is_increasing=true, const char axis=0) const { + return (+*this).sort(is_increasing,axis); + } + + template + CImg& _quicksort(const long indm, const long indM, CImg& permutations, + const bool is_increasing, const bool is_permutations) { + if (indm(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]>(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]>(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } else { + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + if ((*this)[mid]<(*this)[indM]) { + cimg::swap((*this)[indM],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indM],permutations[mid]); + } + if ((*this)[indm]<(*this)[mid]) { + cimg::swap((*this)[indm],(*this)[mid]); + if (is_permutations) cimg::swap(permutations[indm],permutations[mid]); + } + } + if (indM - indm>=3) { + const T pivot = (*this)[mid]; + long i = indm, j = indM; + if (is_increasing) { + do { + while ((*this)[i]pivot) --j; + if (i<=j) { + if (is_permutations) cimg::swap(permutations[i],permutations[j]); + cimg::swap((*this)[i++],(*this)[j--]); + } + } while (i<=j); + } else { + do { + while ((*this)[i]>pivot) ++i; + while ((*this)[j] A; // Input matrix (assumed to contain some values). + CImg<> U,S,V; + A.SVD(U,S,V) + \endcode + **/ + template + const CImg& SVD(CImg& U, CImg& S, CImg& V, const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + if (is_empty()) { U.assign(); S.assign(); V.assign(); } + else { + U = *this; + if (lambda!=0) { + const unsigned int delta = std::min(U._width,U._height); + for (unsigned int i = 0; i rv1(_width); + t anorm = 0, c, f, g = 0, h, s, scale = 0; + int l = 0, nm = 0; + + cimg_forX(U,i) { + l = i + 1; rv1[i] = scale*g; g = s = scale = 0; + if (i=0?-1:1)*std::sqrt(s)); h=f*g-s; U(i,i) = f-g; + for (int j = l; j=0?-1:1)*std::sqrt(s)); h = f*g-s; U(l,i) = f-g; + for (int k = l; k=0; --i) { + if (i=0; --i) { + l = i + 1; g = S[i]; + for (int j = l; j=0; --k) { + for (unsigned int its = 0; its=1; --l) { + nm = l - 1; + if ((cimg::abs(rv1[l]) + anorm)==anorm) { flag = false; break; } + if ((cimg::abs(S[nm]) + anorm)==anorm) break; + } + if (flag) { + c = 0; s = 1; + for (int i = l; i<=k; ++i) { + f = s*rv1[i]; rv1[i] = c*rv1[i]; + if ((cimg::abs(f) + anorm)==anorm) break; + g = S[i]; h = cimg::_hypot(f,g); S[i] = h; h = 1/h; c = g*h; s = -f*h; + cimg_forY(U,j) { const t y = U(nm,j), z = U(i,j); U(nm,j) = y*c + z*s; U(i,j) = z*c - y*s; } + } + } + + const t z = S[k]; + if (l==k) { if (z<0) { S[k] = -z; cimg_forX(U,j) V(k,j) = -V(k,j); } break; } + nm = k - 1; + t x = S[l], y = S[nm]; + g = rv1[nm]; h = rv1[k]; + f = ((y - z)*(y + z)+(g - h)*(g + h))/std::max((t)1e-25,2*h*y); + g = cimg::_hypot(f,(t)1); + f = ((x - z)*(x + z)+h*((y/(f + (f>=0?g:-g))) - h))/std::max((t)1e-25,x); + c = s = 1; + for (int j = l; j<=nm; ++j) { + const int i = j + 1; + g = rv1[i]; h = s*g; g = c*g; + t y = S[i]; + t z = cimg::_hypot(f,h); + rv1[j] = z; c = f/std::max((t)1e-25,z); s = h/std::max((t)1e-25,z); + f = x*c + g*s; g = g*c - x*s; h = y*s; y*=c; + cimg_forX(U,jj) { const t x = V(j,jj), z = V(i,jj); V(j,jj) = x*c + z*s; V(i,jj) = z*c - x*s; } + z = cimg::_hypot(f,h); S[j] = z; + if (z) { z = 1/std::max((t)1e-25,z); c = f*z; s = h*z; } + f = c*g + s*y; x = c*y - s*g; + cimg_forY(U,jj) { const t y = U(j,jj); z = U(i,jj); U(j,jj) = y*c + z*s; U(i,jj) = z*c - y*s; } + } + rv1[l] = 0; rv1[k]=f; S[k]=x; + } + } + + if (sorting) { + CImg permutations; + CImg tmp(_width); + S.sort(permutations,false); + cimg_forY(U,k) { + cimg_forY(permutations,y) tmp(y) = U(permutations(y),k); + std::memcpy(U.data(0,k),tmp._data,sizeof(t)*_width); + } + cimg_forY(V,k) { + cimg_forY(permutations,y) tmp(y) = V(permutations(y),k); + std::memcpy(V.data(0,k),tmp._data,sizeof(t)*_width); + } + } + } + return *this; + } + + //! Compute the SVD of the instance image, viewed as a general matrix. + /** + \return A list of three images [U; S; V], whose meaning is similar as in + SVD(CImg&,CImg&,CImg&,bool,unsigned int,float) const. + **/ + CImgList get_SVD(const bool sorting=true, + const unsigned int max_iteration=40, const float lambda=0) const { + CImgList res(3); + SVD(res[0],res[1],res[2],sorting,max_iteration,lambda); + return res; + } + + // [internal] Compute the LU decomposition of a permuted matrix. + template + CImg& _LU(CImg& indx, bool& d) { + const int N = width(); + int imax = 0; + CImg vv(N); + indx.assign(N); + d = true; + cimg_forX(*this,i) { + Tfloat vmax = 0; + cimg_forX(*this,j) { + const Tfloat tmp = cimg::abs((*this)(j,i)); + if (tmp>vmax) vmax = tmp; + } + if (vmax==0) { indx.fill(0); return fill(0); } + vv[i] = 1/vmax; + } + cimg_forX(*this,j) { + for (int i = 0; i=vmax) { vmax=tmp; imax=i; } + } + if (j!=imax) { + cimg_forX(*this,k) cimg::swap((*this)(k,imax),(*this)(k,j)); + d =!d; + vv[imax] = vv[j]; + } + indx[j] = (t)imax; + if ((*this)(j,j)==0) (*this)(j,j) = (T)1e-20; + if (j + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + if (starting_node>=nb_nodes) + throw CImgArgumentException("CImg<%s>::dijkstra(): Specified indice of starting node %u is higher " + "than number of nodes %u.", + pixel_type(),starting_node,nb_nodes); + CImg dist(1,nb_nodes,1,1,cimg::type::max()); + dist(starting_node) = 0; + previous_node.assign(1,nb_nodes,1,1,(t)-1); + previous_node(starting_node) = (t)starting_node; + CImg Q(nb_nodes); + cimg_forX(Q,u) Q(u) = (unsigned int)u; + cimg::swap(Q(starting_node),Q(0)); + unsigned int sizeQ = nb_nodes; + while (sizeQ) { + // Update neighbors from minimal vertex + const unsigned int umin = Q(0); + if (umin==ending_node) sizeQ = 0; + else { + const T dmin = dist(umin); + const T infty = cimg::type::max(); + for (unsigned int q = 1; qdist(Q(left))) || + (rightdist(Q(right)));) { + if (right + static CImg dijkstra(const tf& distance, const unsigned int nb_nodes, + const unsigned int starting_node, const unsigned int ending_node=~0U) { + CImg foo; + return dijkstra(distance,nb_nodes,starting_node,ending_node,foo); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + /** + \param starting_node Indice of the starting node. + \param ending_node Indice of the ending node. + \param previous_node Array that gives the previous node indice in the path to the starting node + (optional parameter). + \return Array of distances of each node to the starting node. + \note image instance corresponds to the adjacency matrix of the graph. + **/ + template + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) { + return get_dijkstra(starting_node,ending_node,previous_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + template + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node, + CImg& previous_node) const { + if (_width!=_height || _depth!=1 || _spectrum!=1) + throw CImgInstanceException(_cimg_instance + "dijkstra(): Instance is not a graph adjacency matrix.", + cimg_instance); + + return dijkstra(*this,_width,starting_node,ending_node,previous_node); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm. + CImg& dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) { + return get_dijkstra(starting_node,ending_node).move_to(*this); + } + + //! Return minimal path in a graph, using the Dijkstra algorithm \newinstance. + CImg get_dijkstra(const unsigned int starting_node, const unsigned int ending_node=~0U) const { + CImg foo; + return get_dijkstra(starting_node,ending_node,foo); + } + + //! Return an image containing the ascii codes of the specified string. + /** + \param str input C-string to encode as an image. + \param is_last_zero Tells if the ending \c '0' character appear in the resulting image. + **/ + static CImg string(const char *const str, const bool is_last_zero=true, const bool is_shared=false) { + if (!str) return CImg(); + return CImg(str,(unsigned int)std::strlen(str) + (is_last_zero?1:0),1,1,1,is_shared); + } + + //! Return a \c 1x1 image containing specified value. + /** + \param a0 First vector value. + **/ + static CImg vector(const T& a0) { + CImg r(1,1); + r[0] = a0; + return r; + } + + //! Return a \c 1x2 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + **/ + static CImg vector(const T& a0, const T& a1) { + CImg r(1,2); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; + return r; + } + + //! Return a \c 1x3 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2) { + CImg r(1,3); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; + return r; + } + + //! Return a \c 1x4 image containing specified values. + /** + \param a0 First vector value. + \param a1 Second vector value. + \param a2 Third vector value. + \param a3 Fourth vector value. + **/ + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3) { + CImg r(1,4); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + return r; + } + + //! Return a \c 1x5 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + CImg r(1,5); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; + return r; + } + + //! Return a \c 1x6 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + CImg r(1,6); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; + return r; + } + + //! Return a \c 1x7 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6) { + CImg r(1,7); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; + return r; + } + + //! Return a \c 1x8 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7) { + CImg r(1,8); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + return r; + } + + //! Return a \c 1x9 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8) { + CImg r(1,9); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; + return r; + } + + //! Return a \c 1x10 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9) { + CImg r(1,10); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; + return r; + } + + //! Return a \c 1x11 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10) { + CImg r(1,11); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; + return r; + } + + //! Return a \c 1x12 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11) { + CImg r(1,12); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + return r; + } + + //! Return a \c 1x13 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12) { + CImg r(1,13); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; + return r; + } + + //! Return a \c 1x14 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13) { + CImg r(1,14); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; + return r; + } + + //! Return a \c 1x15 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14) { + CImg r(1,15); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; + return r; + } + + //! Return a \c 1x16 image containing specified values. + static CImg vector(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(1,16); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; + return r; + } + + //! Return a 1x1 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg matrix(const T& a0) { + return vector(a0); + } + + //! Return a 2x2 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, + const T& a2, const T& a3) { + CImg r(2,2); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; + *(ptr++) = a2; *(ptr++) = a3; + return r; + } + + //! Return a 3x3 matrix containing specified coefficients. + /** + \param a0 First matrix value. + \param a1 Second matrix value. + \param a2 Third matrix value. + \param a3 Fourth matrix value. + \param a4 Fifth matrix value. + \param a5 Sixth matrix value. + \param a6 Seventh matrix value. + \param a7 Eighth matrix value. + \param a8 Nineth matrix value. + **/ + static CImg matrix(const T& a0, const T& a1, const T& a2, + const T& a3, const T& a4, const T& a5, + const T& a6, const T& a7, const T& a8) { + CImg r(3,3); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; + *(ptr++) = a3; *(ptr++) = a4; *(ptr++) = a5; + *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; + return r; + } + + //! Return a 4x4 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, + const T& a4, const T& a5, const T& a6, const T& a7, + const T& a8, const T& a9, const T& a10, const T& a11, + const T& a12, const T& a13, const T& a14, const T& a15) { + CImg r(4,4); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; + *(ptr++) = a4; *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; + *(ptr++) = a8; *(ptr++) = a9; *(ptr++) = a10; *(ptr++) = a11; + *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; *(ptr++) = a15; + return r; + } + + //! Return a 5x5 matrix containing specified coefficients. + static CImg matrix(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, + const T& a5, const T& a6, const T& a7, const T& a8, const T& a9, + const T& a10, const T& a11, const T& a12, const T& a13, const T& a14, + const T& a15, const T& a16, const T& a17, const T& a18, const T& a19, + const T& a20, const T& a21, const T& a22, const T& a23, const T& a24) { + CImg r(5,5); T *ptr = r._data; + *(ptr++) = a0; *(ptr++) = a1; *(ptr++) = a2; *(ptr++) = a3; *(ptr++) = a4; + *(ptr++) = a5; *(ptr++) = a6; *(ptr++) = a7; *(ptr++) = a8; *(ptr++) = a9; + *(ptr++) = a10; *(ptr++) = a11; *(ptr++) = a12; *(ptr++) = a13; *(ptr++) = a14; + *(ptr++) = a15; *(ptr++) = a16; *(ptr++) = a17; *(ptr++) = a18; *(ptr++) = a19; + *(ptr++) = a20; *(ptr++) = a21; *(ptr++) = a22; *(ptr++) = a23; *(ptr++) = a24; + return r; + } + + //! Return a 1x1 symmetric matrix containing specified coefficients. + /** + \param a0 First matrix value. + \note Equivalent to vector(const T&). + **/ + static CImg tensor(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 symmetric matrix tensor containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2) { + return matrix(a0,a1,a1,a2); + } + + //! Return a 3x3 symmetric matrix containing specified coefficients. + static CImg tensor(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4, const T& a5) { + return matrix(a0,a1,a2,a1,a3,a4,a2,a4,a5); + } + + //! Return a 1x1 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0) { + return matrix(a0); + } + + //! Return a 2x2 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1) { + return matrix(a0,0,0,a1); + } + + //! Return a 3x3 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2) { + return matrix(a0,0,0,0,a1,0,0,0,a2); + } + + //! Return a 4x4 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3) { + return matrix(a0,0,0,0,0,a1,0,0,0,0,a2,0,0,0,0,a3); + } + + //! Return a 5x5 diagonal matrix containing specified coefficients. + static CImg diagonal(const T& a0, const T& a1, const T& a2, const T& a3, const T& a4) { + return matrix(a0,0,0,0,0,0,a1,0,0,0,0,0,a2,0,0,0,0,0,a3,0,0,0,0,0,a4); + } + + //! Return a NxN identity matrix. + /** + \param N Dimension of the matrix. + **/ + static CImg identity_matrix(const unsigned int N) { + CImg res(N,N,1,1,0); + cimg_forX(res,x) res(x,x) = 1; + return res; + } + + //! Return a N-numbered sequence vector from \p a0 to \p a1. + /** + \param N Size of the resulting vector. + \param a0 Starting value of the sequence. + \param a1 Ending value of the sequence. + **/ + static CImg sequence(const unsigned int N, const T& a0, const T& a1) { + if (N) return CImg(1,N).sequence(a0,a1); + return CImg(); + } + + //! Return a 3x3 rotation matrix from an { axis + angle } or a quaternion. + /** + \param x X-coordinate of the rotation axis, or first quaternion coordinate. + \param y Y-coordinate of the rotation axis, or second quaternion coordinate. + \param z Z-coordinate of the rotation axis, or third quaternion coordinate. + \param w Angle of the rotation axis (in degree), or fourth quaternion coordinate. + \param is_quaternion Tell is the four arguments denotes a set { axis + angle } or a quaternion (x,y,z,w). + **/ + static CImg rotation_matrix(const float x, const float y, const float z, const float w, + const bool is_quaternion=false) { + double X, Y, Z, W, N; + if (is_quaternion) { + N = std::sqrt((double)x*x + (double)y*y + (double)z*z + (double)w*w); + if (N>0) { X = x/N; Y = y/N; Z = z/N; W = w/N; } + else { X = Y = Z = 0; W = 1; } + return CImg::matrix((T)(X*X + Y*Y - Z*Z - W*W),(T)(2*Y*Z - 2*X*W),(T)(2*X*Z + 2*Y*W), + (T)(2*X*W + 2*Y*Z),(T)(X*X - Y*Y + Z*Z - W*W),(T)(2*Z*W - 2*X*Y), + (T)(2*Y*W - 2*X*Z),(T)(2*X*Y + 2*Z*W),(T)(X*X - Y*Y - Z*Z + W*W)); + } + N = cimg::hypot((double)x,(double)y,(double)z); + if (N>0) { X = x/N; Y = y/N; Z = z/N; } + else { X = Y = 0; Z = 1; } + const double ang = w*cimg::PI/180, c = std::cos(ang), omc = 1 - c, s = std::sin(ang); + return CImg::matrix((T)(X*X*omc + c),(T)(X*Y*omc - Z*s),(T)(X*Z*omc + Y*s), + (T)(X*Y*omc + Z*s),(T)(Y*Y*omc + c),(T)(Y*Z*omc - X*s), + (T)(X*Z*omc - Y*s),(T)(Y*Z*omc + X*s),(T)(Z*Z*omc + c)); + } + + //@} + //----------------------------------- + // + //! \name Value Manipulation + //@{ + //----------------------------------- + + //! Fill all pixel values with specified value. + /** + \param val Fill value. + **/ + CImg& fill(const T& val) { + if (is_empty()) return *this; + if (val && sizeof(T)!=1) cimg_for(*this,ptrd,T) *ptrd = val; + else std::memset(_data,(int)val,sizeof(T)*size()); + return *this; + } + + //! Fill all pixel values with specified value \newinstance. + CImg get_fill(const T& val) const { + return CImg(_width,_height,_depth,_spectrum).fill(val); + } + + //! Fill sequentially all pixel values with specified values. + /** + \param val0 First fill value. + \param val1 Second fill value. + **/ + CImg& fill(const T& val0, const T& val1) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 1; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 2; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 3; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 4; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 5; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 6; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 7; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 8; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 9; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 10; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 11; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 12; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 13; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 14; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14); + } + + //! Fill sequentially all pixel values with specified values \overloading. + CImg& fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) { + if (is_empty()) return *this; + T *ptrd, *ptre = end() - 15; + for (ptrd = _data; ptrd get_fill(const T& val0, const T& val1, const T& val2, const T& val3, const T& val4, const T& val5, + const T& val6, const T& val7, const T& val8, const T& val9, const T& val10, const T& val11, + const T& val12, const T& val13, const T& val14, const T& val15) const { + return CImg(_width,_height,_depth,_spectrum).fill(val0,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10, + val11,val12,val13,val14,val15); + } + + //! Fill sequentially pixel values according to a given expression. + /** + \param expression C-string describing a math formula, or a sequence of values. + \param repeat_values In case a list of values is provided, tells if this list must be repeated for the filling. + \param list_inputs In case of a mathematical expression, attach a list of images to the specified expression. + \param list_outputs In case of a mathematical expression, attach a list of images to the specified expression. + **/ + CImg& fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) { + return _fill(expression,repeat_values,allow_formula,list_inputs,list_outputs,"fill",0); + } + + CImg& _fill(const char *const expression, const bool repeat_values, bool allow_formula, + const CImgList *const list_inputs, CImgList *const list_outputs, + const char *const calling_function, const CImg *provides_copy) { + if (is_empty() || !expression || !*expression) return *this; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + CImg is_error; + bool is_value_sequence = false; + + if (allow_formula) { + + // Try to pre-detect regular value sequence to avoid exception thrown by _cimg_math_parser. + double value; + char sep; + const int err = cimg_sscanf(expression,"%lf %c",&value,&sep); + if (err==1 || (err==2 && sep==',')) { + if (err==1) return fill((T)value); + else is_value_sequence = true; + } + + // Try to fill values according to a formula. + cimg_abort_init; + if (!is_value_sequence) try { + CImg base = provides_copy?provides_copy->get_shared():get_shared(); + _cimg_math_parser mp(expression + (*expression=='>' || *expression=='<' || + *expression=='*' || *expression==':'), + calling_function,base,this,list_inputs,list_outputs); + if (!provides_copy && expression && *expression!='>' && *expression!='<' && *expression!=':' && + mp.need_input_copy) + base.assign().assign(*this); // Needs input copy + + bool do_in_parallel = false; +#ifdef cimg_use_openmp + cimg_openmp_if(*expression=='*' || *expression==':' || + (mp.is_parallelizable && _width>=320 && _height*_depth*_spectrum>=2)) + do_in_parallel = true; +#endif + if (mp.result_dim) { // Vector-valued expression + const unsigned int N = std::min(mp.result_dim,_spectrum); + const ulongT whd = (ulongT)_width*_height*_depth; + T *ptrd = *expression=='<'?_data + _width*_height*_depth - 1:_data; + if (*expression=='<') { + CImg res(1,mp.result_dim); + cimg_rofYZ(*this,y,z) { + cimg_abort_test(); + cimg_rofX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd--; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + } else if (*expression=='>' || !do_in_parallel) { + CImg res(1,mp.result_dim); + cimg_forYZ(*this,y,z) { + cimg_abort_test(); + cimg_forX(*this,x) { + mp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } + } else { +#ifdef cimg_use_openmp + cimg_pragma_openmp(parallel) + { + _cimg_math_parser + _mp = omp_get_thread_num()?mp:_cimg_math_parser(), + &lmp = omp_get_thread_num()?_mp:mp; + cimg_pragma_openmp(for collapse(2)) + cimg_forYZ(*this,y,z) cimg_abort_try { + cimg_abort_test(); + CImg res(1,lmp.result_dim); + T *ptrd = data(0,y,z,0); + cimg_forX(*this,x) { + lmp(x,y,z,0,res._data); + const double *ptrs = res._data; + T *_ptrd = ptrd++; for (unsigned int n = N; n>0; --n) { *_ptrd = (T)(*ptrs++); _ptrd+=whd; } + } + } cimg_abort_catch() + } +#endif + } + + } else { // Scalar-valued expression + T *ptrd = *expression=='<'?end() - 1:_data; + if (*expression=='<') + cimg_rofYZC(*this,y,z,c) { cimg_abort_test(); cimg_rofX(*this,x) *(ptrd--) = (T)mp(x,y,z,c); } + else if (*expression=='>' || !do_in_parallel) + cimg_forYZC(*this,y,z,c) { cimg_abort_test(); cimg_forX(*this,x) *(ptrd++) = (T)mp(x,y,z,c); } + else { +#ifdef cimg_use_openmp + cimg_pragma_openmp(parallel) + { + _cimg_math_parser + _mp = omp_get_thread_num()?mp:_cimg_math_parser(), + &lmp = omp_get_thread_num()?_mp:mp; + cimg_pragma_openmp(for collapse(3)) + cimg_forYZC(*this,y,z,c) cimg_abort_try { + cimg_abort_test(); + T *ptrd = data(0,y,z,c); + cimg_forX(*this,x) *ptrd++ = (T)lmp(x,y,z,c); + } cimg_abort_catch() + } +#endif + } + } + } catch (CImgException& e) { CImg::string(e._message).move_to(is_error); } + } + + // Try to fill values according to a value sequence. + if (!allow_formula || is_value_sequence || is_error) { + CImg item(256); + char sep = 0; + const char *nexpression = expression; + ulongT nb = 0; + const ulongT siz = size(); + T *ptrd = _data; + for (double val = 0; *nexpression && nb0 && cimg_sscanf(item,"%lf",&val)==1 && (sep==',' || sep==';' || err==1)) { + nexpression+=std::strlen(item) + (err>1); + *(ptrd++) = (T)val; + } else break; + } + cimg::exception_mode(omode); + if (nb get_fill(const char *const expression, const bool repeat_values, const bool allow_formula=true, + const CImgList *const list_inputs=0, CImgList *const list_outputs=0) const { + return (+*this).fill(expression,repeat_values,allow_formula,list_inputs,list_outputs); + } + + //! Fill sequentially pixel values according to the values found in another image. + /** + \param values Image containing the values used for the filling. + \param repeat_values In case there are less values than necessary in \c values, tells if these values must be + repeated for the filling. + **/ + template + CImg& fill(const CImg& values, const bool repeat_values=true) { + if (is_empty() || !values) return *this; + T *ptrd = _data, *ptre = ptrd + size(); + for (t *ptrs = values._data, *ptrs_end = ptrs + values.size(); ptrs + CImg get_fill(const CImg& values, const bool repeat_values=true) const { + return repeat_values?CImg(_width,_height,_depth,_spectrum).fill(values,repeat_values): + (+*this).fill(values,repeat_values); + } + + //! Fill pixel values along the X-axis at a specified pixel position. + /** + \param y Y-coordinate of the filled column. + \param z Z-coordinate of the filled column. + \param c C-coordinate of the filled column. + \param a0 First fill value. + **/ + CImg& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const int a0, ...) { +#define _cimg_fill1(x,y,z,c,off,siz,t) { \ + va_list ap; va_start(ap,a0); T *ptrd = data(x,y,z,c); *ptrd = (T)a0; \ + for (unsigned int k = 1; k& fillX(const unsigned int y, const unsigned int z, const unsigned int c, const double a0, ...) { + if (y<_height && z<_depth && c<_spectrum) _cimg_fill1(0,y,z,c,1,_width,double); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position. + /** + \param x X-coordinate of the filled row. + \param z Z-coordinate of the filled row. + \param c C-coordinate of the filled row. + \param a0 First fill value. + **/ + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const int a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,int); + return *this; + } + + //! Fill pixel values along the Y-axis at a specified pixel position \overloading. + CImg& fillY(const unsigned int x, const unsigned int z, const unsigned int c, const double a0, ...) { + if (x<_width && z<_depth && c<_spectrum) _cimg_fill1(x,0,z,c,_width,_height,double); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position. + /** + \param x X-coordinate of the filled slice. + \param y Y-coordinate of the filled slice. + \param c C-coordinate of the filled slice. + \param a0 First fill value. + **/ + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const int a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,int); + return *this; + } + + //! Fill pixel values along the Z-axis at a specified pixel position \overloading. + CImg& fillZ(const unsigned int x, const unsigned int y, const unsigned int c, const double a0, ...) { + const ulongT wh = (ulongT)_width*_height; + if (x<_width && y<_height && c<_spectrum) _cimg_fill1(x,y,0,c,wh,_depth,double); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position. + /** + \param x X-coordinate of the filled channel. + \param y Y-coordinate of the filled channel. + \param z Z-coordinate of the filled channel. + \param a0 First filling value. + **/ + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const int a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,int); + return *this; + } + + //! Fill pixel values along the C-axis at a specified pixel position \overloading. + CImg& fillC(const unsigned int x, const unsigned int y, const unsigned int z, const double a0, ...) { + const ulongT whd = (ulongT)_width*_height*_depth; + if (x<_width && y<_height && z<_depth) _cimg_fill1(x,y,z,0,whd,_spectrum,double); + return *this; + } + + //! Discard specified sequence of values in the image buffer, along a specific axis. + /** + \param values Sequence of values to discard. + \param axis Axis along which the values are discarded. If set to \c 0 (default value) + the method does it for all the buffer values and returns a one-column vector. + \note Discarded values will change the image geometry, so the resulting image + is returned as a one-column vector. + **/ + template + CImg& discard(const CImg& values, const char axis=0) { + if (is_empty() || !values) return *this; + return get_discard(values,axis).move_to(*this); + } + + template + CImg get_discard(const CImg& values, const char axis=0) const { + CImg res; + if (!values) return +*this; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + ulongT j = 0; + unsigned int k = 0; + int i0 = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) { + if ((*this)(i)!=(T)values[j]) { + if (j) --i; + res.draw_image(k,get_columns(i0,i)); + k+=i - i0 + 1; i0 = i + 1; j = 0; + } else { ++j; if (j>=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = i + 1; } } + } + if (i0=vsiz) { j = 0; i0 = (int)i + 1; }} + } + const ulongT siz = size(); + if ((ulongT)i0& discard(const char axis=0) { + return get_discard(axis).move_to(*this); + } + + //! Discard neighboring duplicates in the image buffer, along the specified axis \newinstance. + CImg get_discard(const char axis=0) const { + CImg res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + T current = *_data?(T)0:(T)1; + int j = 0; + res.assign(width(),height(),depth(),spectrum()); + switch (_axis) { + case 'x' : { + cimg_forX(*this,i) + if ((*this)(i)!=current) { res.draw_image(j++,get_column(i)); current = (*this)(i); } + res.resize(j,-100,-100,-100,0); + } break; + case 'y' : { + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { res.draw_image(0,j++,get_row(i)); current = (*this)(0,i); } + res.resize(-100,j,-100,-100,0); + } break; + case 'z' : { + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { res.draw_image(0,0,j++,get_slice(i)); current = (*this)(0,0,i); } + res.resize(-100,-100,j,-100,0); + } break; + case 'c' : { + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { res.draw_image(0,0,0,j++,get_channel(i)); current = (*this)(0,0,0,i); } + res.resize(-100,-100,-100,j,0); + } break; + default : { + res.unroll('y'); + cimg_foroff(*this,i) + if ((*this)[i]!=current) res[j++] = current = (*this)[i]; + res.resize(-100,j,-100,-100,0); + } + } + return res; + } + + //! Invert endianness of all pixel values. + /** + **/ + CImg& invert_endianness() { + cimg::invert_endianness(_data,size()); + return *this; + } + + //! Invert endianness of all pixel values \newinstance. + CImg get_invert_endianness() const { + return (+*this).invert_endianness(); + } + + //! Fill image with random values in specified range. + /** + \param val_min Minimal authorized random value. + \param val_max Maximal authorized random value. + \note Random variables are uniformely distributed in [val_min,val_max]. + **/ + CImg& rand(const T& val_min, const T& val_max) { + const float delta = (float)val_max - (float)val_min + (cimg::type::is_float()?0:1); + if (cimg::type::is_float()) cimg_for(*this,ptrd,T) *ptrd = (T)(val_min + cimg::rand()*delta); + else cimg_for(*this,ptrd,T) *ptrd = std::min(val_max,(T)(val_min + cimg::rand()*delta)); + return *this; + } + + //! Fill image with random values in specified range \newinstance. + CImg get_rand(const T& val_min, const T& val_max) const { + return (+*this).rand(val_min,val_max); + } + + //! Round pixel values. + /** + \param y Rounding precision. + \param rounding_type Rounding type. Can be: + - \c -1: Backward. + - \c 0: Nearest. + - \c 1: Forward. + **/ + CImg& round(const double y=1, const int rounding_type=0) { + if (y>0) + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=8192)) + cimg_rof(*this,ptrd,T) *ptrd = cimg::round(*ptrd,y,rounding_type); + return *this; + } + + //! Round pixel values \newinstance. + CImg get_round(const double y=1, const unsigned int rounding_type=0) const { + return (+*this).round(y,rounding_type); + } + + //! Add random noise to pixel values. + /** + \param sigma Amplitude of the random additive noise. If \p sigma<0, it stands for a percentage of the + global value range. + \param noise_type Type of additive noise (can be \p 0=gaussian, \p 1=uniform, \p 2=Salt and Pepper, + \p 3=Poisson or \p 4=Rician). + \return A reference to the modified image instance. + \note + - For Poisson noise (\p noise_type=3), parameter \p sigma is ignored, as Poisson noise only depends on + the image value itself. + - Function \p CImg::get_noise() is also defined. It returns a non-shared modified copy of the image instance. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_noise(40); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_noise.jpg + **/ + CImg& noise(const double sigma, const unsigned int noise_type=0) { + if (is_empty()) return *this; + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + Tfloat nsigma = (Tfloat)sigma, m = 0, M = 0; + if (nsigma==0 && noise_type!=3) return *this; + if (nsigma<0 || noise_type==2) m = (Tfloat)min_max(M); + if (nsigma<0) nsigma = (Tfloat)(-nsigma*(M-m)/100.0); + switch (noise_type) { + case 0 : { // Gaussian noise + cimg_rof(*this,ptrd,T) { + Tfloat val = (Tfloat)(*ptrd + nsigma*cimg::grand()); + if (val>vmax) val = vmax; + if (valvmax) val = vmax; + if (val::is_float()?(Tfloat)1:(Tfloat)cimg::type::max(); } + cimg_rof(*this,ptrd,T) if (cimg::rand(100)vmax) val = vmax; + if (val get_noise(const double sigma, const unsigned int noise_type=0) const { + return (+*this).noise(sigma,noise_type); + } + + //! Linearly normalize pixel values. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(160,220); + (img,res).display(); + \endcode + \image html ref_normalize2.jpg + **/ + CImg& normalize(const T& min_value, const T& max_value) { + if (is_empty()) return *this; + const T a = min_value get_normalize(const T& min_value, const T& max_value) const { + return CImg(*this,false).normalize((Tfloat)min_value,(Tfloat)max_value); + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm. + /** + \par Example + \code + const CImg img("reference.jpg"), res = img.get_normalize(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_normalize.jpg + **/ + CImg& normalize() { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + T *ptrd = data(0,y,z,0); + cimg_forX(*this,x) { + const T *ptrs = ptrd; + float n = 0; + cimg_forC(*this,c) { n+=cimg::sqr((float)*ptrs); ptrs+=whd; } + n = (float)std::sqrt(n); + T *_ptrd = ptrd++; + if (n>0) cimg_forC(*this,c) { *_ptrd = (T)(*_ptrd/n); _ptrd+=whd; } + else cimg_forC(*this,c) { *_ptrd = (T)0; _ptrd+=whd; } + } + } + return *this; + } + + //! Normalize multi-valued pixels of the image instance, with respect to their L2-norm \newinstance. + CImg get_normalize() const { + return CImg(*this,false).normalize(); + } + + //! Compute Lp-norm of each multi-valued pixel of the image instance. + /** + \param norm_type Type of computed vector norm (can be \p -1=Linf, or \p>=0). + \par Example + \code + const CImg img("reference.jpg"), res = img.get_norm(); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_norm.jpg + **/ + CImg& norm(const int norm_type=2) { + if (_spectrum==1 && norm_type) return abs(); + return get_norm(norm_type).move_to(*this); + } + + //! Compute L2-norm of each multi-valued pixel of the image instance \newinstance. + CImg get_norm(const int norm_type=2) const { + if (is_empty()) return *this; + if (_spectrum==1 && norm_type) return get_abs(); + const ulongT whd = (ulongT)_width*_height*_depth; + CImg res(_width,_height,_depth); + switch (norm_type) { + case -1 : { // Linf-norm. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { const Tfloat val = (Tfloat)cimg::abs(*_ptrs); if (val>n) n = val; _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 0 : { // L0-norm. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + unsigned int n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=*_ptrs==0?0:1; _ptrs+=whd; } + *(ptrd++) = (Tfloat)n; + } + } + } break; + case 1 : { // L1-norm. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::abs(*_ptrs); _ptrs+=whd; } + *(ptrd++) = n; + } + } + } break; + case 2 : { // L2-norm. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=cimg::sqr((Tfloat)*_ptrs); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::sqrt((Tfloat)n); + } + } + } break; + default : { // Linf-norm. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16)) + cimg_forYZ(*this,y,z) { + const ulongT off = (ulongT)offset(0,y,z); + const T *ptrs = _data + off; + Tfloat *ptrd = res._data + off; + cimg_forX(*this,x) { + Tfloat n = 0; + const T *_ptrs = ptrs++; + cimg_forC(*this,c) { n+=std::pow(cimg::abs((Tfloat)*_ptrs),(Tfloat)norm_type); _ptrs+=whd; } + *(ptrd++) = (Tfloat)std::pow((Tfloat)n,1/(Tfloat)norm_type); + } + } + } + } + return res; + } + + //! Cut pixel values in specified range. + /** + \param min_value Minimum desired value of the resulting image. + \param max_value Maximum desired value of the resulting image. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_cut(160,220); + (img,res).display(); + \endcode + \image html ref_cut.jpg + **/ + CImg& cut(const T& min_value, const T& max_value) { + if (is_empty()) return *this; + const T a = min_value=32768)) + cimg_rof(*this,ptrd,T) *ptrd = (*ptrdb)?b:*ptrd); + return *this; + } + + //! Cut pixel values in specified range \newinstance. + CImg get_cut(const T& min_value, const T& max_value) const { + return (+*this).cut(min_value,max_value); + } + + //! Uniformly quantize pixel values. + /** + \param nb_levels Number of quantization levels. + \param keep_range Tells if resulting values keep the same range as the original ones. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_quantize(4); + (img,res).display(); + \endcode + \image html ref_quantize.jpg + **/ + CImg& quantize(const unsigned int nb_levels, const bool keep_range=true) { + if (!nb_levels) + throw CImgArgumentException(_cimg_instance + "quantize(): Invalid quantization request with 0 values.", + cimg_instance); + + if (is_empty()) return *this; + Tfloat m, M = (Tfloat)max_min(m), range = M - m; + if (range>0) { + if (keep_range) + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { + const unsigned int val = (unsigned int)((*ptrd-m)*nb_levels/range); + *ptrd = (T)(m + std::min(val,nb_levels - 1)*range/nb_levels); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { + const unsigned int val = (unsigned int)((*ptrd-m)*nb_levels/range); + *ptrd = (T)std::min(val,nb_levels - 1); + } + } + return *this; + } + + //! Uniformly quantize pixel values \newinstance. + CImg get_quantize(const unsigned int n, const bool keep_range=true) const { + return (+*this).quantize(n,keep_range); + } + + //! Threshold pixel values. + /** + \param value Threshold value + \param soft_threshold Tells if soft thresholding must be applied (instead of hard one). + \param strict_threshold Tells if threshold value is strict. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_threshold(128); + (img,res.normalize(0,255)).display(); + \endcode + \image html ref_threshold.jpg + **/ + CImg& threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) { + if (is_empty()) return *this; + if (strict_threshold) { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { + const T v = *ptrd; + *ptrd = v>value?(T)(v-value):v<-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536)) + cimg_rof(*this,ptrd,T) *ptrd = *ptrd>value?(T)1:(T)0; + } else { + if (soft_threshold) + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32768)) + cimg_rof(*this,ptrd,T) { + const T v = *ptrd; + *ptrd = v>=value?(T)(v-value):v<=-(float)value?(T)(v + value):(T)0; + } + else + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=65536)) + cimg_rof(*this,ptrd,T) *ptrd = *ptrd>=value?(T)1:(T)0; + } + return *this; + } + + //! Threshold pixel values \newinstance. + CImg get_threshold(const T& value, const bool soft_threshold=false, const bool strict_threshold=false) const { + return (+*this).threshold(value,soft_threshold,strict_threshold); + } + + //! Compute the histogram of pixel values. + /** + \param nb_levels Number of desired histogram levels. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \note + - The histogram H of an image I is the 1d function where H(x) counts the number of occurences of the value x + in the image I. + - The resulting histogram is always defined in 1d. Histograms of multi-valued images are not multi-dimensional. + \par Example + \code + const CImg img = CImg("reference.jpg").histogram(256); + img.display_graph(0,3); + \endcode + \image html ref_histogram.jpg + **/ + CImg& histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) { + return get_histogram(nb_levels,min_value,max_value).move_to(*this); + } + + //! Compute the histogram of pixel values \overloading. + CImg& histogram(const unsigned int nb_levels) { + return get_histogram(nb_levels).move_to(*this); + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels, const T& min_value, const T& max_value) const { + if (!nb_levels || is_empty()) return CImg(); + const double + vmin = (double)(min_value res(nb_levels,1,1,1,0); + cimg_rof(*this,ptrs,T) { + const T val = *ptrs; + if (val>=vmin && val<=vmax) ++res[val==vmax?nb_levels - 1:(unsigned int)((val - vmin)*nb_levels/(vmax - vmin))]; + } + return res; + } + + //! Compute the histogram of pixel values \newinstance. + CImg get_histogram(const unsigned int nb_levels) const { + if (!nb_levels || is_empty()) return CImg(); + T vmax = 0, vmin = min_max(vmax); + return get_histogram(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values. + /** + \param nb_levels Number of histogram levels used for the equalization. + \param min_value Minimum pixel value considered for the histogram computation. + All pixel values lower than \p min_value will not be counted. + \param max_value Maximum pixel value considered for the histogram computation. + All pixel values higher than \p max_value will not be counted. + \par Example + \code + const CImg img("reference.jpg"), res = img.get_equalize(256); + (img,res).display(); + \endcode + \image html ref_equalize.jpg + **/ + CImg& equalize(const unsigned int nb_levels, const T& min_value, const T& max_value) { + if (!nb_levels || is_empty()) return *this; + const T + vmin = min_value hist = get_histogram(nb_levels,vmin,vmax); + ulongT cumul = 0; + cimg_forX(hist,pos) { cumul+=hist[pos]; hist[pos] = cumul; } + if (!cumul) cumul = 1; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=1048576)) + cimg_rof(*this,ptrd,T) { + const int pos = (int)((*ptrd-vmin)*(nb_levels - 1.)/(vmax-vmin)); + if (pos>=0 && pos<(int)nb_levels) *ptrd = (T)(vmin + (vmax-vmin)*hist[pos]/cumul); + } + return *this; + } + + //! Equalize histogram of pixel values \overloading. + CImg& equalize(const unsigned int nb_levels) { + if (!nb_levels || is_empty()) return *this; + T vmax = 0, vmin = min_max(vmax); + return equalize(nb_levels,vmin,vmax); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels, const T& val_min, const T& val_max) const { + return (+*this).equalize(nblevels,val_min,val_max); + } + + //! Equalize histogram of pixel values \newinstance. + CImg get_equalize(const unsigned int nblevels) const { + return (+*this).equalize(nblevels); + } + + //! Index multi-valued pixels regarding to a specified colormap. + /** + \param colormap Multi-valued colormap used as the basis for multi-valued pixel indexing. + \param dithering Level of dithering (0=disable, 1=standard level). + \param map_indexes Tell if the values of the resulting image are the colormap indices or the colormap vectors. + \note + - \p img.index(colormap,dithering,1) is equivalent to img.index(colormap,dithering,0).map(colormap). + \par Example + \code + const CImg img("reference.jpg"), colormap(3,1,1,3, 0,128,255, 0,128,255, 0,128,255); + const CImg res = img.get_index(colormap,1,true); + (img,res).display(); + \endcode + \image html ref_index.jpg + **/ + template + CImg& index(const CImg& colormap, const float dithering=1, const bool map_indexes=false) { + return get_index(colormap,dithering,map_indexes).move_to(*this); + } + + //! Index multi-valued pixels regarding to a specified colormap \newinstance. + template + CImg::Tuint> + get_index(const CImg& colormap, const float dithering=1, const bool map_indexes=true) const { + if (colormap._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "index(): Instance and specified colormap (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + typedef typename CImg::Tuint tuint; + if (is_empty()) return CImg(); + const ulongT + whd = (ulongT)_width*_height*_depth, + pwhd = (ulongT)colormap._width*colormap._height*colormap._depth; + CImg res(_width,_height,_depth,map_indexes?_spectrum:1); + tuint *ptrd = res._data; + if (dithering>0) { // Dithered versions. + const float ndithering = cimg::cut(dithering,0,1)/16; + Tfloat valm = 0, valM = (Tfloat)max_min(valm); + if (valm==valM && valm>=0 && valM<=255) { valm = 0; valM = 255; } + CImg cache = get_crop(-1,0,0,0,_width,1,0,_spectrum - 1); + Tfloat *cache_current = cache.data(1,0,0,0), *cache_next = cache.data(1,1,0,0); + const ulongT cwhd = (ulongT)cache._width*cache._height*cache._depth; + switch (_spectrum) { + case 1 : { // Optimized for scalars. + cimg_forYZ(*this,y,z) { + if (yvalM?valM:_val0; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0valM?valM:_val0, + _val1 = (Tfloat)*ptrs1, val1 = _val1valM?valM:_val1, + _val2 = (Tfloat)*ptrs2, val2 = _val2valM?valM:_val2; + Tfloat distmin = cimg::type::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrpvalM?valM:_val; + dist+=cimg::sqr((*_ptrs=val) - (Tfloat)*_ptrp); _ptrs+=cwhd; _ptrp+=pwhd; + } + if (dist=64 && _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs0 = data(0,y,z), *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp_end = ptrp0 + pwhd; ptrp0=64 && _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp_end = ptrp1; ptrp0=64 && _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z), *ptrd1 = ptrd + whd, *ptrd2 = ptrd1 + whd; + for (const T *ptrs0 = data(0,y,z), *ptrs1 = ptrs0 + whd, *ptrs2 = ptrs1 + whd, + *ptrs_end = ptrs0 + _width; ptrs0::max(); const t *ptrmin0 = colormap._data; + for (const t *ptrp0 = colormap._data, *ptrp1 = ptrp0 + pwhd, *ptrp2 = ptrp1 + pwhd, + *ptrp_end = ptrp1; ptrp0=64 && _height*_depth>=16 && pwhd>=16)) + cimg_forYZ(*this,y,z) { + tuint *ptrd = res.data(0,y,z); + for (const T *ptrs = data(0,y,z), *ptrs_end = ptrs + _width; ptrs::max(); const t *ptrmin = colormap._data; + for (const t *ptrp = colormap._data, *ptrp_end = ptrp + pwhd; ptrp img("reference.jpg"), + colormap1(3,1,1,3, 0,128,255, 0,128,255, 0,128,255), + colormap2(3,1,1,3, 255,0,0, 0,255,0, 0,0,255), + res = img.get_index(colormap1,0).map(colormap2); + (img,res).display(); + \endcode + \image html ref_map.jpg + **/ + template + CImg& map(const CImg& colormap, const unsigned int boundary_conditions=0) { + return get_map(colormap,boundary_conditions).move_to(*this); + } + + //! Map predefined colormap on the scalar (indexed) image instance \newinstance. + template + CImg get_map(const CImg& colormap, const unsigned int boundary_conditions=0) const { + if (_spectrum!=1 && colormap._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "map(): Instance and specified colormap (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + const ulongT + whd = (ulongT)_width*_height*_depth, + pwhd = (ulongT)colormap._width*colormap._height*colormap._depth; + CImg res(_width,_height,_depth,colormap._spectrum==1?_spectrum:colormap._spectrum); + switch (colormap._spectrum) { + + case 1 : { // Optimized for scalars. + const T *ptrs = _data; + switch (boundary_conditions) { + case 2 : // Periodic boundaries. + cimg_for(res,ptrd,t) { + const ulongT ind = (ulongT)*(ptrs++); + *ptrd = colormap[ind%pwhd]; + } break; + case 1 : // Neumann boundaries. + cimg_for(res,ptrd,t) { + const longT ind = (longT)*(ptrs++); + *ptrd = colormap[cimg::cut(ind,(longT)0,(longT)pwhd - 1)]; + } break; + default : // Dirichlet boundaries. + cimg_for(res,ptrd,t) { + const ulongT ind = (ulongT)*(ptrs++); + *ptrd = ind& label(const bool is_high_connectivity=false, const Tfloat tolerance=0) { + return get_label(is_high_connectivity,tolerance).move_to(*this); + } + + //! Label connected components \newinstance. + CImg get_label(const bool is_high_connectivity=false, + const Tfloat tolerance=0) const { + if (is_empty()) return CImg(); + + // Create neighborhood tables. + int dx[13], dy[13], dz[13], nb = 0; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 0; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 0; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 0; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 0; + } + if (_depth>1) { // 3d version. + dx[nb] = 0; dy[nb] = 0; dz[nb++]=1; + if (is_high_connectivity) { + dx[nb] = 1; dy[nb] = 1; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = -1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = -1; + dx[nb] = 0; dy[nb] = 1; dz[nb++] = -1; + + dx[nb] = 0; dy[nb] = 1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = -1; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 0; dz[nb++] = 1; + dx[nb] = 1; dy[nb] = 1; dz[nb++] = 1; + } + } + return _label(nb,dx,dy,dz,tolerance); + } + + //! Label connected components \overloading. + /** + \param connectivity_mask Mask of the neighboring pixels. + \param tolerance Tolerance used to determine if two neighboring pixels belong to the same region. + **/ + template + CImg& label(const CImg& connectivity_mask, const Tfloat tolerance=0) { + return get_label(connectivity_mask,tolerance).move_to(*this); + } + + //! Label connected components \newinstance. + template + CImg get_label(const CImg& connectivity_mask, + const Tfloat tolerance=0) const { + int nb = 0; + cimg_for(connectivity_mask,ptr,t) if (*ptr) ++nb; + CImg dx(nb,1,1,1,0), dy(nb,1,1,1,0), dz(nb,1,1,1,0); + nb = 0; + cimg_forXYZ(connectivity_mask,x,y,z) if ((x || y || z) && + connectivity_mask(x,y,z)) { + dx[nb] = x; dy[nb] = y; dz[nb++] = z; + } + return _label(nb,dx,dy,dz,tolerance); + } + + CImg _label(const unsigned int nb, const int + *const dx, const int *const dy, const int *const dz, + const Tfloat tolerance) const { + CImg res(_width,_height,_depth,_spectrum); + cimg_forC(*this,c) { + CImg _res = res.get_shared_channel(c); + + // Init label numbers. + ulongT *ptr = _res.data(); + cimg_foroff(_res,p) *(ptr++) = p; + + // For each neighbour-direction, label. + for (unsigned int n = 0; n& _system_strescape() { +#define cimg_system_strescape(c,s) case c : if (p!=ptrs) CImg(ptrs,(unsigned int)(p-ptrs),1,1,1,false).\ + move_to(list); \ + CImg(s,(unsigned int)std::strlen(s),1,1,1,false).move_to(list); ptrs = p + 1; break + CImgList list; + const T *ptrs = _data; + cimg_for(*this,p,T) switch ((int)*p) { + cimg_system_strescape('\\',"\\\\"); + cimg_system_strescape('\"',"\\\""); + cimg_system_strescape('!',"\"\\!\""); + cimg_system_strescape('`',"\\`"); + cimg_system_strescape('$',"\\$"); + } + if (ptrs(ptrs,(unsigned int)(end()-ptrs),1,1,1,false).move_to(list); + return (list>'x').move_to(*this); + } + + //@} + //--------------------------------- + // + //! \name Color Base Management + //@{ + //--------------------------------- + + //! Return colormap \e "default", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_default.jpg + **/ + static const CImg& default_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,256,1,3); + for (unsigned int index = 0, r = 16; r<256; r+=32) + for (unsigned int g = 16; g<256; g+=32) + for (unsigned int b = 32; b<256; b+=64) { + colormap(0,index,0) = (Tuchar)r; + colormap(0,index,1) = (Tuchar)g; + colormap(0,index++,2) = (Tuchar)b; + } + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "HSV", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hsv.jpg + **/ + static const CImg& HSV_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + CImg tmp(1,256,1,3,1); + tmp.get_shared_channel(0).sequence(0,359); + colormap = tmp.HSVtoRGB(); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "lines", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_lines.jpg + **/ + static const CImg& lines_LUT256() { + static const unsigned char pal[] = { + 217,62,88,75,1,237,240,12,56,160,165,116,1,1,204,2,15,248,148,185,133,141,46,246,222,116,16,5,207,226, + 17,114,247,1,214,53,238,0,95,55,233,235,109,0,17,54,33,0,90,30,3,0,94,27,19,0,68,212,166,130,0,15,7,119, + 238,2,246,198,0,3,16,10,13,2,25,28,12,6,2,99,18,141,30,4,3,140,12,4,30,233,7,10,0,136,35,160,168,184,20, + 233,0,1,242,83,90,56,180,44,41,0,6,19,207,5,31,214,4,35,153,180,75,21,76,16,202,218,22,17,2,136,71,74, + 81,251,244,148,222,17,0,234,24,0,200,16,239,15,225,102,230,186,58,230,110,12,0,7,129,249,22,241,37,219, + 1,3,254,210,3,212,113,131,197,162,123,252,90,96,209,60,0,17,0,180,249,12,112,165,43,27,229,77,40,195,12, + 87,1,210,148,47,80,5,9,1,137,2,40,57,205,244,40,8,252,98,0,40,43,206,31,187,0,180,1,69,70,227,131,108,0, + 223,94,228,35,248,243,4,16,0,34,24,2,9,35,73,91,12,199,51,1,249,12,103,131,20,224,2,70,32, + 233,1,165,3,8,154,246,233,196,5,0,6,183,227,247,195,208,36,0,0,226,160,210,198,69,153,210,1,23,8,192,2,4, + 137,1,0,52,2,249,241,129,0,0,234,7,238,71,7,32,15,157,157,252,158,2,250,6,13,30,11,162,0,199,21,11,27,224, + 4,157,20,181,111,187,218,3,0,11,158,230,196,34,223,22,248,135,254,210,157,219,0,117,239,3,255,4,227,5,247, + 11,4,3,188,111,11,105,195,2,0,14,1,21,219,192,0,183,191,113,241,1,12,17,248,0,48,7,19,1,254,212,0,239,246, + 0,23,0,250,165,194,194,17,3,253,0,24,6,0,141,167,221,24,212,2,235,243,0,0,205,1,251,133,204,28,4,6,1,10, + 141,21,74,12,236,254,228,19,1,0,214,1,186,13,13,6,13,16,27,209,6,216,11,207,251,59,32,9,155,23,19,235,143, + 116,6,213,6,75,159,23,6,0,228,4,10,245,249,1,7,44,234,4,102,174,0,19,239,103,16,15,18,8,214,22,4,47,244, + 255,8,0,251,173,1,212,252,250,251,252,6,0,29,29,222,233,246,5,149,0,182,180,13,151,0,203,183,0,35,149,0, + 235,246,254,78,9,17,203,73,11,195,0,3,5,44,0,0,237,5,106,6,130,16,214,20,168,247,168,4,207,11,5,1,232,251, + 129,210,116,231,217,223,214,27,45,38,4,177,186,249,7,215,172,16,214,27,249,230,236,2,34,216,217,0,175,30, + 243,225,244,182,20,212,2,226,21,255,20,0,2,13,62,13,191,14,76,64,20,121,4,118,0,216,1,147,0,2,210,1,215, + 95,210,236,225,184,46,0,248,24,11,1,9,141,250,243,9,221,233,160,11,147,2,55,8,23,12,253,9,0,54,0,231,6,3, + 141,8,2,246,9,180,5,11,8,227,8,43,110,242,1,130,5,97,36,10,6,219,86,133,11,108,6,1,5,244,67,19,28,0,174, + 154,16,127,149,252,188,196,196,228,244,9,249,0,0,0,37,170,32,250,0,73,255,23,3,224,234,38,195,198,0,255,87, + 33,221,174,31,3,0,189,228,6,153,14,144,14,108,197,0,9,206,245,254,3,16,253,178,248,0,95,125,8,0,3,168,21, + 23,168,19,50,240,244,185,0,1,144,10,168,31,82,1,13 }; + static const CImg colormap(pal,1,256,1,3,false); + return colormap; + } + + //! Return colormap \e "hot", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_hot.jpg + **/ + static const CImg& hot_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[1] = colormap[2] = colormap[3] = colormap[6] = colormap[7] = colormap[11] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cool", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cool.jpg + **/ + static const CImg& cool_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) colormap.assign(1,2,1,3).fill((T)0,(T)255,(T)255,(T)0,(T)255,(T)255).resize(1,256,1,3,3); + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "jet", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_jet.jpg + **/ + static const CImg& jet_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[2] = colormap[3] = colormap[5] = colormap[6] = colormap[8] = colormap[9] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "flag", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_flag.jpg + **/ + static const CImg& flag_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,4,1,3,(T)0); + colormap[0] = colormap[1] = colormap[5] = colormap[9] = colormap[10] = 255; + colormap.resize(1,256,1,3,0,2); + } + cimg::mutex(8,0); + return colormap; + } + + //! Return colormap \e "cube", containing 256 colors entries in RGB. + /** + \return The following \c 256x1x1x3 colormap is returned: + \image html ref_colormap_cube.jpg + **/ + static const CImg& cube_LUT256() { + static CImg colormap; + cimg::mutex(8); + if (!colormap) { + colormap.assign(1,8,1,3,(T)0); + colormap[1] = colormap[3] = colormap[5] = colormap[7] = + colormap[10] = colormap[11] = colormap[12] = colormap[13] = + colormap[20] = colormap[21] = colormap[22] = colormap[23] = 255; + colormap.resize(1,256,1,3,3); + } + cimg::mutex(8,0); + return colormap; + } + + //! Convert pixel values from sRGB to RGB color spaces. + CImg& sRGBtoRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32)) + cimg_rof(*this,ptr,T) { + const Tfloat + sval = (Tfloat)*ptr/255, + val = (Tfloat)(sval<=0.04045f?sval/12.92f:std::pow((sval + 0.055f)/(1.055f),2.4f)); + *ptr = (T)cimg::cut(val*255,0,255); + } + return *this; + } + + //! Convert pixel values from sRGB to RGB color spaces \newinstance. + CImg get_sRGBtoRGB() const { + return CImg(*this,false).sRGBtoRGB(); + } + + //! Convert pixel values from RGB to sRGB color spaces. + CImg& RGBtosRGB() { + if (is_empty()) return *this; + cimg_pragma_openmp(parallel for cimg_openmp_if(size()>=32)) + cimg_rof(*this,ptr,T) { + const Tfloat + val = (Tfloat)*ptr/255, + sval = (Tfloat)(val<=0.0031308f?val*12.92f:1.055f*std::pow(val,0.416667f) - 0.055f); + *ptr = (T)cimg::cut(sval*255,0,255); + } + return *this; + } + + //! Convert pixel values from RGB to sRGB color spaces \newinstance. + CImg get_RGBtosRGB() const { + return CImg(*this,false).RGBtosRGB(); + } + + //! Convert pixel values from RGB to HSI color spaces. + CImg& RGBtoHSI() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSI(): Instance is not a RGB image.", + cimg_instance); + + 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>=256)) + for (ulongT N = 0; N0) H = B<=G?theta:360 - theta; + if (sum>0) S = 1 - 3*m/sum; + I = sum/(3*255); + p1[N] = (T)cimg::cut(H,0,360); + p2[N] = (T)cimg::cut(S,0,1); + p3[N] = (T)cimg::cut(I,0,1); + } + return *this; + } + + //! Convert pixel values from RGB to HSI color spaces \newinstance. + CImg get_RGBtoHSI() const { + return CImg(*this,false).RGBtoHSI(); + } + + //! Convert pixel values from HSI to RGB color spaces. + CImg& HSItoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSItoRGB(): Instance is not a HSI image.", + cimg_instance); + + 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>=256)) + for (ulongT N = 0; N get_HSItoRGB() const { + return CImg< Tuchar>(*this,false).HSItoRGB(); + } + + //! Convert pixel values from RGB to HSL color spaces. + CImg& RGBtoHSL() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSL(): Instance is not a RGB image.", + cimg_instance); + + 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>=256)) + for (ulongT N = 0; N=6) H-=6; + H*=60; + S = 2*L<=1?(M - m)/(M + m):(M - m)/(2*255 - M - m); + } + p1[N] = (T)cimg::cut(H,0,360); + p2[N] = (T)cimg::cut(S,0,1); + p3[N] = (T)cimg::cut(L,0,1); + } + return *this; + } + + //! Convert pixel values from RGB to HSL color spaces \newinstance. + CImg get_RGBtoHSL() const { + return CImg(*this,false).RGBtoHSL(); + } + + //! Convert pixel values from HSL to RGB color spaces. + CImg& HSLtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSLtoRGB(): Instance is not a HSL image.", + cimg_instance); + + 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>=256)) + for (ulongT N = 0; N1?tr - 1:tr, + ntg = tg<0?tg + 1:tg>1?tg - 1:tg, + ntb = tb<0?tb + 1:tb>1?tb - 1:tb, + R = 6*ntr<1?p + (q - p)*6*ntr:2*ntr<1?q:3*ntr<2?p + (q - p)*6*(2.0f/3 - ntr):p, + G = 6*ntg<1?p + (q - p)*6*ntg:2*ntg<1?q:3*ntg<2?p + (q - p)*6*(2.0f/3 - ntg):p, + B = 6*ntb<1?p + (q - p)*6*ntb:2*ntb<1?q:3*ntb<2?p + (q - p)*6*(2.0f/3 - ntb):p; + p1[N] = (T)cimg::cut(255*R,0,255); + p2[N] = (T)cimg::cut(255*G,0,255); + p3[N] = (T)cimg::cut(255*B,0,255); + } + return *this; + } + + //! Convert pixel values from HSL to RGB color spaces \newinstance. + CImg get_HSLtoRGB() const { + return CImg(*this,false).HSLtoRGB(); + } + + //! Convert pixel values from RGB to HSV color spaces. + CImg& RGBtoHSV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoHSV(): Instance is not a RGB image.", + cimg_instance); + + 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>=256)) + for (ulongT N = 0; N=6) H-=6; + H*=60; + S = (M - m)/M; + } + p1[N] = (T)cimg::cut(H,0,360); + p2[N] = (T)cimg::cut(S,0,1); + p3[N] = (T)cimg::cut(M/255,0,1); + } + return *this; + } + + //! Convert pixel values from RGB to HSV color spaces \newinstance. + CImg get_RGBtoHSV() const { + return CImg(*this,false).RGBtoHSV(); + } + + //! Convert pixel values from HSV to RGB color spaces. + CImg& HSVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "HSVtoRGB(): Instance is not a HSV image.", + cimg_instance); + + 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>=256)) + for (ulongT N = 0; N get_HSVtoRGB() const { + return CImg(*this,false).HSVtoRGB(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& RGBtoYCbCr() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYCbCr(): Instance is not a RGB image.", + cimg_instance); + + 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>=512)) + for (ulongT N = 0; N get_RGBtoYCbCr() const { + return CImg(*this,false).RGBtoYCbCr(); + } + + //! Convert pixel values from RGB to YCbCr color spaces. + CImg& YCbCrtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YCbCrtoRGB(): Instance is not a YCbCr image.", + cimg_instance); + + 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>=512)) + for (ulongT N = 0; N get_YCbCrtoRGB() const { + return CImg(*this,false).YCbCrtoRGB(); + } + + //! Convert pixel values from RGB to YUV color spaces. + CImg& RGBtoYUV() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoYUV(): Instance is not a RGB image.", + cimg_instance); + + 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>=16384)) + for (ulongT N = 0; N get_RGBtoYUV() const { + return CImg(*this,false).RGBtoYUV(); + } + + //! Convert pixel values from YUV to RGB color spaces. + CImg& YUVtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "YUVtoRGB(): Instance is not a YUV image.", + cimg_instance); + + 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>=16384)) + for (ulongT N = 0; N get_YUVtoRGB() const { + return CImg< Tuchar>(*this,false).YUVtoRGB(); + } + + //! Convert pixel values from RGB to CMY color spaces. + CImg& RGBtoCMY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoCMY(): Instance is not a RGB image.", + cimg_instance); + + 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>=2048)) + for (ulongT N = 0; N get_RGBtoCMY() const { + return CImg(*this,false).RGBtoCMY(); + } + + //! Convert pixel values from CMY to RGB color spaces. + CImg& CMYtoRGB() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoRGB(): Instance is not a CMY image.", + cimg_instance); + + 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>=2048)) + for (ulongT N = 0; N get_CMYtoRGB() const { + return CImg(*this,false).CMYtoRGB(); + } + + //! Convert pixel values from CMY to CMYK color spaces. + CImg& CMYtoCMYK() { + return get_CMYtoCMYK().move_to(*this); + } + + //! Convert pixel values from CMY to CMYK color spaces \newinstance. + CImg get_CMYtoCMYK() const { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "CMYtoCMYK(): Instance is not a CMY image.", + cimg_instance); + + CImg res(_width,_height,_depth,4); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3); + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=1024)) + for (ulongT N = 0; N=255) C = M = Y = 0; + else { const Tfloat K1 = 255 - K; C = 255*(C - K)/K1; M = 255*(M - K)/K1; Y = 255*(Y - K)/K1; } + pd1[N] = (Tfloat)cimg::cut(C,0,255), + pd2[N] = (Tfloat)cimg::cut(M,0,255), + pd3[N] = (Tfloat)cimg::cut(Y,0,255), + pd4[N] = (Tfloat)cimg::cut(K,0,255); + } + return res; + } + + //! Convert pixel values from CMYK to CMY color spaces. + CImg& CMYKtoCMY() { + return get_CMYKtoCMY().move_to(*this); + } + + //! Convert pixel values from CMYK to CMY color spaces \newinstance. + CImg get_CMYKtoCMY() const { + if (_spectrum!=4) + throw CImgInstanceException(_cimg_instance + "CMYKtoCMY(): Instance is not a CMYK image.", + cimg_instance); + + CImg res(_width,_height,_depth,3); + const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2), *ps4 = data(0,0,0,3); + Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2); + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for cimg_openmp_if(whd>=1024)) + for (ulongT N = 0; N& RGBtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "RGBtoXYZ(): Instance is not a RGB image.", + cimg_instance); + + 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>=2048)) + for (ulongT N = 0; N get_RGBtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).RGBtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to RGB color spaces. + /** + \param use_D65 Tell to use the D65 illuminant (D50 otherwise). + **/ + CImg& XYZtoRGB(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoRGB(): Instance is not a XYZ image.", + cimg_instance); + + 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>=2048)) + for (ulongT N = 0; N get_XYZtoRGB(const bool use_D65=true) const { + return CImg(*this,false).XYZtoRGB(use_D65); + } + + //! Convert pixel values from XYZ to Lab color spaces. + CImg& 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 white = CImg(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)) + for (ulongT N = 0; N get_XYZtoLab(const bool use_D65=true) const { + return CImg(*this,false).XYZtoLab(use_D65); + } + + //! Convert pixel values from Lab to XYZ color spaces. + CImg& LabtoXYZ(const bool use_D65=true) { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "LabtoXYZ(): Instance is not a Lab image.", + cimg_instance); + const CImg white = CImg(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)) + for (ulongT N = 0; N216?cX*cX*cX:(116*cX - 16)*27/24389), + Y = (Tfloat)(27*L>216?cY*cY*cY:27*L/24389), + Z = (Tfloat)(24389*cZ>216?cZ*cZ*cZ:(116*cZ - 16)*27/24389); + p1[N] = (T)(X*white[0]); + p2[N] = (T)(Y*white[1]); + p3[N] = (T)(Z*white[2]); + } + return *this; + } + + //! Convert pixel values from Lab to XYZ color spaces \newinstance. + CImg get_LabtoXYZ(const bool use_D65=true) const { + return CImg(*this,false).LabtoXYZ(use_D65); + } + + //! Convert pixel values from XYZ to xyY color spaces. + CImg& XYZtoxyY() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "XYZtoxyY(): Instance is not a XYZ image.", + cimg_instance); + + 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>=4096)) + for (ulongT N = 0; N0?sum:1; + p1[N] = (T)(X/nsum); + p2[N] = (T)(Y/nsum); + p3[N] = (T)Y; + } + return *this; + } + + //! Convert pixel values from XYZ to xyY color spaces \newinstance. + CImg get_XYZtoxyY() const { + return CImg(*this,false).XYZtoxyY(); + } + + //! Convert pixel values from xyY pixels to XYZ color spaces. + CImg& xyYtoXYZ() { + if (_spectrum!=3) + throw CImgInstanceException(_cimg_instance + "xyYtoXYZ(): Instance is not a xyY image.", + cimg_instance); + + 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>=4096)) + for (ulongT N = 0; N0?py:1; + p1[N] = (T)(px*Y/ny); + p2[N] = (T)Y; + p3[N] = (T)((1 - px - py)*Y/ny); + } + return *this; + } + + //! Convert pixel values from xyY pixels to XYZ color spaces \newinstance. + CImg get_xyYtoXYZ() const { + return CImg(*this,false).xyYtoXYZ(); + } + + //! Convert pixel values from RGB to Lab color spaces. + CImg& RGBtoLab(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoLab(use_D65); + } + + //! Convert pixel values from RGB to Lab color spaces \newinstance. + CImg get_RGBtoLab(const bool use_D65=true) const { + return CImg(*this,false).RGBtoLab(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces. + CImg& LabtoRGB(const bool use_D65=true) { + return LabtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from Lab to RGB color spaces \newinstance. + CImg get_LabtoRGB(const bool use_D65=true) const { + return CImg(*this,false).LabtoRGB(use_D65); + } + + //! Convert pixel values from RGB to xyY color spaces. + CImg& RGBtoxyY(const bool use_D65=true) { + return RGBtoXYZ(use_D65).XYZtoxyY(); + } + + //! Convert pixel values from RGB to xyY color spaces \newinstance. + CImg get_RGBtoxyY(const bool use_D65=true) const { + return CImg(*this,false).RGBtoxyY(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces. + CImg& xyYtoRGB(const bool use_D65=true) { + return xyYtoXYZ().XYZtoRGB(use_D65); + } + + //! Convert pixel values from xyY to RGB color spaces \newinstance. + CImg get_xyYtoRGB(const bool use_D65=true) const { + return CImg(*this,false).xyYtoRGB(use_D65); + } + + //! Convert pixel values from RGB to CMYK color spaces. + CImg& RGBtoCMYK() { + return RGBtoCMY().CMYtoCMYK(); + } + + //! Convert pixel values from RGB to CMYK color spaces \newinstance. + CImg get_RGBtoCMYK() const { + return CImg(*this,false).RGBtoCMYK(); + } + + //! Convert pixel values from CMYK to RGB color spaces. + CImg& CMYKtoRGB() { + return CMYKtoCMY().CMYtoRGB(); + } + + //! Convert pixel values from CMYK to RGB color spaces \newinstance. + CImg get_CMYKtoRGB() const { + return CImg(*this,false).CMYKtoRGB(); + } + + //@} + //------------------------------------------ + // + //! \name Geometric / Spatial Manipulation + //@{ + //------------------------------------------ + + static float _cimg_lanczos(const float x) { + if (x<=-2 || x>=2) return 0; + const float a = (float)cimg::PI*x, b = 0.5f*a; + return (float)(x?std::sin(a)*std::sin(b)/(a*b):1); + } + + //! Resize image to new dimensions. + /** + \param size_x Number of columns (new size along the X-axis). + \param size_y Number of rows (new size along the Y-axis). + \param size_z Number of slices (new size along the Z-axis). + \param size_c Number of vector-channels (new size along the C-axis). + \param interpolation_type Method of interpolation: + - -1 = no interpolation: raw memory resizing. + - 0 = no interpolation: additional space is filled according to \p boundary_conditions. + - 1 = nearest-neighbor interpolation. + - 2 = moving average interpolation. + - 3 = linear interpolation. + - 4 = grid interpolation. + - 5 = cubic interpolation. + - 6 = lanczos interpolation. + \param boundary_conditions Border condition type. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100). + **/ + CImg& resize(const int size_x, const int size_y=-100, + const int size_z=-100, const int size_c=-100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + if (!size_x || !size_y || !size_z || !size_c) return assign(); + const unsigned int + _sx = (unsigned int)(size_x<0?-size_x*width()/100:size_x), + _sy = (unsigned int)(size_y<0?-size_y*height()/100:size_y), + _sz = (unsigned int)(size_z<0?-size_z*depth()/100:size_z), + _sc = (unsigned int)(size_c<0?-size_c*spectrum()/100:size_c), + sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1; + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return *this; + if (is_empty()) return assign(sx,sy,sz,sc,(T)0); + if (interpolation_type==-1 && sx*sy*sz*sc==size()) { + _width = sx; _height = sy; _depth = sz; _spectrum = sc; + return *this; + } + return get_resize(sx,sy,sz,sc,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c).move_to(*this); + } + + //! Resize image to new dimensions \newinstance. + CImg get_resize(const int size_x, const int size_y = -100, + const int size_z = -100, const int size_c = -100, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + if (centering_x<0 || centering_x>1 || centering_y<0 || centering_y>1 || + centering_z<0 || centering_z>1 || centering_c<0 || centering_c>1) + throw CImgArgumentException(_cimg_instance + "resize(): Specified centering arguments (%g,%g,%g,%g) are outside range [0,1].", + cimg_instance, + centering_x,centering_y,centering_z,centering_c); + + if (!size_x || !size_y || !size_z || !size_c) return CImg(); + const unsigned int + _sx = (unsigned int)(size_x<0?-size_x*width()/100:size_x), + _sy = (unsigned int)(size_y<0?-size_y*height()/100:size_y), + _sz = (unsigned int)(size_z<0?-size_z*depth()/100:size_z), + _sc = (unsigned int)(size_c<0?-size_c*spectrum()/100:size_c), + sx = _sx?_sx:1, sy = _sy?_sy:1, sz = _sz?_sz:1, sc = _sc?_sc:1; + if (sx==_width && sy==_height && sz==_depth && sc==_spectrum) return +*this; + if (is_empty()) return CImg(sx,sy,sz,sc,(T)0); + CImg res; + switch (interpolation_type) { + + // Raw resizing. + // + case -1 : + std::memcpy(res.assign(sx,sy,sz,sc,(T)0)._data,_data,sizeof(T)*std::min(size(),(ulongT)sx*sy*sz*sc)); + break; + + // No interpolation. + // + case 0 : { + const int + xc = (int)(centering_x*((int)sx - width())), + yc = (int)(centering_y*((int)sy - height())), + zc = (int)(centering_z*((int)sz - depth())), + cc = (int)(centering_c*((int)sc - spectrum())); + + switch (boundary_conditions) { + case 2 : { // Periodic boundary. + res.assign(sx,sy,sz,sc); + const int + x0 = ((int)xc%width()) - width(), + y0 = ((int)yc%height()) - height(), + z0 = ((int)zc%depth()) - depth(), + c0 = ((int)cc%spectrum()) - spectrum(); + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=65536)) + for (int c = c0; c<(int)sc; c+=spectrum()) + for (int z = z0; z<(int)sz; z+=depth()) + for (int y = y0; y<(int)sy; y+=height()) + for (int x = x0; x<(int)sx; x+=width()) + res.draw_image(x,y,z,c,*this); + } break; + case 1 : { // Neumann boundary. + res.assign(sx,sy,sz,sc).draw_image(xc,yc,zc,cc,*this); + CImg sprite; + if (xc>0) { // X-backward + res.get_crop(xc,yc,zc,cc,xc,yc + height() - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc - 1; x>=0; --x) res.draw_image(x,yc,zc,cc,sprite); + } + if (xc + width()<(int)sx) { // X-forward + res.get_crop(xc + width() - 1,yc,zc,cc,xc + width() - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int x = xc + width(); x<(int)sx; ++x) res.draw_image(x,yc,zc,cc,sprite); + } + if (yc>0) { // Y-backward + res.get_crop(0,yc,zc,cc,sx - 1,yc,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc - 1; y>=0; --y) res.draw_image(0,y,zc,cc,sprite); + } + if (yc + height()<(int)sy) { // Y-forward + res.get_crop(0,yc + height() - 1,zc,cc,sx - 1,yc + height() - 1, + zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int y = yc + height(); y<(int)sy; ++y) res.draw_image(0,y,zc,cc,sprite); + } + if (zc>0) { // Z-backward + res.get_crop(0,0,zc,cc,sx - 1,sy - 1,zc,cc + spectrum() - 1).move_to(sprite); + for (int z = zc - 1; z>=0; --z) res.draw_image(0,0,z,cc,sprite); + } + if (zc + depth()<(int)sz) { // Z-forward + res.get_crop(0,0,zc +depth() - 1,cc,sx - 1,sy - 1,zc + depth() - 1,cc + spectrum() - 1).move_to(sprite); + for (int z = zc + depth(); z<(int)sz; ++z) res.draw_image(0,0,z,cc,sprite); + } + if (cc>0) { // C-backward + res.get_crop(0,0,0,cc,sx - 1,sy - 1,sz - 1,cc).move_to(sprite); + for (int c = cc - 1; c>=0; --c) res.draw_image(0,0,0,c,sprite); + } + if (cc + spectrum()<(int)sc) { // C-forward + res.get_crop(0,0,0,cc + spectrum() - 1,sx - 1,sy - 1,sz - 1,cc + spectrum() - 1).move_to(sprite); + for (int c = cc + spectrum(); c<(int)sc; ++c) res.draw_image(0,0,0,c,sprite); + } + } break; + default : // Dirichlet boundary. + res.assign(sx,sy,sz,sc,(T)0).draw_image(xc,yc,zc,cc,*this); + } + break; + } break; + + // Nearest neighbor interpolation. + // + case 1 : { + res.assign(sx,sy,sz,sc); + CImg off_x(sx), off_y(sy + 1), off_z(sz + 1), off_c(sc + 1); + const ulongT + wh = (ulongT)_width*_height, + whd = (ulongT)_width*_height*_depth, + sxy = (ulongT)sx*sy, + sxyz = (ulongT)sx*sy*sz; + if (sx==_width) off_x.fill(1); + else { + ulongT *poff_x = off_x._data, curr = 0; + cimg_forX(res,x) { + const ulongT old = curr; + curr = (ulongT)((x + 1.0)*_width/sx); + *(poff_x++) = curr - old; + } + } + if (sy==_height) off_y.fill(_width); + else { + ulongT *poff_y = off_y._data, curr = 0; + cimg_forY(res,y) { + const ulongT old = curr; + curr = (ulongT)((y + 1.0)*_height/sy); + *(poff_y++) = _width*(curr - old); + } + *poff_y = 0; + } + if (sz==_depth) off_z.fill(wh); + else { + ulongT *poff_z = off_z._data, curr = 0; + cimg_forZ(res,z) { + const ulongT old = curr; + curr = (ulongT)((z + 1.0)*_depth/sz); + *(poff_z++) = wh*(curr - old); + } + *poff_z = 0; + } + if (sc==_spectrum) off_c.fill(whd); + else { + ulongT *poff_c = off_c._data, curr = 0; + cimg_forC(res,c) { + const ulongT old = curr; + curr = (ulongT)((c + 1.0)*_spectrum/sc); + *(poff_c++) = whd*(curr - old); + } + *poff_c = 0; + } + + T *ptrd = res._data; + const T* ptrc = _data; + const ulongT *poff_c = off_c._data; + for (unsigned int c = 0; c tmp(sx,_height,_depth,_spectrum,0); + for (unsigned int a = _width*sx, b = _width, c = sx, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + cimg_forYZC(tmp,y,z,v) tmp(t,y,z,v)+=(Tfloat)(*this)(s,y,z,v)*d; + if (!b) { + cimg_forYZC(tmp,y,z,v) tmp(t,y,z,v)/=_width; + ++t; + b = _width; + } + if (!c) { ++s; c = sx; } + } + tmp.move_to(res); + instance_first = false; + } + if (sy!=_height) { + CImg tmp(sx,sy,_depth,_spectrum,0); + for (unsigned int a = _height*sy, b = _height, c = sy, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) + cimg_forXZC(tmp,x,z,v) tmp(x,t,z,v)+=(Tfloat)(*this)(x,s,z,v)*d; + else + cimg_forXZC(tmp,x,z,v) tmp(x,t,z,v)+=(Tfloat)res(x,s,z,v)*d; + if (!b) { + cimg_forXZC(tmp,x,z,v) tmp(x,t,z,v)/=_height; + ++t; + b = _height; + } + if (!c) { ++s; c = sy; } + } + tmp.move_to(res); + instance_first = false; + } + if (sz!=_depth) { + CImg tmp(sx,sy,sz,_spectrum,0); + for (unsigned int a = _depth*sz, b = _depth, c = sz, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) + cimg_forXYC(tmp,x,y,v) tmp(x,y,t,v)+=(Tfloat)(*this)(x,y,s,v)*d; + else + cimg_forXYC(tmp,x,y,v) tmp(x,y,t,v)+=(Tfloat)res(x,y,s,v)*d; + if (!b) { + cimg_forXYC(tmp,x,y,v) tmp(x,y,t,v)/=_depth; + ++t; + b = _depth; + } + if (!c) { ++s; c = sz; } + } + tmp.move_to(res); + instance_first = false; + } + if (sc!=_spectrum) { + CImg tmp(sx,sy,sz,sc,0); + for (unsigned int a = _spectrum*sc, b = _spectrum, c = sc, s = 0, t = 0; a; ) { + const unsigned int d = std::min(b,c); + a-=d; b-=d; c-=d; + if (instance_first) + cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)+=(Tfloat)(*this)(x,y,z,s)*d; + else + cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)+=(Tfloat)res(x,y,z,s)*d; + if (!b) { + cimg_forXYZ(tmp,x,y,z) tmp(x,y,z,t)/=_spectrum; + ++t; + b = _spectrum; + } + if (!c) { ++s; c = sc; } + } + tmp.move_to(res); + instance_first = false; + } + } break; + + // Linear interpolation. + // + case 3 : { + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg 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 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 double *pfoff = foff._data; + cimg_forX(resx,x) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXZC(resy,x,z,c) { + 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 double *pfoff = foff._data; + cimg_forY(resy,y) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + 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); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXYC(resz,x,y,c) { + 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 double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrssc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + 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); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXYZ(resc,x,y,z) { + 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 double *pfoff = foff._data; + cimg_forC(resc,c) { + const double alpha = *(pfoff++); + const T val1 = *ptrs, val2 = ptrs resx, resy, resz, resc; + if (sx!=_width) { + if (sx<_width) get_resize(sx,_height,_depth,_spectrum,1).move_to(resx); + else { + resx.assign(sx,_height,_depth,_spectrum,(T)0); + const int dx = (int)(2*sx), dy = 2*width(); + int err = (int)(dy + centering_x*(sx*dy/width() - dy)), xs = 0; + cimg_forX(resx,x) if ((err-=dy)<=0) { + cimg_forYZC(resx,y,z,c) resx(x,y,z,c) = (*this)(xs,y,z,c); + ++xs; + err+=dx; + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (sy<_height) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + resy.assign(sx,sy,_depth,_spectrum,(T)0); + const int dx = (int)(2*sy), dy = 2*height(); + int err = (int)(dy + centering_y*(sy*dy/height() - dy)), ys = 0; + cimg_forY(resy,y) if ((err-=dy)<=0) { + cimg_forXZC(resy,x,z,c) resy(x,y,z,c) = resx(x,ys,z,c); + ++ys; + err+=dx; + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (sz<_depth) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + resz.assign(sx,sy,sz,_spectrum,(T)0); + const int dx = (int)(2*sz), dy = 2*depth(); + int err = (int)(dy + centering_z*(sz*dy/depth() - dy)), zs = 0; + cimg_forZ(resz,z) if ((err-=dy)<=0) { + cimg_forXYC(resz,x,y,c) resz(x,y,z,c) = resy(x,y,zs,c); + ++zs; + err+=dx; + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (sc<_spectrum) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + resc.assign(sx,sy,sz,sc,(T)0); + const int dx = (int)(2*sc), dy = 2*spectrum(); + int err = (int)(dy + centering_c*(sc*dy/spectrum() - dy)), cs = 0; + cimg_forC(resc,c) if ((err-=dy)<=0) { + cimg_forXYZ(resc,x,y,z) resc(x,y,z,c) = resz(x,y,z,cs); + ++cs; + err+=dx; + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Cubic interpolation. + // + case 5 : { + const Tfloat vmin = (Tfloat)cimg::type::min(), vmax = (Tfloat)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg 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 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 *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 double *pfoff = foff._data; + cimg_forX(resx,x) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - 1):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + 1):val1, + val3 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXZC(resy,x,z,c) { + 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 double *pfoff = foff._data; + cimg_forY(resy,y) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sx):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sx):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + 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); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXYC(resz,x,y,c) { + 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 double *pfoff = foff._data; + cimg_forZ(resz,z) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxy):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxy):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + 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); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXYZ(resc,x,y,z) { + 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 double *pfoff = foff._data; + cimg_forC(resc,c) { + const double + t = *(pfoff++), + val1 = (double)*ptrs, + val0 = ptrs>ptrs0?(double)*(ptrs - sxyz):val1, + val2 = ptrs<=ptrsmax?(double)*(ptrs + sxyz):val1, + val3 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Lanczos interpolation. + // + case 6 : { + const double vmin = (double)cimg::type::min(), vmax = (double)cimg::type::max(); + CImg off(cimg::max(sx,sy,sz,sc)); + CImg foff(off._width); + CImg 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 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 *const ptrs0 = data(0,y,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + 1, + *const ptrsmax = ptrs0 + (_width - 2); + 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 + 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), + 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 = ptrsvmax?vmax:val); + ptrs+=*(poff++); + } + } + } + } + } else resx.assign(*this,true); + + if (sy!=_height) { + if (_height==1) resx.get_resize(sx,sy,_depth,_spectrum,1).move_to(resy); + else { + if (_height>sy) resx.get_resize(sx,sy,_depth,_spectrum,2).move_to(resy); + else { + const double fy = (!boundary_conditions && sy>_height)?(sy>1?(_height - 1.0)/(sy - 1):0): + (double)_height/sy; + resy.assign(sx,sy,_depth,_spectrum); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forY(resy,y) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXZC(resy,x,z,c) { + const T *const ptrs0 = resx.data(x,0,z,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sx, + *const ptrsmax = ptrs0 + (_height - 2)*sx; + T *ptrd = resy.data(x,0,z,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forY(resy,y) { + 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), + 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 = ptrsvmax?vmax:val); + ptrd+=sx; + ptrs+=*(poff++); + } + } + } + } + resx.assign(); + } else resy.assign(resx,true); + + if (sz!=_depth) { + if (_depth==1) resy.get_resize(sx,sy,sz,_spectrum,1).move_to(resz); + else { + if (_depth>sz) resy.get_resize(sx,sy,sz,_spectrum,2).move_to(resz); + else { + 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); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forZ(resz,z) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXYC(resz,x,y,c) { + const T *const ptrs0 = resy.data(x,y,0,c), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxy, + *const ptrsmax = ptrs0 + (_depth - 2)*sxy; + T *ptrd = resz.data(x,y,0,c); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forZ(resz,z) { + 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), + 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 = ptrsvmax?vmax:val); + ptrd+=sxy; + ptrs+=*(poff++); + } + } + } + } + resy.assign(); + } else resz.assign(resy,true); + + if (sc!=_spectrum) { + if (_spectrum==1) resz.get_resize(sx,sy,sz,sc,1).move_to(resc); + else { + if (_spectrum>sc) resz.get_resize(sx,sy,sz,sc,2).move_to(resc); + else { + 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); + curr = old = 0; + unsigned int *poff = off._data; + double *pfoff = foff._data; + cimg_forC(resc,c) { + *(pfoff++) = curr - (unsigned int)curr; + old = curr; + 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)) + cimg_forXYZ(resc,x,y,z) { + const T *const ptrs0 = resz.data(x,y,z,0), *ptrs = ptrs0, *const ptrsmin = ptrs0 + sxyz, + *const ptrsmax = ptrs + (_spectrum - 2)*sxyz; + T *ptrd = resc.data(x,y,z,0); + const unsigned int *poff = off._data; + const double *pfoff = foff._data; + cimg_forC(resc,c) { + 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), + 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 = ptrsvmax?vmax:val); + ptrd+=sxyz; + ptrs+=*(poff++); + } + } + } + } + resz.assign(); + } else resc.assign(resz,true); + + return resc._is_shared?(resz._is_shared?(resy._is_shared?(resx._is_shared?(+(*this)):resx):resy):resz):resc; + } break; + + // Unknow interpolation. + // + default : + throw CImgArgumentException(_cimg_instance + "resize(): Invalid specified interpolation %d " + "(should be { -1=raw | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | " + "5=cubic | 6=lanczos }).", + cimg_instance, + interpolation_type); + } + return res; + } + + //! Resize image to dimensions of another image. + /** + \param src Reference image used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + template + CImg& resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of another image \newinstance. + template + CImg get_resize(const CImg& src, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(src._width,src._height,src._depth,src._spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window. + /** + \param disp Reference display window used for dimensions. + \param interpolation_type Interpolation method. + \param boundary_conditions Boundary conditions. + \param centering_x Set centering type (only if \p interpolation_type=0). + \param centering_y Set centering type (only if \p interpolation_type=0). + \param centering_z Set centering type (only if \p interpolation_type=0). + \param centering_c Set centering type (only if \p interpolation_type=0). + **/ + CImg& resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) { + return resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to dimensions of a display window \newinstance. + CImg get_resize(const CImgDisplay& disp, + const int interpolation_type=1, const unsigned int boundary_conditions=0, + const float centering_x = 0, const float centering_y = 0, + const float centering_z = 0, const float centering_c = 0) const { + return get_resize(disp.width(),disp.height(),_depth,_spectrum,interpolation_type,boundary_conditions, + centering_x,centering_y,centering_z,centering_c); + } + + //! Resize image to half-size along XY axes, using an optimized filter. + CImg& resize_halfXY() { + return get_resize_halfXY().move_to(*this); + } + + //! Resize image to half-size along XY axes, using an optimized filter \newinstance. + CImg get_resize_halfXY() const { + if (is_empty()) return *this; + static const Tfloat kernel[9] = { 0.07842776544f, 0.1231940459f, 0.07842776544f, + 0.1231940459f, 0.1935127547f, 0.1231940459f, + 0.07842776544f, 0.1231940459f, 0.07842776544f }; + CImg I(9), res(_width/2,_height/2,_depth,_spectrum); + T *ptrd = res._data; + cimg_forZC(*this,z,c) cimg_for3x3(*this,x,y,z,c,I,T) + if (x%2 && y%2) *(ptrd++) = (T) + (I[0]*kernel[0] + I[1]*kernel[1] + I[2]*kernel[2] + + I[3]*kernel[3] + I[4]*kernel[4] + I[5]*kernel[5] + + I[6]*kernel[6] + I[7]*kernel[7] + I[8]*kernel[8]); + return res; + } + + //! Resize image to double-size, using the Scale2X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_doubleXY() { + return get_resize_doubleXY().move_to(*this); + } + + //! Resize image to double-size, using the Scale2X algorithm \newinstance. + CImg get_resize_doubleXY() const { +#define _cimg_gs2x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=(res)._width, ptrd2+=(res)._width) + +#define _cimg_gs2x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs2x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(_width<<1,_height<<1,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width; + _cimg_gs2x_for3x3(*this,x,y,z,c,I,T) { + if (Icp!=Icn && Ipc!=Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = Ipc==Icn?Ipc:Icc; + *(ptrd2++) = Icn==Inc?Inc:Icc; + } else { *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; } + } + } + return res; + } + + //! Resize image to triple-size, using the Scale3X algorithm. + /** + \note Use anisotropic upscaling algorithm + described here. + **/ + CImg& resize_tripleXY() { + return get_resize_tripleXY().move_to(*this); + } + + //! Resize image to triple-size, using the Scale3X algorithm \newinstance. + CImg get_resize_tripleXY() const { +#define _cimg_gs3x_for3(bound,i) \ + for (int i = 0, _p1##i = 0, \ + _n1##i = 1>=(bound)?(int)(bound) - 1:1; \ + _n1##i<(int)(bound) || i==--_n1##i; \ + _p1##i = i++, ++_n1##i, ptrd1+=2*(res)._width, ptrd2+=2*(res)._width, ptrd3+=2*(res)._width) + +#define _cimg_gs3x_for3x3(img,x,y,z,c,I,T) \ + _cimg_gs3x_for3((img)._height,y) for (int x = 0, \ + _p1##x = 0, \ + _n1##x = (int)( \ + (I[0] = I[1] = (T)(img)(_p1##x,_p1##y,z,c)), \ + (I[3] = I[4] = (T)(img)(0,y,z,c)), \ + (I[6] = I[7] = (T)(img)(0,_n1##y,z,c)), \ + 1>=(img)._width?(img).width() - 1:1); \ + (_n1##x<(img).width() && ( \ + (I[2] = (T)(img)(_n1##x,_p1##y,z,c)), \ + (I[5] = (T)(img)(_n1##x,y,z,c)), \ + (I[8] = (T)(img)(_n1##x,_n1##y,z,c)),1)) || \ + x==--_n1##x; \ + I[0] = I[1], I[1] = I[2], \ + I[3] = I[4], I[4] = I[5], \ + I[6] = I[7], I[7] = I[8], \ + _p1##x = x++, ++_n1##x) + + if (is_empty()) return *this; + CImg res(3*_width,3*_height,_depth,_spectrum); + CImg_3x3(I,T); + cimg_forZC(*this,z,c) { + T + *ptrd1 = res.data(0,0,z,c), + *ptrd2 = ptrd1 + res._width, + *ptrd3 = ptrd2 + res._width; + _cimg_gs3x_for3x3(*this,x,y,z,c,I,T) { + if (Icp != Icn && Ipc != Inc) { + *(ptrd1++) = Ipc==Icp?Ipc:Icc; + *(ptrd1++) = (Ipc==Icp && Icc!=Inp) || (Icp==Inc && Icc!=Ipp)?Icp:Icc; + *(ptrd1++) = Icp==Inc?Inc:Icc; + *(ptrd2++) = (Ipc==Icp && Icc!=Ipn) || (Ipc==Icn && Icc!=Ipp)?Ipc:Icc; + *(ptrd2++) = Icc; + *(ptrd2++) = (Icp==Inc && Icc!=Inn) || (Icn==Inc && Icc!=Inp)?Inc:Icc; + *(ptrd3++) = Ipc==Icn?Ipc:Icc; + *(ptrd3++) = (Ipc==Icn && Icc!=Inn) || (Icn==Inc && Icc!=Ipn)?Icn:Icc; + *(ptrd3++) = Icn==Inc?Inc:Icc; + } else { + *(ptrd1++) = Icc; *(ptrd1++) = Icc; *(ptrd1++) = Icc; + *(ptrd2++) = Icc; *(ptrd2++) = Icc; *(ptrd2++) = Icc; + *(ptrd3++) = Icc; *(ptrd3++) = Icc; *(ptrd3++) = Icc; + } + } + } + return res; + } + + //! Mirror image content along specified axis. + /** + \param axis Mirror axis + **/ + CImg& mirror(const char axis) { + if (is_empty()) return *this; + T *pf, *pb, *buf = 0; + switch (cimg::lowercase(axis)) { + case 'x' : { + pf = _data; pb = data(_width - 1); + const unsigned int width2 = _width/2; + for (unsigned int yzv = 0; yzv<_height*_depth*_spectrum; ++yzv) { + for (unsigned int x = 0; x get_mirror(const char axis) const { + return (+*this).mirror(axis); + } + + //! Mirror image content along specified axes. + /** + \param axes Mirror axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& mirror(const char *const axes) { + for (const char *s = axes; *s; ++s) mirror(*s); + return *this; + } + + //! Mirror image content along specified axes \newinstance. + CImg get_mirror(const char *const axes) const { + return (+*this).mirror(axes); + } + + //! Shift image content. + /** + \param delta_x Amount of displacement along the X-axis. + \param delta_y Amount of displacement along the Y-axis. + \param delta_z Amount of displacement along the Z-axis. + \param delta_c Amount of displacement along the C-axis. + \param boundary_conditions Border condition. + + - \c boundary_conditions can be: + - 0: Zero border condition (Dirichlet). + - 1: Nearest neighbors (Neumann). + - 2: Repeat Pattern (Fourier style). + **/ + CImg& shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const int boundary_conditions=0) { + if (is_empty()) return *this; + if (delta_x) // Shift along X-axis + switch (boundary_conditions) { + case 0 : + if (cimg::abs(delta_x)>=width()) return fill((T)0); + if (delta_x<0) cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(-delta_x,y,z,c),(_width + delta_x)*sizeof(T)); + std::memset(data(_width + delta_x,y,z,c),0,-delta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memmove(data(delta_x,y,z,c),data(0,y,z,c),(_width-delta_x)*sizeof(T)); + std::memset(data(0,y,z,c),0,delta_x*sizeof(T)); + } + break; + case 1 : + if (delta_x<0) { + const int ndelta_x = (-delta_x>=width())?width() - 1:-delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(_width - 1,y,z,c); + const T val = *ptrd; + for (int l = 0; l=width())?width() - 1:delta_x; + if (!ndelta_x) return *this; + cimg_forYZC(*this,y,z,c) { + std::memmove(data(ndelta_x,y,z,c),data(0,y,z,c),(_width-ndelta_x)*sizeof(T)); + T *ptrd = data(0,y,z,c); + const T val = *ptrd; + for (int l = 0; l0) cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(0,y,z,c),ndelta_x*sizeof(T)); + std::memmove(data(0,y,z,c),data(ndelta_x,y,z,c),(_width-ndelta_x)*sizeof(T)); + std::memcpy(data(_width-ndelta_x,y,z,c),buf,ndelta_x*sizeof(T)); + } else cimg_forYZC(*this,y,z,c) { + std::memcpy(buf,data(_width + ndelta_x,y,z,c),-ndelta_x*sizeof(T)); + std::memmove(data(-ndelta_x,y,z,c),data(0,y,z,c),(_width + ndelta_x)*sizeof(T)); + std::memcpy(data(0,y,z,c),buf,-ndelta_x*sizeof(T)); + } + delete[] buf; + } + } + + if (delta_y) // Shift along Y-axis + switch (boundary_conditions) { + case 0 : + if (cimg::abs(delta_y)>=height()) return fill((T)0); + if (delta_y<0) cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,-delta_y,z,c),_width*(_height + delta_y)*sizeof(T)); + std::memset(data(0,_height + delta_y,z,c),0,-delta_y*_width*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memmove(data(0,delta_y,z,c),data(0,0,z,c),_width*(_height-delta_y)*sizeof(T)); + std::memset(data(0,0,z,c),0,delta_y*_width*sizeof(T)); + } + break; + case 1 : + if (delta_y<0) { + const int ndelta_y = (-delta_y>=height())?height() - 1:-delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,_height-ndelta_y,z,c), *ptrs = data(0,_height - 1,z,c); + for (int l = 0; l=height())?height() - 1:delta_y; + if (!ndelta_y) return *this; + cimg_forZC(*this,z,c) { + std::memmove(data(0,ndelta_y,z,c),data(0,0,z,c),_width*(_height-ndelta_y)*sizeof(T)); + T *ptrd = data(0,1,z,c), *ptrs = data(0,0,z,c); + for (int l = 0; l0) cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,0,z,c),_width*ndelta_y*sizeof(T)); + std::memmove(data(0,0,z,c),data(0,ndelta_y,z,c),_width*(_height-ndelta_y)*sizeof(T)); + std::memcpy(data(0,_height-ndelta_y,z,c),buf,_width*ndelta_y*sizeof(T)); + } else cimg_forZC(*this,z,c) { + std::memcpy(buf,data(0,_height + ndelta_y,z,c),-ndelta_y*_width*sizeof(T)); + std::memmove(data(0,-ndelta_y,z,c),data(0,0,z,c),_width*(_height + ndelta_y)*sizeof(T)); + std::memcpy(data(0,0,z,c),buf,-ndelta_y*_width*sizeof(T)); + } + delete[] buf; + } + } + + if (delta_z) // Shift along Z-axis + switch (boundary_conditions) { + case 0 : + if (cimg::abs(delta_z)>=depth()) return fill((T)0); + if (delta_z<0) cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,-delta_z,c),_width*_height*(_depth + delta_z)*sizeof(T)); + std::memset(data(0,0,_depth + delta_z,c),0,_width*_height*(-delta_z)*sizeof(T)); + } else cimg_forC(*this,c) { + std::memmove(data(0,0,delta_z,c),data(0,0,0,c),_width*_height*(_depth-delta_z)*sizeof(T)); + std::memset(data(0,0,0,c),0,delta_z*_width*_height*sizeof(T)); + } + break; + case 1 : + if (delta_z<0) { + const int ndelta_z = (-delta_z>=depth())?depth() - 1:-delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,_depth-ndelta_z,c), *ptrs = data(0,0,_depth - 1,c); + for (int l = 0; l=depth())?depth() - 1:delta_z; + if (!ndelta_z) return *this; + cimg_forC(*this,c) { + std::memmove(data(0,0,ndelta_z,c),data(0,0,0,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + T *ptrd = data(0,0,1,c), *ptrs = data(0,0,0,c); + for (int l = 0; l0) cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,0,c),_width*_height*ndelta_z*sizeof(T)); + std::memmove(data(0,0,0,c),data(0,0,ndelta_z,c),_width*_height*(_depth-ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,_depth-ndelta_z,c),buf,_width*_height*ndelta_z*sizeof(T)); + } else cimg_forC(*this,c) { + std::memcpy(buf,data(0,0,_depth + ndelta_z,c),-ndelta_z*_width*_height*sizeof(T)); + std::memmove(data(0,0,-ndelta_z,c),data(0,0,0,c),_width*_height*(_depth + ndelta_z)*sizeof(T)); + std::memcpy(data(0,0,0,c),buf,-ndelta_z*_width*_height*sizeof(T)); + } + delete[] buf; + } + } + + if (delta_c) // Shift along C-axis + switch (boundary_conditions) { + case 0 : + if (cimg::abs(delta_c)>=spectrum()) return fill((T)0); + if (delta_c<0) { + std::memmove(_data,data(0,0,0,-delta_c),_width*_height*_depth*(_spectrum + delta_c)*sizeof(T)); + std::memset(data(0,0,0,_spectrum + delta_c),0,_width*_height*_depth*(-delta_c)*sizeof(T)); + } else { + std::memmove(data(0,0,0,delta_c),_data,_width*_height*_depth*(_spectrum-delta_c)*sizeof(T)); + std::memset(_data,0,delta_c*_width*_height*_depth*sizeof(T)); + } + break; + case 1 : + if (delta_c<0) { + const int ndelta_c = (-delta_c>=spectrum())?spectrum() - 1:-delta_c; + if (!ndelta_c) return *this; + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,_spectrum-ndelta_c), *ptrs = data(0,0,0,_spectrum - 1); + for (int l = 0; l=spectrum())?spectrum() - 1:delta_c; + if (!ndelta_c) return *this; + std::memmove(data(0,0,0,ndelta_c),_data,_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + T *ptrd = data(0,0,0,1); + for (int l = 0; l0) { + std::memcpy(buf,_data,_width*_height*_depth*ndelta_c*sizeof(T)); + std::memmove(_data,data(0,0,0,ndelta_c),_width*_height*_depth*(_spectrum-ndelta_c)*sizeof(T)); + std::memcpy(data(0,0,0,_spectrum-ndelta_c),buf,_width*_height*_depth*ndelta_c*sizeof(T)); + } else { + std::memcpy(buf,data(0,0,0,_spectrum + ndelta_c),-ndelta_c*_width*_height*_depth*sizeof(T)); + std::memmove(data(0,0,0,-ndelta_c),_data,_width*_height*_depth*(_spectrum + ndelta_c)*sizeof(T)); + std::memcpy(_data,buf,-ndelta_c*_width*_height*_depth*sizeof(T)); + } + delete[] buf; + } + } + return *this; + } + + //! Shift image content \newinstance. + CImg get_shift(const int delta_x, const int delta_y=0, const int delta_z=0, const int delta_c=0, + const int boundary_conditions=0) const { + return (+*this).shift(delta_x,delta_y,delta_z,delta_c,boundary_conditions); + } + + //! Permute axes order. + /** + \param order Axes permutations, as a C-string of 4 characters. + This function permutes image content regarding the specified axes permutation. + **/ + CImg& permute_axes(const char *const order) { + return get_permute_axes(order).move_to(*this); + } + + //! Permute axes order \newinstance. + CImg get_permute_axes(const char *const order) const { + const T foo = (T)0; + return _permute_axes(order,foo); + } + + template + CImg _permute_axes(const char *const permut, const t&) const { + if (is_empty() || !permut) return CImg(*this,false); + CImg res; + const T* ptrs = _data; + unsigned char s_code[4] = { 0,1,2,3 }, n_code[4] = { 0 }; + for (unsigned int l = 0; permut[l]; ++l) { + int c = cimg::lowercase(permut[l]); + if (c!='x' && c!='y' && c!='z' && c!='c') { *s_code = 4; break; } + else { ++n_code[c%=4]; s_code[l] = c; } + } + if (*permut && *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; + } + } + 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 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 permutation '%s'.", + cimg_instance, + permut); + return res; + } + + //! Unroll pixel values along specified axis. + /** + \param axis Unroll axis (can be \c 'x', \c 'y', \c 'z' or c 'c'). + **/ + CImg& unroll(const char axis) { + const unsigned int siz = (unsigned int)size(); + if (siz) switch (cimg::lowercase(axis)) { + case 'x' : _width = siz; _height = _depth = _spectrum = 1; break; + case 'y' : _height = siz; _width = _depth = _spectrum = 1; break; + case 'z' : _depth = siz; _width = _height = _spectrum = 1; break; + default : _spectrum = siz; _width = _height = _depth = 1; + } + return *this; + } + + //! Unroll pixel values along specified axis \newinstance. + CImg get_unroll(const char axis) const { + return (+*this).unroll(axis); + } + + //! Rotate image with arbitrary angle. + /** + \param angle Rotation angle, in degrees. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \note Most of the time, size of the image is modified. + **/ + CImg& rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.0f); + if (nangle==0.0f) return *this; + return get_rotate(nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle \newinstance. + CImg get_rotate(const float angle, const unsigned int interpolation=1, + const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res; + const float nangle = cimg::mod(angle,360.0f); + if (boundary_conditions!=1 && cimg::mod(nangle,90.0f)==0) { // Optimized version for orthogonal angles. + const int wm1 = width() - 1, hm1 = height() - 1; + const int iangle = (int)nangle/90; + switch (iangle) { + case 1 : { // 90 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(y,hm1 - x,z,c); + } break; + case 2 : { // 180 deg + res.assign(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - x,hm1 - y,z,c); + } break; + case 3 : { // 270 deg + res.assign(_height,_width,_depth,_spectrum); + T *ptrd = res._data; + cimg_forXYZC(res,x,y,z,c) *(ptrd++) = (*this)(wm1 - y,x,z,c); + } break; + default : // 0 deg + return *this; + } + } else { // Generic angle + const float + rad = (float)(nangle*cimg::PI/180.0), + ca = (float)std::cos(rad), sa = (float)std::sin(rad), + ux = cimg::abs((_width - 1)*ca), uy = cimg::abs((_width - 1)*sa), + vx = cimg::abs((_height - 1)*sa), vy = cimg::abs((_height - 1)*ca), + w2 = 0.5f*(_width - 1), h2 = 0.5f*(_height - 1); + res.assign((int)cimg::round(1 + ux + vx),(int)cimg::round(1 + uy + vy),_depth,_spectrum); + const float rw2 = 0.5f*(res._width - 1), rh2 = 0.5f*(res._height - 1); + _rotate(res,nangle,interpolation,boundary_conditions,w2,h2,rw2,rh2); + } + return res; + } + + //! Rotate image with arbitrary angle, around a center point. + /** + \param angle Rotation angle, in degrees. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \param interpolation_type Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + **/ + CImg& rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) { + return get_rotate(angle,cx,cy,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate image with arbitrary angle, around a center point \newinstance. + CImg get_rotate(const float angle, const float cx, const float cy, + const unsigned int interpolation, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + _rotate(res,angle,interpolation,boundary_conditions,cx,cy,cx,cy); + return res; + } + + // [internal] Perform 2d rotation with arbitrary angle. + void _rotate(CImg& res, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, + const float rw2, const float rh2) const { + const float + rad = (float)(angle*cimg::PI/180.0), + ca = (float)std::cos(rad), sa = (float)std::sin(rad); + + switch (boundary_conditions) { + case 0 : { // Dirichlet boundaries + switch (interpolation) { + case 2 : { // Cubic interpolation + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + const Tfloat val = cubic_atXY(w2 + xc*ca + yc*sa,h2 - xc*sa + yc*ca,z,c,(T)0); + res(x,y,z,c) = cimg::type::cut(val); + } + } break; + case 1 : { // Linear interpolation + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + res(x,y,z,c) = (T)linear_atXY(w2 + xc*ca + yc*sa,h2 - xc*sa + yc*ca,z,c,(T)0); + } + } break; + default : { // Nearest-neighbor interpolation + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + res(x,y,z,c) = atXY((int)cimg::round(w2 + xc*ca + yc*sa), + (int)cimg::round(h2 - xc*sa + yc*ca),z,c,(T)0); + } + } + } + } break; + case 1 : { // Neumann boundaries. + switch (interpolation) { + case 2 : { // Cubic interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + const Tfloat val = _cubic_atXY(w2 + xc*ca + yc*sa,h2 - xc*sa + yc*ca,z,c); + res(x,y,z,c) = cimg::type::cut(val); + } + } break; + case 1 : { // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + res(x,y,z,c) = (T)_linear_atXY(w2 + xc*ca + yc*sa,h2 - xc*sa + yc*ca,z,c); + } + } break; + default : { // Nearest-neighbor interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + res(x,y,z,c) = _atXY((int)cimg::round(w2 + xc*ca + yc*sa), + (int)cimg::round(h2 - xc*sa + yc*ca),z,c); + } + } + } + } break; + default : { // Periodic boundaries. + switch (interpolation) { + case 2 : { // Cubic interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + const Tfloat val = _cubic_atXY(cimg::mod(w2 + xc*ca + yc*sa,(float)width()), + cimg::mod(h2 - xc*sa + yc*ca,(float)height()),z,c); + res(x,y,z,c) = cimg::type::cut(val); + } + } break; + case 1 : { // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + res(x,y,z,c) = (T)_linear_atXY(cimg::mod(w2 + xc*ca + yc*sa,(float)width()), + cimg::mod(h2 - xc*sa + yc*ca,(float)height()),z,c); + } + } break; + default : { // Nearest-neighbor interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZC(res,x,y,z,c) { + const float xc = x - rw2, yc = y - rh2; + res(x,y,z,c) = (*this)(cimg::mod((int)cimg::round(w2 + xc*ca + yc*sa),(float)width()), + cimg::mod((int)cimg::round(h2 - xc*sa + yc*ca),(float)height()),z,c); + } + } + } + } break; + } + } + + //! Rotate volumetric image with arbitrary angle and axis. + /** + \param u X-coordinate of the 3d rotation axis. + \param v Y-coordinate of the 3d rotation axis. + \param w Z-coordinate of the 3d rotation axis. + \param angle Rotation angle, in degrees. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) { + const float nangle = cimg::mod(angle,360.0f); + if (nangle==0.0f) return *this; + return get_rotate(u,v,w,nangle,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const unsigned int interpolation, const unsigned int boundary_conditions) const { + if (is_empty()) return *this; + CImg res; + const float + w1 = _width - 1, h1 = _height - 1, d1 = _depth -1, + w2 = 0.5f*w1, h2 = 0.5f*h1, d2 = 0.5f*d1; + CImg R = CImg::rotation_matrix(u,v,w,angle); + const CImg + X = R*CImg(8,3,1,1, + 0.0f,w1,w1,0.0f,0.0f,w1,w1,0.0f, + 0.0f,0.0f,h1,h1,0.0f,0.0f,h1,h1, + 0.0f,0.0f,0.0f,0.0f,d1,d1,d1,d1); + float + xm, xM = X.get_shared_row(0).max_min(xm), + ym, yM = X.get_shared_row(1).max_min(ym), + zm, zM = X.get_shared_row(2).max_min(zm); + const int + dx = (int)cimg::round(xM - xm), + dy = (int)cimg::round(yM - ym), + dz = (int)cimg::round(zM - zm); + R.transpose(); + res.assign(1 + dx,1 + dy,1 + dz,_spectrum); + const float rw2 = 0.5f*dx, rh2 = 0.5f*dy, rd2 = 0.5f*dz; + _rotate(res,R,interpolation,boundary_conditions,w2,h2,d2,rw2,rh2,rd2); + return res; + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point. + /** + \param u X-coordinate of the 3d rotation axis. + \param v Y-coordinate of the 3d rotation axis. + \param w Z-coordinate of the 3d rotation axis. + \param cx X-coordinate of the rotation center. + \param cy Y-coordinate of the rotation center. + \param cz Z-coordinate of the rotation center. + \param angle Rotation angle, in degrees. + \param interpolation Type of interpolation. Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + \note Most of the time, size of the image is modified. + **/ + CImg rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + const float nangle = cimg::mod(angle,360.0f); + if (nangle==0.0f) return *this; + return get_rotate(u,v,w,nangle,cx,cy,cz,interpolation,boundary_conditions).move_to(*this); + } + + //! Rotate volumetric image with arbitrary angle and axis, around a center point \newinstance. + CImg get_rotate(const float u, const float v, const float w, const float angle, + const float cx, const float cy, const float cz, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty()) return *this; + CImg res(_width,_height,_depth,_spectrum); + CImg R = CImg::rotation_matrix(u,v,w,-angle); + _rotate(res,R,interpolation,boundary_conditions,cx,cy,cz,cx,cy,cz); + return res; + } + + // [internal] Perform 3d rotation with arbitrary axis and angle. + void _rotate(CImg& res, const CImg& R, + const unsigned int interpolation, const unsigned int boundary_conditions, + const float w2, const float h2, const float d2, + const float rw2, const float rh2, const float rd2) const { + switch (boundary_conditions) { + case 0 : { // Dirichlet boundaries + switch (interpolation) { + case 2 : { // Cubic interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc, + Y = h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc, + Z = d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc; + cimg_forC(res,c) res(x,y,z,c) = cimg::type::cut(cubic_atXYZ(X,Y,Z,c,(T)0)); + } + } break; + case 1 : { // Linear interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc, + Y = h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc, + Z = d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc; + cimg_forC(res,c) res(x,y,z,c) = linear_atXYZ(X,Y,Z,c,(T)0); + } + } break; + default : { // Nearest-neighbor interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float xc = x - rw2, yc = y - rh2, zc = z - rd2; + const int + X = (int)cimg::round(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc), + Y = (int)cimg::round(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc), + Z = (int)cimg::round(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc); + cimg_forC(res,c) res(x,y,z,c) = atXYZ(X,Y,Z,c,(T)0); + } + } + } + } break; + + case 1 : { // Neumann boundaries + switch (interpolation) { + case 2 : { // Cubic interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc, + Y = h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc, + Z = d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc; + cimg_forC(res,c) res(x,y,z,c) = cimg::type::cut(_cubic_atXYZ(X,Y,Z,c)); + } + } break; + case 1 : { // Linear interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc, + Y = h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc, + Z = d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc; + cimg_forC(res,c) res(x,y,z,c) = _linear_atXYZ(X,Y,Z,c); + } + } break; + default : { // Nearest-neighbor interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float xc = x - rw2, yc = y - rh2, zc = z - rd2; + const int + X = (int)cimg::round(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc), + Y = (int)cimg::round(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc), + Z = (int)cimg::round(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc); + cimg_forC(res,c) res(x,y,z,c) = _atXYZ(X,Y,Z,c); + } + } + } + } break; + + default : { // Periodic boundaries + switch (interpolation) { + case 2 : { // Cubic interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = cimg::mod((float)(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc),(float)width()), + Y = cimg::mod((float)(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc),(float)height()), + Z = cimg::mod((float)(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc),(float)depth()); + cimg_forC(res,c) res(x,y,z,c) = cimg::type::cut(_cubic_atXYZ(X,Y,Z,c)); + } + } break; + case 1 : { // Linear interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float + xc = x - rw2, yc = y - rh2, zc = z - rd2, + X = cimg::mod((float)(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc),(float)width()), + Y = cimg::mod((float)(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc),(float)height()), + Z = cimg::mod((float)(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc),(float)depth()); + cimg_forC(res,c) res(x,y,z,c) = (T)_linear_atXYZ(X,Y,Z,c); + } + } break; + default : { // Nearest-neighbor interpolation + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res.size()>=2048)) + cimg_forXYZ(res,x,y,z) { + const float xc = x - rw2, yc = y - rh2, zc = z - rd2; + const int + X = cimg::mod((int)cimg::round(w2 + R(0,0)*xc + R(1,0)*yc + R(2,0)*zc),width()), + Y = cimg::mod((int)cimg::round(h2 + R(0,1)*xc + R(1,1)*yc + R(2,1)*zc),height()), + Z = cimg::mod((int)cimg::round(d2 + R(0,2)*xc + R(1,2)*yc + R(2,2)*zc),depth()); + cimg_forC(res,c) res(x,y,z,c) = (*this)(X,Y,Z,c); + } + } + } + } break; + } + } + + //! Warp image content by a warping field. + /** + \param warp Warping field. + \param mode Can be { 0=backward-absolute | 1=backward-relative | 2=forward-absolute | 3=foward-relative } + \param is_relative Tells if warping field gives absolute or relative warping coordinates. + \param interpolation Can be { 0=nearest | 1=linear | 2=cubic }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann | 2=periodic }. + **/ + template + CImg& warp(const CImg& warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) { + return get_warp(warp,mode,interpolation,boundary_conditions).move_to(*this); + } + + //! Warp image content by a warping field \newinstance + template + CImg get_warp(const CImg& warp, const unsigned int mode=0, + const unsigned int interpolation=1, const unsigned int boundary_conditions=0) const { + if (is_empty() || !warp) return *this; + if (mode && !is_sameXYZ(warp)) + throw CImgArgumentException(_cimg_instance + "warp(): Instance and specified relative warping field (%u,%u,%u,%u,%p) " + "have different XYZ dimensions.", + cimg_instance, + warp._width,warp._height,warp._depth,warp._spectrum,warp._data); + + CImg res(warp._width,warp._height,warp._depth,_spectrum); + + if (warp._spectrum==1) { // 1d warping. + if (mode>=3) { // Forward-relative warp. + res.fill((T)0); + if (interpolation>=1) // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),x + (float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=1) // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atX(*(ptrs++),(float)*(ptrs0++),y,z,c); + } + else // Nearest-neighbor interpolation. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)); + if (X>=0 && X=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX(cimg::mod(x - (float)*(ptrs0++),(float)_width),y,z,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX(x - (float)*(ptrs0++),y,z,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)cubic_atX(x - (float)*(ptrs0++),y,z,c,(T)0); + } + } else if (interpolation==1) { // Linear interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(cimg::mod(x - (float)*(ptrs0++),(float)_width),y,z,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(x - (float)*(ptrs0++),y,z,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)linear_atX(x - (float)*(ptrs0++),y,z,c,(T)0); + } + } else { // Nearest-neighbor interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod(x - (int)cimg::round(*(ptrs0++)),(int)_width),y,z,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = _atX(x - (int)*(ptrs0++),y,z,c); + } + else // Dirichlet boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = atX(x - (int)*(ptrs0++),y,z,c,(T)0); + } + } + } else { // Backward-absolute warp. + if (interpolation==2) { // Cubic interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX(cimg::mod((float)*(ptrs0++),(float)_width),0,0,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atX((float)*(ptrs0++),0,0,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)cubic_atX((float)*(ptrs0++),0,0,c,(T)0); + } + } else if (interpolation==1) { // Linear interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atX(cimg::mod((float)*(ptrs0++),(float)_width),0,0,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atX((float)*(ptrs0++),0,0,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)linear_atX((float)*(ptrs0++),0,0,c,(T)0); + } + } else { // Nearest-neighbor interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod((int)cimg::round(*(ptrs0++)),(int)_width),0,0,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = _atX((int)*(ptrs0++),0,0,c); + } + else // Dirichlet boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = atX((int)*(ptrs0++),0,0,c,(T)0); + } + } + } + + } else if (warp._spectrum==2) { // 2d warping. + if (mode>=3) { // Forward-relative warp. + res.fill((T)0); + if (interpolation>=1) // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = x + (int)cimg::round(*(ptrs0++)), Y = y + (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=1) // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXY(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),z,c); + } + else // Nearest-neighbor interpolation. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int X = (int)cimg::round(*(ptrs0++)), Y = (int)cimg::round(*(ptrs1++)); + if (X>=0 && X=0 && Y=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY(cimg::mod(x - (float)*(ptrs0++),(float)_width), + cimg::mod(y - (float)*(ptrs1++),(float)_height),z,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)cubic_atXY(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c,(T)0); + } + } else if (interpolation==1) { // Linear interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(cimg::mod(x - (float)*(ptrs0++),(float)_width), + cimg::mod(y - (float)*(ptrs1++),(float)_height),z,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)linear_atXY(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z,c,(T)0); + } + } else { // Nearest-neighbor interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod(x - (int)cimg::round(*(ptrs0++)),(int)_width), + cimg::mod(y - (int)cimg::round(*(ptrs1++)),(int)_height),z,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = _atXY(x - (int)*(ptrs0++),y - (int)*(ptrs1++),z,c); + } + else // Dirichlet boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = atXY(x - (int)*(ptrs0++),y - (int)*(ptrs1++),z,c,(T)0); + } + } + } else { // Backward-absolute warp. + if (interpolation==2) { // Cubic interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY(cimg::mod((float)*(ptrs0++),(float)_width), + cimg::mod((float)*(ptrs1++),(float)_height),0,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXY((float)*(ptrs0++),(float)*(ptrs1++),0,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)cubic_atXY((float)*(ptrs0++),(float)*(ptrs1++),0,c,(T)0); + } + } else if (interpolation==1) { // Linear interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY(cimg::mod((float)*(ptrs0++),(float)_width), + cimg::mod((float)*(ptrs1++),(float)_height),0,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXY((float)*(ptrs0++),(float)*(ptrs1++),0,c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)linear_atXY((float)*(ptrs0++),(float)*(ptrs1++),0,c,(T)0); + } + } else { // Nearest-neighbor interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod((int)cimg::round(*(ptrs0++)),(int)_width), + cimg::mod((int)cimg::round(*(ptrs1++)),(int)_height),0,c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = _atXY((int)*(ptrs0++),(int)*(ptrs1++),0,c); + } + else // Dirichlet boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1); T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = atXY((int)*(ptrs0++),(int)*(ptrs1++),0,c,(T)0); + } + } + } + + } else { // 3d warping. + if (mode>=3) { // Forward-relative warp. + res.fill((T)0); + if (interpolation>=1) // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),x + (float)*(ptrs0++),y + (float)*(ptrs1++), + z + (float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = x + (int)cimg::round(*(ptrs0++)), + Y = y + (int)cimg::round(*(ptrs1++)), + Z = z + (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z=1) // Linear interpolation. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) res.set_linear_atXYZ(*(ptrs++),(float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c); + } + else // Nearest-neighbor interpolation. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + const T *ptrs = data(0,y,z,c); + cimg_forX(res,x) { + const int + X = (int)cimg::round(*(ptrs0++)), + Y = (int)cimg::round(*(ptrs1++)), + Z = (int)cimg::round(*(ptrs2++)); + if (X>=0 && X=0 && Y=0 && Z=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXYZ(cimg::mod(x - (float)*(ptrs0++),(float)_width), + cimg::mod(y - (float)*(ptrs1++),(float)_height), + cimg::mod(z - (float)*(ptrs2++),(float)_depth),c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) + *(ptrd++) = (T)_cubic_atXYZ(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) + *(ptrd++) = (T)cubic_atXYZ(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c,(T)0); + } + } else if (interpolation==1) { // Linear interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ(cimg::mod(x - (float)*(ptrs0++),(float)_width), + cimg::mod(y - (float)*(ptrs1++),(float)_height), + cimg::mod(z - (float)*(ptrs2++),(float)_depth),c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) + *(ptrd++) = (T)_linear_atXYZ(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) + *(ptrd++) = (T)linear_atXYZ(x - (float)*(ptrs0++),y - (float)*(ptrs1++),z - (float)*(ptrs2++),c,(T)0); + } + } else { // Nearest neighbor interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod(x - (int)cimg::round(*(ptrs0++)),(int)_width), + cimg::mod(y - (int)cimg::round(*(ptrs1++)),(int)_height), + cimg::mod(z - (int)cimg::round(*(ptrs2++)),(int)_depth),c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = _atXYZ(x - (int)*(ptrs0++),y - (int)*(ptrs1++),z - (int)*(ptrs2++),c); + } + else // Dirichlet boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = atXYZ(x - (int)*(ptrs0++),y - (int)*(ptrs1++),z - (int)*(ptrs2++),c,(T)0); + } + } + } else { // Backward-absolute warp. + if (interpolation==2) { // Cubic interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXYZ(cimg::mod((float)*(ptrs0++),(float)_width), + cimg::mod((float)*(ptrs1++),(float)_height), + cimg::mod((float)*(ptrs2++),(float)_depth),c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_cubic_atXYZ((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=4096)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)cubic_atXYZ((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++), + c,(T)0); + } + } else if (interpolation==1) { // Linear interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ(cimg::mod((float)*(ptrs0++),(float)_width), + cimg::mod((float)*(ptrs1++),(float)_height), + cimg::mod((float)*(ptrs2++),(float)_depth),c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)_linear_atXYZ((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++),c); + } + else // Dirichlet boundaries. + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(res.size()>=1048576)) + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (T)linear_atXYZ((float)*(ptrs0++),(float)*(ptrs1++),(float)*(ptrs2++), + c,(T)0); + } + } else { // Nearest-neighbor interpolation. + if (boundary_conditions==2) // Periodic boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = (*this)(cimg::mod((int)cimg::round(*(ptrs0++)),(int)_width), + cimg::mod((int)cimg::round(*(ptrs1++)),(int)_height), + cimg::mod((int)cimg::round(*(ptrs2++)),(int)_depth),c); + } + else if (boundary_conditions==1) // Neumann boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = _atXYZ((int)*(ptrs0++),(int)*(ptrs1++),(int)*(ptrs2++),c); + } + else // Dirichlet boundaries. + cimg_forYZC(res,y,z,c) { + const t *ptrs0 = warp.data(0,y,z,0), *ptrs1 = warp.data(0,y,z,1), *ptrs2 = warp.data(0,y,z,2); + T *ptrd = res.data(0,y,z,c); + cimg_forX(res,x) *(ptrd++) = atXYZ((int)*(ptrs0++),(int)*(ptrs1++),(int)*(ptrs2++),c,(T)0); + } + } + } + } + return res; + } + + //! Generate a 2d representation of a 3d image, with XY,XZ and YZ views. + /** + \param x0 X-coordinate of the projection point. + \param y0 Y-coordinate of the projection point. + \param z0 Z-coordinate of the projection point. + **/ + CImg get_projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) const { + if (is_empty() || _depth<2) return +*this; + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + const CImg + img_xy = get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1), + img_zy = get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).permute_axes("xzyc"). + resize(_depth,_height,1,-100,-1), + img_xz = get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1); + return CImg(_width + _depth,_height + _depth,1,_spectrum,cimg::min(img_xy.min(),img_zy.min(),img_xz.min())). + draw_image(0,0,img_xy).draw_image(img_xy._width,0,img_zy). + draw_image(0,img_xy._height,img_xz); + } + + //! Construct a 2d representation of a 3d image, with XY,XZ and YZ views \inplace. + CImg& projections2d(const unsigned int x0, const unsigned int y0, const unsigned int z0) { + if (_depth<2) return *this; + return get_projections2d(x0,y0,z0).move_to(*this); + } + + //! Crop image region. + /** + \param x0 = X-coordinate of the upper-left crop rectangle corner. + \param y0 = Y-coordinate of the upper-left crop rectangle corner. + \param z0 = Z-coordinate of the upper-left crop rectangle corner. + \param c0 = C-coordinate of the upper-left crop rectangle corner. + \param x1 = X-coordinate of the lower-right crop rectangle corner. + \param y1 = Y-coordinate of the lower-right crop rectangle corner. + \param z1 = Z-coordinate of the lower-right crop rectangle corner. + \param c1 = C-coordinate of the lower-right crop rectangle corner. + \param boundary_conditions = Dirichlet (false) or Neumann border conditions. + **/ + CImg& crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const bool boundary_conditions=false) { + return get_crop(x0,y0,z0,c0,x1,y1,z1,c1,boundary_conditions).move_to(*this); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, const int c0, + const int x1, const int y1, const int z1, const int c1, + const bool boundary_conditions=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "crop(): Empty instance.", + cimg_instance); + const int + nx0 = x0 res(1U + nx1 - nx0,1U + ny1 - ny0,1U + nz1 - nz0,1U + nc1 - nc0); + if (nx0<0 || nx1>=width() || ny0<0 || ny1>=height() || nz0<0 || nz1>=depth() || nc0<0 || nc1>=spectrum()) { + if (boundary_conditions) cimg_forXYZC(res,x,y,z,c) res(x,y,z,c) = _atXYZC(nx0 + x,ny0 + y,nz0 + z,nc0 + c); + else res.fill((T)0).draw_image(-nx0,-ny0,-nz0,-nc0,*this); + } else res.draw_image(-nx0,-ny0,-nz0,-nc0,*this); + return res; + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const bool boundary_conditions=false) { + return crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const bool boundary_conditions=false) const { + return get_crop(x0,y0,z0,0,x1,y1,z1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int y0, + const int x1, const int y1, + const bool boundary_conditions=false) { + return crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int y0, + const int x1, const int y1, + const bool boundary_conditions=false) const { + return get_crop(x0,y0,0,0,x1,y1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \overloading. + CImg& crop(const int x0, const int x1, const bool boundary_conditions=false) { + return crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Crop image region \newinstance. + CImg get_crop(const int x0, const int x1, const bool boundary_conditions=false) const { + return get_crop(x0,0,0,0,x1,_height - 1,_depth - 1,_spectrum - 1,boundary_conditions); + } + + //! Autocrop image region, regarding the specified background value. + CImg& autocrop(const T& value, const char *const axes="czyx") { + if (is_empty()) return *this; + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + const CImg coords = _autocrop(value,axis); + if (coords[0]==-1 && coords[1]==-1) return assign(); // Image has only 'value' pixels. + else switch (axis) { + case 'x' : { + const int x0 = coords[0], x1 = coords[1]; + if (x0>=0 && x1>=0) crop(x0,x1); + } break; + case 'y' : { + const int y0 = coords[0], y1 = coords[1]; + if (y0>=0 && y1>=0) crop(0,y0,_width - 1,y1); + } break; + case 'z' : { + const int z0 = coords[0], z1 = coords[1]; + if (z0>=0 && z1>=0) crop(0,0,z0,_width - 1,_height - 1,z1); + } break; + default : { + const int c0 = coords[0], c1 = coords[1]; + if (c0>=0 && c1>=0) crop(0,0,0,c0,_width - 1,_height - 1,_depth - 1,c1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background value \newinstance. + CImg get_autocrop(const T& value, const char *const axes="czyx") const { + return (+*this).autocrop(value,axes); + } + + //! Autocrop image region, regarding the specified background color. + /** + \param color Color used for the crop. If \c 0, color is guessed. + \param axes Axes used for the crop. + **/ + CImg& autocrop(const T *const color=0, const char *const axes="zyx") { + if (is_empty()) return *this; + if (!color) { // Guess color. + const CImg col1 = get_vector_at(0,0,0); + const unsigned int w = _width, h = _height, d = _depth, s = _spectrum; + autocrop(col1,axes); + if (_width==w && _height==h && _depth==d && _spectrum==s) { + const CImg col2 = get_vector_at(w - 1,h - 1,d - 1); + autocrop(col2,axes); + } + return *this; + } + for (const char *s = axes; *s; ++s) { + const char axis = cimg::lowercase(*s); + switch (axis) { + case 'x' : { + int x0 = width(), x1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'x'); + const int nx0 = coords[0], nx1 = coords[1]; + if (nx0>=0 && nx1>=0) { x0 = std::min(x0,nx0); x1 = std::max(x1,nx1); } + } + if (x0==width() && x1==-1) return assign(); else crop(x0,x1); + } break; + case 'y' : { + int y0 = height(), y1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'y'); + const int ny0 = coords[0], ny1 = coords[1]; + if (ny0>=0 && ny1>=0) { y0 = std::min(y0,ny0); y1 = std::max(y1,ny1); } + } + if (y0==height() && y1==-1) return assign(); else crop(0,y0,_width - 1,y1); + } break; + default : { + int z0 = depth(), z1 = -1; + cimg_forC(*this,c) { + const CImg coords = get_shared_channel(c)._autocrop(color[c],'z'); + const int nz0 = coords[0], nz1 = coords[1]; + if (nz0>=0 && nz1>=0) { z0 = std::min(z0,nz0); z1 = std::max(z1,nz1); } + } + if (z0==depth() && z1==-1) return assign(); else crop(0,0,z0,_width - 1,_height - 1,z1); + } + } + } + return *this; + } + + //! Autocrop image region, regarding the specified background color \newinstance. + CImg get_autocrop(const T *const color=0, const char *const axes="zyx") const { + return (+*this).autocrop(color,axes); + } + + //! Autocrop image region, regarding the specified background color \overloading. + template CImg& autocrop(const CImg& color, const char *const axes="zyx") { + return get_autocrop(color,axes).move_to(*this); + } + + //! Autocrop image region, regarding the specified background color \newinstance. + template CImg get_autocrop(const CImg& color, const char *const axes="zyx") const { + return get_autocrop(color._data,axes); + } + + CImg _autocrop(const T& value, const char axis) const { + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { + int x0 = -1, x1 = -1; + cimg_forX(*this,x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x0 = x; x = width(); y = height(); z = depth(); c = spectrum(); } + if (x0>=0) { + for (int x = width() - 1; x>=0; --x) cimg_forYZC(*this,y,z,c) + if ((*this)(x,y,z,c)!=value) { x1 = x; x = 0; y = height(); z = depth(); c = spectrum(); } + } + res = CImg::vector(x0,x1); + } break; + case 'y' : { + int y0 = -1, y1 = -1; + cimg_forY(*this,y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y0 = y; x = width(); y = height(); z = depth(); c = spectrum(); } + if (y0>=0) { + for (int y = height() - 1; y>=0; --y) cimg_forXZC(*this,x,z,c) + if ((*this)(x,y,z,c)!=value) { y1 = y; x = width(); y = 0; z = depth(); c = spectrum(); } + } + res = CImg::vector(y0,y1); + } break; + case 'z' : { + int z0 = -1, z1 = -1; + cimg_forZ(*this,z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z0 = z; x = width(); y = height(); z = depth(); c = spectrum(); } + if (z0>=0) { + for (int z = depth() - 1; z>=0; --z) cimg_forXYC(*this,x,y,c) + if ((*this)(x,y,z,c)!=value) { z1 = z; x = width(); y = height(); z = 0; c = spectrum(); } + } + res = CImg::vector(z0,z1); + } break; + default : { + int c0 = -1, c1 = -1; + cimg_forC(*this,c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c0 = c; x = width(); y = height(); z = depth(); c = spectrum(); } + if (c0>=0) { + for (int c = spectrum() - 1; c>=0; --c) cimg_forXYZ(*this,x,y,z) + if ((*this)(x,y,z,c)!=value) { c1 = c; x = width(); y = height(); z = depth(); c = 0; } + } + res = CImg::vector(c0,c1); + } + } + return res; + } + + //! Return specified image column. + /** + \param x0 Image column. + **/ + CImg get_column(const int x0) const { + return get_columns(x0,x0); + } + + //! Return specified image column \inplace. + CImg& column(const int x0) { + return columns(x0,x0); + } + + //! Return specified range of image columns. + /** + \param x0 Starting image column. + \param x1 Ending image column. + **/ + CImg& columns(const int x0, const int x1) { + return get_columns(x0,x1).move_to(*this); + } + + //! Return specified range of image columns \inplace. + CImg get_columns(const int x0, const int x1) const { + return get_crop(x0,0,0,0,x1,height() - 1,depth() - 1,spectrum() - 1); + } + + //! Return specified image row. + CImg get_row(const int y0) const { + return get_rows(y0,y0); + } + + //! Return specified image row \inplace. + /** + \param y0 Image row. + **/ + CImg& row(const int y0) { + return rows(y0,y0); + } + + //! Return specified range of image rows. + /** + \param y0 Starting image row. + \param y1 Ending image row. + **/ + CImg get_rows(const int y0, const int y1) const { + return get_crop(0,y0,0,0,width() - 1,y1,depth() - 1,spectrum() - 1); + } + + //! Return specified range of image rows \inplace. + CImg& rows(const int y0, const int y1) { + return get_rows(y0,y1).move_to(*this); + } + + //! Return specified image slice. + /** + \param z0 Image slice. + **/ + CImg get_slice(const int z0) const { + return get_slices(z0,z0); + } + + //! Return specified image slice \inplace. + CImg& slice(const int z0) { + return slices(z0,z0); + } + + //! Return specified range of image slices. + /** + \param z0 Starting image slice. + \param z1 Ending image slice. + **/ + CImg get_slices(const int z0, const int z1) const { + return get_crop(0,0,z0,0,width() - 1,height() - 1,z1,spectrum() - 1); + } + + //! Return specified range of image slices \inplace. + CImg& slices(const int z0, const int z1) { + return get_slices(z0,z1).move_to(*this); + } + + //! Return specified image channel. + /** + \param c0 Image channel. + **/ + CImg get_channel(const int c0) const { + return get_channels(c0,c0); + } + + //! Return specified image channel \inplace. + CImg& channel(const int c0) { + return channels(c0,c0); + } + + //! Return specified range of image channels. + /** + \param c0 Starting image channel. + \param c1 Ending image channel. + **/ + CImg get_channels(const int c0, const int c1) const { + return get_crop(0,0,0,c0,width() - 1,height() - 1,depth() - 1,c1); + } + + //! Return specified range of image channels \inplace. + CImg& channels(const int c0, const int c1) { + return get_channels(c0,c1).move_to(*this); + } + + //! Return stream line of a 2d or 3d vector field. + CImg get_streamline(const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false) const { + if (_spectrum!=2 && _spectrum!=3) + throw CImgInstanceException(_cimg_instance + "streamline(): Instance is not a 2d or 3d vector field.", + cimg_instance); + if (_spectrum==2) { + if (is_oriented_only) { + typename CImg::_functor4d_streamline2d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.0f,_height - 1.0f,0.0f); + } else { + typename CImg::_functor4d_streamline2d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.0f,_height - 1.0f,0.0f); + } + } + if (is_oriented_only) { + typename CImg::_functor4d_streamline3d_oriented func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,true, + 0,0,0,_width - 1.0f,_height - 1.0f,_depth - 1.0f); + } + typename CImg::_functor4d_streamline3d_directed func(*this); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,false, + 0,0,0,_width - 1.0f,_height - 1.0f,_depth - 1.0f); + } + + //! Return stream line of a 3d vector field. + /** + \param func Vector field function. + \param x X-coordinate of the starting point of the streamline. + \param y Y-coordinate of the starting point of the streamline. + \param z Z-coordinate of the starting point of the streamline. + \param L Streamline length. + \param dl Streamline length increment. + \param interpolation_type Type of interpolation. + Can be { 0=nearest int | 1=linear | 2=2nd-order RK | 3=4th-order RK. }. + \param is_backward_tracking Tells if the streamline is estimated forward or backward. + \param is_oriented_only Tells if the direction of the vectors must be ignored. + \param x0 X-coordinate of the first bounding-box vertex. + \param y0 Y-coordinate of the first bounding-box vertex. + \param z0 Z-coordinate of the first bounding-box vertex. + \param x1 X-coordinate of the second bounding-box vertex. + \param y1 Y-coordinate of the second bounding-box vertex. + \param z1 Z-coordinate of the second bounding-box vertex. + **/ + template + static CImg streamline(const tfunc& func, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=false, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + if (dl<=0) + throw CImgArgumentException("CImg<%s>::streamline(): Invalid specified integration length %g " + "(should be >0).", + pixel_type(), + dl); + + const bool is_bounded = (x0!=x1 || y0!=y1 || z0!=z1); + if (L<=0 || (is_bounded && (xx1 || yy1 || zz1))) return CImg(); + const unsigned int size_L = (unsigned int)cimg::round(L/dl + 1); + CImg coordinates(size_L,3); + const float dl2 = dl/2; + float + *ptr_x = coordinates.data(0,0), + *ptr_y = coordinates.data(0,1), + *ptr_z = coordinates.data(0,2), + pu = (float)(dl*func(x,y,z,0)), + pv = (float)(dl*func(x,y,z,1)), + pw = (float)(dl*func(x,y,z,2)), + X = x, Y = y, Z = z; + + switch (interpolation_type) { + case 0 : { // Nearest integer interpolation. + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + const int + xi = (int)(X>0?X + 0.5f:X - 0.5f), + yi = (int)(Y>0?Y + 0.5f:Y - 0.5f), + zi = (int)(Z>0?Z + 0.5f:Z - 0.5f); + float + u = (float)(dl*func((float)xi,(float)yi,(float)zi,0)), + v = (float)(dl*func((float)xi,(float)yi,(float)zi,1)), + w = (float)(dl*func((float)xi,(float)yi,(float)zi,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 1 : { // First-order interpolation. + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u = (float)(dl*func(X,Y,Z,0)), + v = (float)(dl*func(X,Y,Z,1)), + w = (float)(dl*func(X,Y,Z,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + case 2 : { // Second order interpolation. + cimg_forX(coordinates,l) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u = (float)(dl*func(X + u0,Y + v0,Z + w0,0)), + v = (float)(dl*func(X + u0,Y + v0,Z + w0,1)), + w = (float)(dl*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u*pu + v*pv + w*pw<0) { u = -u; v = -v; w = -w; } + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } break; + default : { // Fourth order interpolation. + cimg_forX(coordinates,x) { + *(ptr_x++) = X; *(ptr_y++) = Y; *(ptr_z++) = Z; + float + u0 = (float)(dl2*func(X,Y,Z,0)), + v0 = (float)(dl2*func(X,Y,Z,1)), + w0 = (float)(dl2*func(X,Y,Z,2)); + if (is_oriented_only && u0*pu + v0*pv + w0*pw<0) { u0 = -u0; v0 = -v0; w0 = -w0; } + float + u1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,0)), + v1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,1)), + w1 = (float)(dl2*func(X + u0,Y + v0,Z + w0,2)); + if (is_oriented_only && u1*pu + v1*pv + w1*pw<0) { u1 = -u1; v1 = -v1; w1 = -w1; } + float + u2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,0)), + v2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,1)), + w2 = (float)(dl2*func(X + u1,Y + v1,Z + w1,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u2 = -u2; v2 = -v2; w2 = -w2; } + float + u3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,0)), + v3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,1)), + w3 = (float)(dl2*func(X + u2,Y + v2,Z + w2,2)); + if (is_oriented_only && u2*pu + v2*pv + w2*pw<0) { u3 = -u3; v3 = -v3; w3 = -w3; } + const float + u = (u0 + u3)/3 + (u1 + u2)/1.5f, + v = (v0 + v3)/3 + (v1 + v2)/1.5f, + w = (w0 + w3)/3 + (w1 + w2)/1.5f; + if (is_backward_tracking) { X-=(pu=u); Y-=(pv=v); Z-=(pw=w); } else { X+=(pu=u); Y+=(pv=v); Z+=(pw=w); } + if (is_bounded && (Xx1 || Yy1 || Zz1)) break; + } + } + } + if (ptr_x!=coordinates.data(0,1)) coordinates.resize((int)(ptr_x-coordinates.data()),3,1,1,0); + return coordinates; + } + + //! Return stream line of a 3d vector field \overloading. + static CImg streamline(const char *const expression, + const float x, const float y, const float z, + const float L=256, const float dl=0.1f, + const unsigned int interpolation_type=2, const bool is_backward_tracking=true, + const bool is_oriented_only=false, + const float x0=0, const float y0=0, const float z0=0, + const float x1=0, const float y1=0, const float z1=0) { + _functor4d_streamline_expr func(expression); + return streamline(func,x,y,z,L,dl,interpolation_type,is_backward_tracking,is_oriented_only,x0,y0,z0,x1,y1,z1); + } + + struct _functor4d_streamline2d_directed { + const CImg& ref; + _functor4d_streamline2d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return c<2?(float)ref._linear_atXY(x,y,(int)z,c):0; + } + }; + + struct _functor4d_streamline3d_directed { + const CImg& ref; + _functor4d_streamline3d_directed(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref._linear_atXYZ(x,y,z,c); + } + }; + + struct _functor4d_streamline2d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline2d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,1,2); } + ~_functor4d_streamline2d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign2d(i,j) \ + if (I(i,j,0)*I(0,0,0) + I(i,j,1)*I(0,0,1)<0) { I(i,j,0) = -I(i,j,0); I(i,j,1) = -I(i,j,1); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z; + const float + dx = x - xi, + dy = y - yi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + I(0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,1) = (float)ref(xi,yi,zi,1); + I(1,0,0) = (float)ref(nxi,yi,zi,0); I(1,0,1) = (float)ref(nxi,yi,zi,1); + I(1,1,0) = (float)ref(nxi,nyi,zi,0); I(1,1,1) = (float)ref(nxi,nyi,zi,1); + I(0,1,0) = (float)ref(xi,nyi,zi,0); I(0,1,1) = (float)ref(xi,nyi,zi,1); + _cimg_vecalign2d(1,0); _cimg_vecalign2d(1,1); _cimg_vecalign2d(0,1); + } + return c<2?(float)pI->_linear_atXY(dx,dy,0,c):0; + } + }; + + struct _functor4d_streamline3d_oriented { + const CImg& ref; + CImg *pI; + _functor4d_streamline3d_oriented(const CImg& pref):ref(pref),pI(0) { pI = new CImg(2,2,2,3); } + ~_functor4d_streamline3d_oriented() { delete pI; } + float operator()(const float x, const float y, const float z, const unsigned int c) const { +#define _cimg_vecalign3d(i,j,k) if (I(i,j,k,0)*I(0,0,0,0) + I(i,j,k,1)*I(0,0,0,1) + I(i,j,k,2)*I(0,0,0,2)<0) { \ + I(i,j,k,0) = -I(i,j,k,0); I(i,j,k,1) = -I(i,j,k,1); I(i,j,k,2) = -I(i,j,k,2); } + int + xi = (int)x - (x>=0?0:1), nxi = xi + 1, + yi = (int)y - (y>=0?0:1), nyi = yi + 1, + zi = (int)z - (z>=0?0:1), nzi = zi + 1; + const float + dx = x - xi, + dy = y - yi, + dz = z - zi; + if (c==0) { + CImg& I = *pI; + if (xi<0) xi = 0; + if (nxi<0) nxi = 0; + if (xi>=ref.width()) xi = ref.width() - 1; + if (nxi>=ref.width()) nxi = ref.width() - 1; + if (yi<0) yi = 0; + if (nyi<0) nyi = 0; + if (yi>=ref.height()) yi = ref.height() - 1; + if (nyi>=ref.height()) nyi = ref.height() - 1; + if (zi<0) zi = 0; + if (nzi<0) nzi = 0; + if (zi>=ref.depth()) zi = ref.depth() - 1; + if (nzi>=ref.depth()) nzi = ref.depth() - 1; + I(0,0,0,0) = (float)ref(xi,yi,zi,0); I(0,0,0,1) = (float)ref(xi,yi,zi,1); + I(0,0,0,2) = (float)ref(xi,yi,zi,2); I(1,0,0,0) = (float)ref(nxi,yi,zi,0); + I(1,0,0,1) = (float)ref(nxi,yi,zi,1); I(1,0,0,2) = (float)ref(nxi,yi,zi,2); + I(1,1,0,0) = (float)ref(nxi,nyi,zi,0); I(1,1,0,1) = (float)ref(nxi,nyi,zi,1); + I(1,1,0,2) = (float)ref(nxi,nyi,zi,2); I(0,1,0,0) = (float)ref(xi,nyi,zi,0); + I(0,1,0,1) = (float)ref(xi,nyi,zi,1); I(0,1,0,2) = (float)ref(xi,nyi,zi,2); + I(0,0,1,0) = (float)ref(xi,yi,nzi,0); I(0,0,1,1) = (float)ref(xi,yi,nzi,1); + I(0,0,1,2) = (float)ref(xi,yi,nzi,2); I(1,0,1,0) = (float)ref(nxi,yi,nzi,0); + I(1,0,1,1) = (float)ref(nxi,yi,nzi,1); I(1,0,1,2) = (float)ref(nxi,yi,nzi,2); + I(1,1,1,0) = (float)ref(nxi,nyi,nzi,0); I(1,1,1,1) = (float)ref(nxi,nyi,nzi,1); + I(1,1,1,2) = (float)ref(nxi,nyi,nzi,2); I(0,1,1,0) = (float)ref(xi,nyi,nzi,0); + I(0,1,1,1) = (float)ref(xi,nyi,nzi,1); I(0,1,1,2) = (float)ref(xi,nyi,nzi,2); + _cimg_vecalign3d(1,0,0); _cimg_vecalign3d(1,1,0); _cimg_vecalign3d(0,1,0); + _cimg_vecalign3d(0,0,1); _cimg_vecalign3d(1,0,1); _cimg_vecalign3d(1,1,1); _cimg_vecalign3d(0,1,1); + } + return (float)pI->_linear_atXYZ(dx,dy,dz,c); + } + }; + + struct _functor4d_streamline_expr { + _cimg_math_parser *mp; + ~_functor4d_streamline_expr() { delete mp; } + _functor4d_streamline_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,"streamline",CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)(*mp)(x,y,z,c); + } + }; + + //! Return a shared-memory image referencing a range of pixels of the image instance. + /** + \param x0 X-coordinate of the starting pixel. + \param x1 X-coordinate of the ending pixel. + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) { + const unsigned int + beg = (unsigned int)offset(x0,y0,z0,c0), + end = (unsigned int)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of pixels of the image instance \const. + const CImg get_shared_points(const unsigned int x0, const unsigned int x1, + const unsigned int y0=0, const unsigned int z0=0, const unsigned int c0=0) const { + const unsigned int + beg = (unsigned int)offset(x0,y0,z0,c0), + end = (unsigned int)offset(x1,y0,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_points(): Invalid request of a shared-memory subset (%u->%u,%u,%u,%u).", + cimg_instance, + x0,x1,y0,z0,c0); + + return CImg(_data + beg,x1 - x0 + 1,1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance. + /** + \param y0 Y-coordinate of the starting row. + \param y1 Y-coordinate of the ending row. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) { + const unsigned int + beg = (unsigned int)offset(0,y0,z0,c0), + end = (unsigned int)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing a range of rows of the image instance \const. + const CImg get_shared_rows(const unsigned int y0, const unsigned int y1, + const unsigned int z0=0, const unsigned int c0=0) const { + const unsigned int + beg = (unsigned int)offset(0,y0,z0,c0), + end = (unsigned int)offset(0,y1,z0,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_rows(): Invalid request of a shared-memory subset " + "(0->%u,%u->%u,%u,%u).", + cimg_instance, + _width - 1,y0,y1,z0,c0); + + return CImg(_data + beg,_width,y1 - y0 + 1,1,1,true); + } + + //! Return a shared-memory image referencing one row of the image instance. + /** + \param y0 Y-coordinate. + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared-memory image referencing one row of the image instance \const. + const CImg get_shared_row(const unsigned int y0, const unsigned int z0=0, const unsigned int c0=0) const { + return get_shared_rows(y0,y0,z0,c0); + } + + //! Return a shared memory image referencing a range of slices of the image instance. + /** + \param z0 Z-coordinate of the starting slice. + \param z1 Z-coordinate of the ending slice. + \param c0 C-coordinate. + **/ + CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) { + const unsigned int + beg = (unsigned int)offset(0,0,z0,c0), + end = (unsigned int)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared memory image referencing a range of slices of the image instance \const. + const CImg get_shared_slices(const unsigned int z0, const unsigned int z1, const unsigned int c0=0) const { + const unsigned int + beg = (unsigned int)offset(0,0,z0,c0), + end = (unsigned int)offset(0,0,z1,c0); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_slices(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,%u->%u,%u).", + cimg_instance, + _width - 1,_height - 1,z0,z1,c0); + + return CImg(_data + beg,_width,_height,z1 - z0 + 1,1,true); + } + + //! Return a shared-memory image referencing one slice of the image instance. + /** + \param z0 Z-coordinate. + \param c0 C-coordinate. + **/ + CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing one slice of the image instance \const. + const CImg get_shared_slice(const unsigned int z0, const unsigned int c0=0) const { + return get_shared_slices(z0,z0,c0); + } + + //! Return a shared-memory image referencing a range of channels of the image instance. + /** + \param c0 C-coordinate of the starting channel. + \param c1 C-coordinate of the ending channel. + **/ + CImg get_shared_channels(const unsigned int c0, const unsigned int c1) { + const unsigned int + beg = (unsigned int)offset(0,0,0,c0), + end = (unsigned int)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing a range of channels of the image instance \const. + const CImg get_shared_channels(const unsigned int c0, const unsigned int c1) const { + const unsigned int + beg = (unsigned int)offset(0,0,0,c0), + end = (unsigned int)offset(0,0,0,c1); + if (beg>end || beg>=size() || end>=size()) + throw CImgArgumentException(_cimg_instance + "get_shared_channels(): Invalid request of a shared-memory subset " + "(0->%u,0->%u,0->%u,%u->%u).", + cimg_instance, + _width - 1,_height - 1,_depth - 1,c0,c1); + + return CImg(_data + beg,_width,_height,_depth,c1 - c0 + 1,true); + } + + //! Return a shared-memory image referencing one channel of the image instance. + /** + \param c0 C-coordinate. + **/ + CImg get_shared_channel(const unsigned int c0) { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory image referencing one channel of the image instance \const. + const CImg get_shared_channel(const unsigned int c0) const { + return get_shared_channels(c0,c0); + } + + //! Return a shared-memory version of the image instance. + CImg get_shared() { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Return a shared-memory version of the image instance \const. + const CImg get_shared() const { + return CImg(_data,_width,_height,_depth,_spectrum,true); + } + + //! Split image into a list along specified axis. + /** + \param axis Splitting axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param nb Number of splitted parts. + \note + - If \c nb==0, instance image is splitted into blocs of egal values along the specified axis. + - If \c nb<=0, instance image is splitted into blocs of -\c nb pixel wide. + - If \c nb>0, instance image is splitted into \c nb blocs. + **/ + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + if (is_empty()) return res; + const char _axis = cimg::lowercase(axis); + + if (nb<0) { // Split by bloc size. + const unsigned int dp = (unsigned int)(nb?-nb:1); + switch (_axis) { + case 'x': { + if (_width>dp) { + res.assign(_width/dp + (_width%dp?1:0),1,1); + const unsigned int pe = _width - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=128 && _height*_depth*_spectrum>=128)) + for (unsigned int p = 0; pdp) { + res.assign(_height/dp + (_height%dp?1:0),1,1); + const unsigned int pe = _height - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=128 && _width*_depth*_spectrum>=128)) + for (unsigned int p = 0; pdp) { + res.assign(_depth/dp + (_depth%dp?1:0),1,1); + const unsigned int pe = _depth - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=128 && _width*_height*_spectrum>=128)) + for (unsigned int p = 0; pdp) { + res.assign(_spectrum/dp + (_spectrum%dp?1:0),1,1); + const unsigned int pe = _spectrum - dp; + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=128 && _width*_height*_depth>=128)) + for (unsigned int p = 0; p0) { // Split by number of (non-homogeneous) blocs. + const unsigned int siz = _axis=='x'?_width:_axis=='y'?_height:_axis=='z'?_depth:_axis=='c'?_spectrum:0; + if ((unsigned int)nb>siz) + throw CImgArgumentException(_cimg_instance + "get_split(): Instance cannot be split along %c-axis into %u blocs.", + cimg_instance, + axis,nb); + if (nb==1) res.assign(*this); + else { + int err = (int)siz; + unsigned int _p = 0; + switch (_axis) { + case 'x' : { + cimg_forX(*this,p) if ((err-=nb)<=0) { + get_crop(_p,0,0,0,p,_height - 1,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'y' : { + cimg_forY(*this,p) if ((err-=nb)<=0) { + get_crop(0,_p,0,0,_width - 1,p,_depth - 1,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'z' : { + cimg_forZ(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,_p,0,_width - 1,_height - 1,p,_spectrum - 1).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } break; + case 'c' : { + cimg_forC(*this,p) if ((err-=nb)<=0) { + get_crop(0,0,0,_p,_width - 1,_height - 1,_depth - 1,p).move_to(res); + err+=(int)siz; + _p = p + 1U; + } + } + } + } + } else { // Split by egal values according to specified axis. + T current = *_data; + switch (_axis) { + case 'x' : { + int i0 = 0; + cimg_forX(*this,i) + if ((*this)(i)!=current) { get_columns(i0,i - 1).move_to(res); i0 = i; current = (*this)(i); } + get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + int i0 = 0; + cimg_forY(*this,i) + if ((*this)(0,i)!=current) { get_rows(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,i); } + get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + int i0 = 0; + cimg_forZ(*this,i) + if ((*this)(0,0,i)!=current) { get_slices(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,i); } + get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + int i0 = 0; + cimg_forC(*this,i) + if ((*this)(0,0,0,i)!=current) { get_channels(i0,i - 1).move_to(res); i0 = i; current = (*this)(0,0,0,i); } + get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + longT i0 = 0; + cimg_foroff(*this,i) + if ((*this)[i]!=current) { + CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); + i0 = (longT)i; current = (*this)[i]; + } + CImg(_data + i0,1,(unsigned int)(size() - i0)).move_to(res); + } + } + } + return res; + } + + //! Split image into a list of sub-images, according to a specified splitting value sequence and optionnally axis. + /** + \param values Splitting value sequence. + \param axis Axis along which the splitting is performed. Can be '0' to ignore axis. + \param keep_values Tells if the splitting sequence must be kept in the splitted blocs. + **/ + template + CImgList get_split(const CImg& values, const char axis=0, const bool keep_values=true) const { + CImgList res; + if (is_empty()) return res; + const ulongT vsiz = values.size(); + const char _axis = cimg::lowercase(axis); + if (!vsiz) return CImgList(*this); + if (vsiz==1) { // Split according to a single value. + const T value = (T)*values; + switch (_axis) { + case 'x' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_width && (*this)(i)==value) ++i; + if (i>i0) { if (keep_values) get_columns(i0,i - 1).move_to(res); i0 = i; } + while (i<_width && (*this)(i)!=value) ++i; + if (i>i0) { get_columns(i0,i - 1).move_to(res); i0 = i; } + } while (i<_width); + } break; + case 'y' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_height && (*this)(0,i)==value) ++i; + if (i>i0) { if (keep_values) get_rows(i0,i - 1).move_to(res); i0 = i; } + while (i<_height && (*this)(0,i)!=value) ++i; + if (i>i0) { get_rows(i0,i - 1).move_to(res); i0 = i; } + } while (i<_height); + } break; + case 'z' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_depth && (*this)(0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_slices(i0,i - 1).move_to(res); i0 = i; } + while (i<_depth && (*this)(0,0,i)!=value) ++i; + if (i>i0) { get_slices(i0,i - 1).move_to(res); i0 = i; } + } while (i<_depth); + } break; + case 'c' : { + unsigned int i0 = 0, i = 0; + do { + while (i<_spectrum && (*this)(0,0,0,i)==value) ++i; + if (i>i0) { if (keep_values) get_channels(i0,i - 1).move_to(res); i0 = i; } + while (i<_spectrum && (*this)(0,0,0,i)!=value) ++i; + if (i>i0) { get_channels(i0,i - 1).move_to(res); i0 = i; } + } while (i<_spectrum); + } break; + default : { + const ulongT siz = size(); + ulongT i0 = 0, i = 0; + do { + while (ii0) { if (keep_values) CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; } + while (ii0) { CImg(_data + i0,1,(unsigned int)(i - i0)).move_to(res); i0 = i; } + } while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_columns(i0,i1 - 1).move_to(res); + if (keep_values) get_columns(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_width); + if (i0<_width) get_columns(i0,width() - 1).move_to(res); + } break; + case 'y' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((*this)(0,i)==*values) { + i1 = i; j = 0; + while (i<_height && (*this)(0,i)==values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_rows(i0,i1 - 1).move_to(res); + if (keep_values) get_rows(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_height); + if (i0<_height) get_rows(i0,height() - 1).move_to(res); + } break; + case 'z' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((*this)(0,0,i)==*values) { + i1 = i; j = 0; + while (i<_depth && (*this)(0,0,i)==values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_slices(i0,i1 - 1).move_to(res); + if (keep_values) get_slices(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_depth); + if (i0<_depth) get_slices(i0,depth() - 1).move_to(res); + } break; + case 'c' : { + unsigned int i0 = 0, i1 = 0, i = 0; + do { + if ((*this)(0,0,0,i)==*values) { + i1 = i; j = 0; + while (i<_spectrum && (*this)(0,0,0,i)==values[j]) { ++i; if (++j>=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) get_channels(i0,i1 - 1).move_to(res); + if (keep_values) get_channels(i1,i - 1).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i<_spectrum); + if (i0<_spectrum) get_channels(i0,spectrum() - 1).move_to(res); + } break; + default : { + ulongT i0 = 0, i1 = 0, i = 0; + const ulongT siz = size(); + do { + if ((*this)[i]==*values) { + i1 = i; j = 0; + while (i=vsiz) j = 0; } + i-=j; + if (i>i1) { + if (i1>i0) CImg(_data + i0,1,(unsigned int)(i1 - i0)).move_to(res); + if (keep_values) CImg(_data + i1,1,(unsigned int)(i - i1)).move_to(res); + i0 = i; + } else ++i; + } else ++i; + } while (i(_data + i0,1,(unsigned int)(siz - i0)).move_to(res); + } break; + } + } + return res; + } + + //! Append two images along specified axis. + /** + \param img Image to append with instance image. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Append alignment in \c [0,1]. + **/ + template + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,true).insert(img).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \specialization. + CImg& append(const CImg& img, const char axis='x', const float align=0) { + if (is_empty()) return assign(img,false); + if (!img) return *this; + return CImgList(*this,img,true).get_append(axis,align).move_to(*this); + } + + //! Append two images along specified axis \const. + template + CImg<_cimg_Tt> get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList<_cimg_Tt>(*this,true).insert(img).get_append(axis,align); + } + + //! Append two images along specified axis \specialization. + CImg get_append(const CImg& img, const char axis='x', const float align=0) const { + if (is_empty()) return +img; + if (!img) return +*this; + return CImgList(*this,img,true).get_append(axis,align); + } + + //@} + //--------------------------------------- + // + //! \name Filtering / Transforms + //@{ + //--------------------------------------- + + //! Correlate image by a kernel. + /** + \param kernel = the correlation kernel. + \param boundary_conditions = the border condition type (0=zero, 1=dirichlet) + \param is_normalized = enable local normalization. + \note + - The correlation of the image instance \p *this by the kernel \p kernel is defined to be: + res(x,y,z) = sum_{i,j,k} (*this)(x + i,y + j,z + k)*kernel(i,j,k). + **/ + template + CImg& correlate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false) { + if (is_empty() || !kernel) return *this; + return get_correlate(kernel,boundary_conditions,is_normalized).move_to(*this); + } + + template + CImg<_cimg_Ttfloat> get_correlate(const CImg& 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 + CImg<_cimg_Ttfloat> _correlate(const CImg& 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 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). + CImg _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 I; + switch (_kernel._depth) { + case 3 : { + I.assign(27); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg _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) { + const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + + I[ 3]*I[ 3] + I[ 4]*I[ 4] + I[ 5]*I[ 5] + + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] + + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + + I[18]*I[18] + I[19]*I[19] + I[20]*I[20] + + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + + I[24]*I[24] + I[25]*I[25] + I[26]*I[26]); + *(ptrd++) = (Ttfloat)(N?(I[ 0]*_K[ 0] + I[ 1]*_K[ 1] + I[ 2]*_K[ 2] + + I[ 3]*_K[ 3] + I[ 4]*_K[ 4] + I[ 5]*_K[ 5] + + I[ 6]*_K[ 6] + I[ 7]*_K[ 7] + I[ 8]*_K[ 8] + + I[ 9]*_K[ 9] + I[10]*_K[10] + I[11]*_K[11] + + I[12]*_K[12] + I[13]*_K[13] + I[14]*_K[14] + + I[15]*_K[15] + I[16]*_K[16] + I[17]*_K[17] + + I[18]*_K[18] + I[19]*_K[19] + I[20]*_K[20] + + I[21]*_K[21] + I[22]*_K[22] + I[23]*_K[23] + + I[24]*_K[24] + I[25]*_K[25] + I[26]*_K[26])/std::sqrt(N):0); + } + } else cimg_for3x3x3(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[ 0]*_K[ 0] + I[ 1]*_K[ 1] + I[ 2]*_K[ 2] + + I[ 3]*_K[ 3] + I[ 4]*_K[ 4] + I[ 5]*_K[ 5] + + I[ 6]*_K[ 6] + I[ 7]*_K[ 7] + I[ 8]*_K[ 8] + + I[ 9]*_K[ 9] + I[10]*_K[10] + I[11]*_K[11] + + I[12]*_K[12] + I[13]*_K[13] + I[14]*_K[14] + + I[15]*_K[15] + I[16]*_K[16] + I[17]*_K[17] + + I[18]*_K[18] + I[19]*_K[19] + I[20]*_K[20] + + I[21]*_K[21] + I[22]*_K[22] + I[23]*_K[23] + + I[24]*_K[24] + I[25]*_K[25] + I[26]*_K[26]); + } + } break; + case 2 : { + I.assign(8); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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) { + const Ttfloat N = M*(I[0]*I[0] + I[1]*I[1] + + I[2]*I[2] + I[3]*I[3] + + I[4]*I[4] + I[5]*I[5] + + I[6]*I[6] + I[7]*I[7]); + *(ptrd++) = (Ttfloat)(N?(I[0]*K[0] + I[1]*K[1] + + I[2]*K[2] + I[3]*K[3] + + I[4]*K[4] + I[5]*K[5] + + I[6]*K[6] + I[7]*K[7])/std::sqrt(N):0); + } + } else cimg_for2x2x2(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[0]*K[0] + I[1]*K[1] + + I[2]*K[2] + I[3]*K[3] + + I[4]*K[4] + I[5]*K[5] + + I[6]*K[6] + I[7]*K[7]); + } + } break; + default : + case 1 : + switch (_kernel._width) { + case 6 : { + I.assign(36); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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) { + const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + I[ 4]*I[ 4] + + I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + I[ 9]*I[ 9] + + I[10]*I[10] + I[11]*I[11] + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + I[18]*I[18] + I[19]*I[19] + + I[20]*I[20] + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + I[24]*I[24] + + I[25]*I[25] + I[26]*I[26] + I[27]*I[27] + I[28]*I[28] + I[29]*I[29] + + I[30]*I[30] + I[31]*I[31] + I[32]*I[32] + I[33]*I[33] + I[34]*I[34] + + I[35]*I[35]); + *(ptrd++) = (Ttfloat)(N?(I[ 0]*K[ 0] + I[ 1]*K[ 1] + I[ 2]*K[ 2] + I[ 3]*K[ 3] + + I[ 4]*K[ 4] + I[ 5]*K[ 5] + I[ 6]*K[ 6] + I[ 7]*K[ 7] + + I[ 8]*K[ 8] + I[ 9]*K[ 9] + I[10]*K[10] + I[11]*K[11] + + I[12]*K[12] + I[13]*K[13] + I[14]*K[14] + I[15]*K[15] + + I[16]*K[16] + I[17]*K[17] + I[18]*K[18] + I[19]*K[19] + + I[20]*K[20] + I[21]*K[21] + I[22]*K[22] + I[23]*K[23] + + I[24]*K[24] + I[25]*K[25] + I[26]*K[26] + I[27]*K[27] + + I[28]*K[28] + I[29]*K[29] + I[30]*K[30] + I[31]*K[31] + + I[32]*K[32] + I[33]*K[33] + I[34]*K[34] + I[35]*K[35])/ + std::sqrt(N):0); + } + } else cimg_forZ(_img,z) cimg_for6x6(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[ 0]*K[ 0] + I[ 1]*K[ 1] + I[ 2]*K[ 2] + I[ 3]*K[ 3] + + I[ 4]*K[ 4] + I[ 5]*K[ 5] + I[ 6]*K[ 6] + I[ 7]*K[ 7] + + I[ 8]*K[ 8] + I[ 9]*K[ 9] + I[10]*K[10] + I[11]*K[11] + + I[12]*K[12] + I[13]*K[13] + I[14]*K[14] + I[15]*K[15] + + I[16]*K[16] + I[17]*K[17] + I[18]*K[18] + I[19]*K[19] + + I[20]*K[20] + I[21]*K[21] + I[22]*K[22] + I[23]*K[23] + + I[24]*K[24] + I[25]*K[25] + I[26]*K[26] + I[27]*K[27] + + I[28]*K[28] + I[29]*K[29] + I[30]*K[30] + I[31]*K[31] + + I[32]*K[32] + I[33]*K[33] + I[34]*K[34] + I[35]*K[35]); + } + } break; + case 5 : { + I.assign(25); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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) { + const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + I[ 4]*I[ 4] + + I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] + I[ 8]*I[ 8] + I[ 9]*I[ 9] + + I[10]*I[10] + I[11]*I[11] + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + + I[15]*I[15] + I[16]*I[16] + I[17]*I[17] + I[18]*I[18] + I[19]*I[19] + + I[20]*I[20] + I[21]*I[21] + I[22]*I[22] + I[23]*I[23] + I[24]*I[24]); + *(ptrd++) = (Ttfloat)(N?(I[ 0]*K[ 0] + I[ 1]*K[ 1] + I[ 2]*K[ 2] + I[ 3]*K[ 3] + + I[ 4]*K[ 4] + I[ 5]*K[ 5] + I[ 6]*K[ 6] + I[ 7]*K[ 7] + + I[ 8]*K[ 8] + I[ 9]*K[ 9] + I[10]*K[10] + I[11]*K[11] + + I[12]*K[12] + I[13]*K[13] + I[14]*K[14] + I[15]*K[15] + + I[16]*K[16] + I[17]*K[17] + I[18]*K[18] + I[19]*K[19] + + I[20]*K[20] + I[21]*K[21] + I[22]*K[22] + I[23]*K[23] + + I[24]*K[24])/std::sqrt(N):0); + } + } else cimg_forZ(_img,z) cimg_for5x5(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[ 0]*K[ 0] + I[ 1]*K[ 1] + I[ 2]*K[ 2] + I[ 3]*K[ 3] + + I[ 4]*K[ 4] + I[ 5]*K[ 5] + I[ 6]*K[ 6] + I[ 7]*K[ 7] + + I[ 8]*K[ 8] + I[ 9]*K[ 9] + I[10]*K[10] + I[11]*K[11] + + I[12]*K[12] + I[13]*K[13] + I[14]*K[14] + I[15]*K[15] + + I[16]*K[16] + I[17]*K[17] + I[18]*K[18] + I[19]*K[19] + + I[20]*K[20] + I[21]*K[21] + I[22]*K[22] + I[23]*K[23] + + I[24]*K[24]); + } + } break; + case 4 : { + I.assign(16); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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) { + const Ttfloat N = M*(I[ 0]*I[ 0] + I[ 1]*I[ 1] + I[ 2]*I[ 2] + I[ 3]*I[ 3] + + I[ 4]*I[ 4] + I[ 5]*I[ 5] + I[ 6]*I[ 6] + I[ 7]*I[ 7] + + I[ 8]*I[ 8] + I[ 9]*I[ 9] + I[10]*I[10] + I[11]*I[11] + + I[12]*I[12] + I[13]*I[13] + I[14]*I[14] + I[15]*I[15]); + *(ptrd++) = (Ttfloat)(N?(I[ 0]*K[ 0] + I[ 1]*K[ 1] + I[ 2]*K[ 2] + I[ 3]*K[ 3] + + I[ 4]*K[ 4] + I[ 5]*K[ 5] + I[ 6]*K[ 6] + I[ 7]*K[ 7] + + I[ 8]*K[ 8] + I[ 9]*K[ 9] + I[10]*K[10] + I[11]*K[11] + + I[12]*K[12] + I[13]*K[13] + I[14]*K[14] + I[15]*K[15])/ + std::sqrt(N):0); + } + } else cimg_forZ(_img,z) cimg_for4x4(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[ 0]*K[ 0] + I[ 1]*K[ 1] + I[ 2]*K[ 2] + I[ 3]*K[ 3] + + I[ 4]*K[ 4] + I[ 5]*K[ 5] + I[ 6]*K[ 6] + I[ 7]*K[ 7] + + I[ 8]*K[ 8] + I[ 9]*K[ 9] + I[10]*K[10] + I[11]*K[11] + + I[12]*K[12] + I[13]*K[13] + I[14]*K[14] + I[15]*K[15]); + } + } break; + case 3 : { + I.assign(9); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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) { + const Ttfloat N = M*(I[0]*I[0] + I[1]*I[1] + I[2]*I[2] + + I[3]*I[3] + I[4]*I[4] + I[5]*I[5] + + I[6]*I[6] + I[7]*I[7] + I[8]*I[8]); + *(ptrd++) = (Ttfloat)(N?(I[0]*K[0] + I[1]*K[1] + I[2]*K[2] + + I[3]*K[3] + I[4]*K[4] + I[5]*K[5] + + I[6]*K[6] + I[7]*K[7] + I[8]*K[8])/std::sqrt(N):0); + } + } else cimg_forZ(_img,z) cimg_for3x3(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[0]*K[0] + I[1]*K[1] + I[2]*K[2] + + I[3]*K[3] + I[4]*K[4] + I[5]*K[5] + + I[6]*K[6] + I[7]*K[7] + I[8]*K[8]); + } + } break; + case 2 : { + I.assign(4); + cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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) { + const Ttfloat N = M*(I[0]*I[0] + I[1]*I[1] + + I[2]*I[2] + I[3]*I[3]); + *(ptrd++) = (Ttfloat)(N?(I[0]*K[0] + I[1]*K[1] + + I[2]*K[2] + I[3]*K[3])/std::sqrt(N):0); + } + } else cimg_forZ(_img,z) cimg_for2x2(_img,x,y,z,0,I,T) + *(ptrd++) = (Ttfloat)(I[0]*K[0] + I[1]*K[1] + + I[2]*K[2] + I[3]*K[3]); + } + } break; + case 1 : + if (is_normalized) res.fill(1); + else cimg_forC(res,c) { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg 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. + int + mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = 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; + cimg_forC(res,c) cimg_abort_try { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_normalized) { // Normalized correlation. + const Ttfloat _M = (Ttfloat)K.magnitude(2), M = _M*_M; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width*_height*_depth>=32768)) + for (int z = mz1; z=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Ttfloat val = 0, N = 0; + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const Ttfloat _val = (Ttfloat)_img._atXYZ(x + xm,y + ym,z + zm); + val+=_val*K(mx1 + xm,my1 + ym,mz1 + zm); + N+=_val*_val; + } + N*=M; + res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0); + } + } cimg_abort_catch2() + else + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Ttfloat val = 0, N = 0; + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) { + const Ttfloat _val = (Ttfloat)_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + val+=_val*K(mx1 + xm,my1 + ym,mz1 + zm); + N+=_val*_val; + } + N*=M; + res(x,y,z,c) = (Ttfloat)(N?val/std::sqrt(N):0); + } + } 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=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Ttfloat val = 0; + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + val+=_img._atXYZ(x + xm,y + ym,z + zm)*K(mx1 + xm,my1 + ym,mz1 + zm); + res(x,y,z,c) = (Ttfloat)val; + } + } cimg_abort_catch2() + else + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Ttfloat val = 0; + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + val+=_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0)*K(mx1 + xm,my1 + ym,mz1 + zm); + res(x,y,z,c) = (Ttfloat)val; + } + } cimg_abort_catch2() + } + } cimg_abort_catch() + } + cimg_abort_test(); + return res; + } + + //! Convolve image by a kernel. + /** + \param kernel = the correlation kernel. + \param boundary_conditions = the border condition type (0=zero, 1=dirichlet) + \param is_normalized = enable local normalization. + \note + - The result \p res of the convolution of an image \p img by a kernel \p kernel is defined to be: + res(x,y,z) = sum_{i,j,k} img(x-i,y-j,z-k)*kernel(i,j,k) + **/ + template + CImg& convolve(const CImg& kernel, const unsigned int boundary_conditions=1, const bool is_normalized=false) { + if (is_empty() || !kernel) return *this; + return get_convolve(kernel,boundary_conditions,is_normalized).move_to(*this); + } + + //! Convolve image by a kernel \newinstance. + template + CImg<_cimg_Ttfloat> get_convolve(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_normalized=false) const { + return _correlate(CImg(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. + **/ + CImg& cumulate(const char axis=0) { + switch (cimg::lowercase(axis)) { + case 'x' : + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=512 && _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { + T *ptrd = data(0,y,z,c); + Tlong cumul = (Tlong)0; + cimg_forX(*this,x) { cumul+=(Tlong)*ptrd; *(ptrd++) = (T)cumul; } + } + break; + case 'y' : { + const ulongT w = (ulongT)_width; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_height>=512 && _width*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { + T *ptrd = data(x,0,z,c); + Tlong cumul = (Tlong)0; + cimg_forY(*this,y) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=w; } + } + } break; + case 'z' : { + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_depth>=512 && _width*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { + T *ptrd = data(x,y,0,c); + Tlong cumul = (Tlong)0; + cimg_forZ(*this,z) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=wh; } + } + } break; + case 'c' : { + const ulongT whd = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_spectrum>=512 && _width*_height*_depth>=16)) + cimg_forXYZ(*this,x,y,z) { + T *ptrd = data(x,y,z,0); + Tlong cumul = (Tlong)0; + cimg_forC(*this,c) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; ptrd+=whd; } + } + } break; + default : { // Global cumulation. + Tlong cumul = (Tlong)0; + cimg_for(*this,ptrd,T) { cumul+=(Tlong)*ptrd; *ptrd = (T)cumul; } + } + } + return *this; + } + + //! Cumulate image values, optionally along specified axis \newinstance. + CImg get_cumulate(const char axis=0) const { + return CImg(*this,false).cumulate(axis); + } + + //! Cumulate image values, along specified axes. + /** + \param axes Cumulation axes, as a C-string. + \note \c axes may contains multiple characters, e.g. \c "xyz" + **/ + CImg& cumulate(const char *const axes) { + for (const char *s = axes; *s; ++s) cumulate(*s); + return *this; + } + + //! Cumulate image values, along specified axes \newintance. + CImg get_cumulate(const char *const axes) const { + return CImg(*this,false).cumulate(axes); + } + + //! Erode image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the erosion in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& erode(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_erode(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Erode image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_erode(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_real=false) const { + if (is_empty() || !kernel) return *this; + if (!is_real && kernel==0) return CImg(width(),height(),depth(),spectrum(),0); + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,std::max(_spectrum,kernel._spectrum)); + const int + mx2 = kernel.width()/2, my2 = kernel.height()/2, mz2 = 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; + cimg_forC(*this,c) cimg_abort_try { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real erosion + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width*_height*_depth>=32768)) + for (int z = mz1; z::max(); + 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(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(_img(x + xm,y + ym,z + zm) - mval); + if (cval=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + 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(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(_img._atXYZ(x + xm,y + ym,z + zm) - mval); + if (cval=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + 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(mx1 + xm,my1 + ym,mz1 + zm); + const Tt cval = (Tt)(_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) - mval); + if (cval=32768)) + for (int z = mz1; z::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const Tt cval = (Tt)_img(x + xm,y + ym,z + zm); + if (cval=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + if (K(mx1 + xm,my1 + ym,mz1 + zm)) { + const T cval = (Tt)_img._atXYZ(x + xm,y + ym,z + zm); + if (cval=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt min_val = cimg::type::max(); + for (int zm = -mz1; zm<=mz2; ++zm) + for (int ym = -my1; ym<=my2; ++ym) + for (int xm = -mx1; xm<=mx2; ++xm) + 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& 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, _s2 = s/2 + 1, _s1 = s - _s2, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = buf._data, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; }} + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _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, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::min(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val1 && _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, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val<=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::min(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val get_erode(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).erode(sx,sy,sz); + } + + //! Erode the image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& erode(const unsigned int s) { + return erode(s,s,s); + } + + //! Erode the image by a square structuring element of specified size \newinstance. + CImg get_erode(const unsigned int s) const { + return (+*this).erode(s); + } + + //! Dilate image by a structuring element. + /** + \param kernel Structuring element. + \param boundary_conditions Boundary conditions. + \param is_real Do the dilation in real (a.k.a 'non-flat') mode (\c true) rather than binary mode (\c false). + **/ + template + CImg& dilate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_real=false) { + if (is_empty() || !kernel) return *this; + return get_dilate(kernel,boundary_conditions,is_real).move_to(*this); + } + + //! Dilate image by a structuring element \newinstance. + template + CImg<_cimg_Tt> get_dilate(const CImg& kernel, const unsigned int boundary_conditions=1, + const bool is_real=false) const { + if (is_empty() || !kernel || (!is_real && kernel==0)) return *this; + typedef _cimg_Tt Tt; + CImg res(_width,_height,_depth,_spectrum); + const int + 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; + cimg_forC(*this,c) cimg_abort_try { + cimg_abort_test(); + const CImg _img = get_shared_channel(c%_spectrum); + const CImg K = kernel.get_shared_channel(c%kernel._spectrum); + if (is_real) { // Real dilation + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width*_height*_depth>=32768)) + for (int z = mz1; z::min(); + 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 Tt cval = (Tt)(_img(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } cimg_abort_catch2() + if (boundary_conditions) + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + 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 Tt cval = (Tt)(_img._atXYZ(x + xm,y + ym,z + zm) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } cimg_abort_catch2() + else + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + cimg_forYZ(*this,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + 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 Tt cval = (Tt)(_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0) + mval); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } cimg_abort_catch2() + } else { // Binary dilation + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + for (int z = mz1; z::min(); + 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)) { + const Tt cval = (Tt)_img(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } cimg_abort_catch2() + if (boundary_conditions) + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + 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)) { + const T cval = (Tt)_img._atXYZ(x + xm,y + ym,z + zm); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } cimg_abort_catch2() + else + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=128)) + cimg_forYZ(res,y,z) cimg_abort_try2 { + cimg_abort_test2(); + for (int x = 0; x=mye || z=mze)?++x:((x=mxe)?++x:(x=mxe))) { + Tt max_val = cimg::type::min(); + 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)) { + const T cval = (Tt)_img.atXYZ(x + xm,y + ym,z + zm,0,(T)0); + if (cval>max_val) max_val = cval; + } + res(x,y,z,c) = max_val; + } + } cimg_abort_catch2() + } + } cimg_abort_catch() + cimg_abort_test(); + return res; + } + + //! Dilate image by a rectangular structuring element of specified size. + /** + \param sx Width of the structuring element. + \param sy Height of the structuring element. + \param sz Depth of the structuring element. + **/ + CImg& 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, _s1 = s/2, _s2 = s - _s1, s1 = _s1>L?L:_s1, s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forYZC(*this,y,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(0,y,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(0,y,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(0,y,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + 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, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXZC(*this,x,z,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,0,z,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,0,z,c); cur = std::max(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,0,z,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + + 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, + s2 = _s2>L?L:_s2; + CImg buf(L); + cimg_pragma_openmp(parallel for collapse(3) firstprivate(buf) if (size()>524288)) + cimg_forXYC(*this,x,y,c) { + T *const ptrdb = buf._data, *ptrd = ptrdb, *const ptrde = buf._data + L - 1; + const T *const ptrsb = data(x,y,0,c), *ptrs = ptrsb, *const ptrse = ptrs + L*off - off; + T cur = *ptrs; ptrs+=off; bool is_first = true; + for (int p = s2 - 1; p>0 && ptrs<=ptrse; --p) { + const T val = *ptrs; ptrs+=off; if (val>=cur) { cur = val; is_first = false; } + } + *(ptrd++) = cur; + if (ptrs>=ptrse) { + T *pd = data(x,y,0,c); cur = std::max(cur,*ptrse); cimg_forX(buf,x) { *pd = cur; pd+=off; } + } else { + for (int p = s1; p>0 && ptrd<=ptrde; --p) { + const T val = *ptrs; if (ptrs=cur) { cur = val; is_first = false; } + *(ptrd++) = cur; + } + for (int p = L - s - 1; p>0; --p) { + const T val = *ptrs; ptrs+=off; + if (is_first) { + const T *nptrs = ptrs - off; cur = val; + for (int q = s - 2; q>0; --q) { nptrs-=off; const T nval = *nptrs; if (nval>cur) cur = nval; } + nptrs-=off; const T nval = *nptrs; if (nval>cur) { cur = nval; is_first = true; } else is_first = false; + } else { if (val>=cur) cur = val; else if (cur==*(ptrs-s*off)) is_first = true; } + *(ptrd++) = cur; + } + ptrd = ptrde; ptrs = ptrse; cur = *ptrs; ptrs-=off; + for (int p = s1; p>0 && ptrs>=ptrsb; --p) { + const T val = *ptrs; ptrs-=off; if (val>cur) cur = val; + } + *(ptrd--) = cur; + for (int p = s2 - 1; p>0 && ptrd>=ptrdb; --p) { + const T val = *ptrs; if (ptrs>ptrsb) ptrs-=off; if (val>cur) cur = val; *(ptrd--) = cur; + } + T *pd = data(x,y,0,c); cimg_for(buf,ps,T) { *pd = *ps; pd+=off; } + } + } + } + return *this; + } + + //! Dilate image by a rectangular structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int sx, const unsigned int sy, const unsigned int sz=1) const { + return (+*this).dilate(sx,sy,sz); + } + + //! Dilate image by a square structuring element of specified size. + /** + \param s Size of the structuring element. + **/ + CImg& dilate(const unsigned int s) { + return dilate(s,s,s); + } + + //! Dilate image by a square structuring element of specified size \newinstance. + CImg get_dilate(const unsigned int s) const { + return (+*this).dilate(s); + } + + //! Compute watershed transform. + /** + \param priority Priority map. + \param is_high_connectivity Boolean that choose between 4(false)- or 8(true)-connectivity + in 2d case, and between 6(false)- or 26(true)-connectivity in 3d case. + \note Non-zero values of the instance instance are propagated to zero-valued ones according to + specified the priority map. + **/ + template + CImg& watershed(const CImg& priority, const bool is_high_connectivity=false) { +#define _cimg_watershed_init(cond,X,Y,Z) \ + if (cond && !(*this)(X,Y,Z)) Q._priority_queue_insert(labels,sizeQ,priority(X,Y,Z),X,Y,Z,nb_seeds) + +#define _cimg_watershed_propagate(cond,X,Y,Z) \ + if (cond) { \ + if ((*this)(X,Y,Z)) { \ + ns = labels(X,Y,Z) - 1; xs = seeds(ns,0); ys = seeds(ns,1); zs = seeds(ns,2); \ + d = cimg::sqr((float)x - xs) + cimg::sqr((float)y - ys) + cimg::sqr((float)z - zs); \ + if (d labels(_width,_height,_depth,1,0), seeds(64,3); + CImg::type> Q; + unsigned int sizeQ = 0; + int px, nx, py, ny, pz, nz; + bool is_px, is_nx, is_py, is_ny, is_pz, is_nz; + const bool is_3d = _depth>1; + + // Find seed points and insert them in priority queue. + unsigned int nb_seeds = 0; + const T *ptrs = _data; + cimg_forXYZ(*this,x,y,z) if (*(ptrs++)) { // 3d version + if (nb_seeds>=seeds._width) seeds.resize(2*seeds._width,3,1,1,0); + seeds(nb_seeds,0) = x; seeds(nb_seeds,1) = y; seeds(nb_seeds++,2) = z; + px = x - 1; nx = x + 1; + py = y - 1; ny = y + 1; + pz = z - 1; nz = z + 1; + is_px = px>=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz=0; is_nx = nx=0; is_ny = ny=0; is_nz = nz::inf(); + T label = (T)0; + _cimg_watershed_propagate(is_px,px,y,z); + _cimg_watershed_propagate(is_nx,nx,y,z); + _cimg_watershed_propagate(is_py,x,py,z); + _cimg_watershed_propagate(is_ny,x,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_pz,x,y,pz); + _cimg_watershed_propagate(is_nz,x,y,nz); + } + if (is_high_connectivity) { + _cimg_watershed_propagate(is_px && is_py,px,py,z); + _cimg_watershed_propagate(is_nx && is_py,nx,py,z); + _cimg_watershed_propagate(is_px && is_ny,px,ny,z); + _cimg_watershed_propagate(is_nx && is_ny,nx,ny,z); + if (is_3d) { + _cimg_watershed_propagate(is_px && is_pz,px,y,pz); + _cimg_watershed_propagate(is_nx && is_pz,nx,y,pz); + _cimg_watershed_propagate(is_px && is_nz,px,y,nz); + _cimg_watershed_propagate(is_nx && is_nz,nx,y,nz); + _cimg_watershed_propagate(is_py && is_pz,x,py,pz); + _cimg_watershed_propagate(is_ny && is_pz,x,ny,pz); + _cimg_watershed_propagate(is_py && is_nz,x,py,nz); + _cimg_watershed_propagate(is_ny && is_nz,x,ny,nz); + _cimg_watershed_propagate(is_px && is_py && is_pz,px,py,pz); + _cimg_watershed_propagate(is_nx && is_py && is_pz,nx,py,pz); + _cimg_watershed_propagate(is_px && is_ny && is_pz,px,ny,pz); + _cimg_watershed_propagate(is_nx && is_ny && is_pz,nx,ny,pz); + _cimg_watershed_propagate(is_px && is_py && is_nz,px,py,nz); + _cimg_watershed_propagate(is_nx && is_py && is_nz,nx,py,nz); + _cimg_watershed_propagate(is_px && is_ny && is_nz,px,ny,nz); + _cimg_watershed_propagate(is_nx && is_ny && is_nz,nx,ny,nz); + } + } + (*this)(x,y,z) = label; + labels(x,y,z) = ++nmin; + } + return *this; + } + + //! Compute watershed transform \newinstance. + template + CImg get_watershed(const CImg& priority, const bool is_high_connectivity=false) const { + return (+*this).watershed(priority,is_high_connectivity); + } + + // [internal] Insert/Remove items in priority queue, for watershed/distance transforms. + template + bool _priority_queue_insert(CImg& is_queued, unsigned int& siz, const tv value, + const unsigned int x, const unsigned int y, const unsigned int z, + const unsigned int n=1) { + if (is_queued(x,y,z)) return false; + is_queued(x,y,z) = (tq)n; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; + (*this)(siz - 1,1) = (T)x; + (*this)(siz - 1,2) = (T)y; + (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); + cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); + cimg::swap((*this)(pos,3),(*this)(par,3)); + } + return true; + } + + CImg& _priority_queue_remove(unsigned int& siz) { + (*this)(0,0) = (*this)(--siz,0); + (*this)(0,1) = (*this)(siz,1); + (*this)(0,2) = (*this)(siz,2); + (*this)(0,3) = (*this)(siz,3); + const float value = (*this)(0,0); + for (unsigned int pos = 0, left = 0, right = 0; + ((right=2*(pos + 1),(left=right - 1))(*this)(right,0)) { + cimg::swap((*this)(pos,0),(*this)(left,0)); + cimg::swap((*this)(pos,1),(*this)(left,1)); + cimg::swap((*this)(pos,2),(*this)(left,2)); + cimg::swap((*this)(pos,3),(*this)(left,3)); + pos = left; + } else { + cimg::swap((*this)(pos,0),(*this)(right,0)); + cimg::swap((*this)(pos,1),(*this)(right,1)); + cimg::swap((*this)(pos,2),(*this)(right,2)); + cimg::swap((*this)(pos,3),(*this)(right,3)); + pos = right; + } + } else { + cimg::swap((*this)(pos,0),(*this)(left,0)); + cimg::swap((*this)(pos,1),(*this)(left,1)); + cimg::swap((*this)(pos,2),(*this)(left,2)); + cimg::swap((*this)(pos,3),(*this)(left,3)); + pos = left; + } + } + return *this; + } + + //! Apply recursive Deriche filter. + /** + \param sigma Standard deviation of the filter. + \param order Order of the filter. Can be { 0=smooth-filter | 1=1st-derivative | 2=2nd-derivative }. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + **/ + CImg& deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) { +#define _cimg_deriche_apply \ + CImg Y(N); \ + Tfloat *ptrY = Y._data, yb = 0, yp = 0; \ + T xp = (T)0; \ + if (boundary_conditions) { xp = *ptrX; yb = yp = (Tfloat)(coefp*xp); } \ + for (int m = 0; m=0; --n) { \ + const T xc = *(ptrX-=off); \ + const Tfloat yc = (Tfloat)(a2*xn + a3*xa - b1*yn - b2*ya); \ + xa = xn; xn = xc; ya = yn; yn = yc; \ + *ptrX = (T)(*(--ptrY)+yc); \ + } + const char naxis = cimg::lowercase(axis); + const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.1f && !order)) return *this; + const float + nnsigma = nsigma<0.1f?0.1f:nsigma, + alpha = 1.695f/nnsigma, + ema = (float)std::exp(-alpha), + ema2 = (float)std::exp(-2*alpha), + b1 = -2*ema, + b2 = ema2; + float a0 = 0, a1 = 0, a2 = 0, a3 = 0, coefp = 0, coefn = 0; + switch (order) { + case 0 : { + const float k = (1-ema)*(1-ema)/(1 + 2*alpha*ema-ema2); + a0 = k; + a1 = k*(alpha - 1)*ema; + a2 = k*(alpha + 1)*ema; + a3 = -k*ema2; + } break; + case 1 : { + const float k = -(1-ema)*(1-ema)*(1-ema)/(2*(ema + 1)*ema); + a0 = a3 = 0; + a1 = k*ema; + a2 = -a1; + } break; + case 2 : { + const float + ea = (float)std::exp(-alpha), + k = -(ema2 - 1)/(2*alpha*ema), + kn = (-2*(-1 + 3*ea - 3*ea*ea + ea*ea*ea)/(3*ea + 1 + 3*ea*ea + ea*ea*ea)); + a0 = kn; + a1 = -kn*(1 + k*alpha)*ema; + a2 = kn*(1 - k*alpha)*ema; + a3 = -kn*ema2; + } break; + default : + throw CImgArgumentException(_cimg_instance + "deriche(): Invalid specified filter order %u " + "(should be { 0=smoothing | 1=1st-derivative | 2=2nd-derivative }).", + cimg_instance, + order); + } + coefp = (a0 + a1)/(1 + b1 + b2); + coefn = (a2 + a3)/(1 + b1 + b2); + switch (naxis) { + case 'x' : { + const int N = width(); + const ulongT off = 1U; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) { T *ptrX = data(0,y,z,c); _cimg_deriche_apply; } + } break; + case 'y' : { + const int N = height(); + const ulongT off = (ulongT)_width; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) { T *ptrX = data(x,0,z,c); _cimg_deriche_apply; } + } break; + case 'z' : { + const int N = depth(); + const ulongT off = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) { T *ptrX = data(x,y,0,c); _cimg_deriche_apply; } + } break; + default : { + const int N = spectrum(); + const ulongT off = (ulongT)_width*_height*_depth; + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) { T *ptrX = data(x,y,z,0); _cimg_deriche_apply; } + } + } + return *this; + } + + //! Apply recursive Deriche filter \newinstance. + CImg get_deriche(const float sigma, const unsigned int order=0, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).deriche(sigma,order,axis,boundary_conditions); + } + + // [internal] Apply a recursive filter (used by CImg::vanvliet()). + /* + \param ptr the pointer of the data + \param filter the coefficient of the filter in the following order [n,n - 1,n - 2,n - 3]. + \param N size of the data + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivtive, 2nd derivative, 3rd derivative + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note Boundary condition using B. Triggs method (IEEE trans on Sig Proc 2005). + */ + static void _cimg_recursive_apply(T *data, const double filter[], const int N, const ulongT off, + const unsigned int order, const bool boundary_conditions) { + double val[4] = { 0 }; // res[n,n - 1,n - 2,n - 3,..] or res[n,n + 1,n + 2,n + 3,..] + const double + sumsq = filter[0], sum = sumsq * sumsq, + a1 = filter[1], a2 = filter[2], a3 = filter[3], + scaleM = 1.0 / ( (1.0 + a1 - a2 + a3) * (1.0 - a1 - a2 - a3) * (1.0 + a2 + (a1 - a3) * a3) ); + double M[9]; // Triggs matrix + M[0] = scaleM * (-a3 * a1 + 1.0 - a3 * a3 - a2); + M[1] = scaleM * (a3 + a1) * (a2 + a3 * a1); + M[2] = scaleM * a3 * (a1 + a3 * a2); + M[3] = scaleM * (a1 + a3 * a2); + M[4] = -scaleM * (a2 - 1.0) * (a2 + a3 * a1); + M[5] = -scaleM * a3 * (a3 * a1 + a3 * a3 + a2 - 1.0); + M[6] = scaleM * (a3 * a1 + a2 + a1 * a1 - a2 * a2); + M[7] = scaleM * (a1 * a2 + a3 * a2 * a2 - a1 * a3 * a3 - a3 * a3 * a3 - a3 * a2 + a3); + M[8] = scaleM * a3 * (a1 + a3 * a2); + switch (order) { + case 0 : { + const double iplus = (boundary_conditions?data[(N - 1)*off]:(T)0); + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 1; k<4; ++k) val[k] = (boundary_conditions?*data/sumsq:0); + } else { + /* apply Triggs border condition */ + const double + uplus = iplus/(1.0 - a1 - a2 - a3), vplus = uplus/(1.0 - a1 - a2 - a3), + unp = val[1] - uplus, unp1 = val[2] - uplus, unp2 = val[3] - uplus; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2 + vplus) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2 + vplus) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2 + vplus) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) val[k] = val[k - 1]; + } + if (!pass) data -= off; + } + } break; + case 1 : { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + /* apply Triggs border condition */ + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + } else { data-=off;} + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 2: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + /* apply Triggs border condition */ + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + case 3: { + double x[3]; // [front,center,back] + for (int pass = 0; pass<2; ++pass) { + if (!pass) { + for (int k = 0; k<3; ++k) x[k] = (boundary_conditions?*data:(T)0); + for (int k = 0; k<4; ++k) val[k] = 0; + } else { + /* apply Triggs border condition */ + const double + unp = val[1], unp1 = val[2], unp2 = val[3]; + val[0] = (M[0] * unp + M[1] * unp1 + M[2] * unp2) * sum; + val[1] = (M[3] * unp + M[4] * unp1 + M[5] * unp2) * sum; + val[2] = (M[6] * unp + M[7] * unp1 + M[8] * unp2) * sum; + *data = (T)val[0]; + data -= off; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + for (int n = pass; n0; --k) x[k] = x[k - 1]; + for (int k = 3; k>0; --k) val[k] = val[k - 1]; + } + *data = (T)0; + } + } break; + } + } + + //! Van Vliet recursive Gaussian filter. + /** + \param sigma standard deviation of the Gaussian filter + \param order the order of the filter 0,1,2,3 + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + \note dirichlet boundary condition has a strange behavior + + I.T. Young, L.J. van Vliet, M. van Ginkel, Recursive Gabor filtering. + IEEE Trans. Sig. Proc., vol. 50, pp. 2799-2805, 2002. + + (this is an improvement over Young-Van Vliet, Sig. Proc. 44, 1995) + + Boundary conditions (only for order 0) using Triggs matrix, from + B. Triggs and M. Sdika. Boundary conditions for Young-van Vliet + recursive filtering. IEEE Trans. Signal Processing, + vol. 54, pp. 2365-2367, 2006. + **/ + CImg& vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) { + if (is_empty()) return *this; + const char naxis = cimg::lowercase(axis); + const float nsigma = sigma>=0?sigma:-sigma*(naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + if (is_empty() || (nsigma<0.5f && !order)) return *this; + const double + nnsigma = nsigma<0.5f?0.5f:nsigma, + m0 = 1.16680, m1 = 1.10783, m2 = 1.40586, + m1sq = m1 * m1, m2sq = m2 * m2, + q = (nnsigma<3.556?-0.2568 + 0.5784*nnsigma + 0.0561*nnsigma*nnsigma:2.5091 + 0.9804*(nnsigma - 3.556)), + qsq = q * q, + scale = (m0 + q) * (m1sq + m2sq + 2 * m1 * q + qsq), + b1 = -q * (2 * m0 * m1 + m1sq + m2sq + (2 * m0 + 4 * m1) * q + 3 * qsq) / scale, + b2 = qsq * (m0 + 2 * m1 + 3 * q) / scale, + b3 = -qsq * q / scale, + B = ( m0 * (m1sq + m2sq) ) / scale; + double filter[4]; + filter[0] = B; filter[1] = -b1; filter[2] = -b2; filter[3] = -b3; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_recursive_apply(data(0,y,z,c),filter,_width,1U,order,boundary_conditions); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_recursive_apply(data(x,0,z,c),filter,_height,(ulongT)_width,order,boundary_conditions); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_recursive_apply(data(x,y,0,c),filter,_depth,(ulongT)_width*_height, + order,boundary_conditions); + } break; + default : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_recursive_apply(data(x,y,z,0),filter,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions); + } + } + return *this; + } + + //! Blur image using Van Vliet recursive Gaussian filter. \newinstance. + CImg get_vanvliet(const float sigma, const unsigned int order, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).vanvliet(sigma,order,axis,boundary_conditions); + } + + //! Blur image. + /** + \param sigma_x Standard deviation of the blur, along the X-axis. + \param sigma_y Standard deviation of the blur, along the Y-axis. + \param sigma_z Standard deviation of the blur, along the Z-axis. + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \param is_gaussian Tells if the blur uses a gaussian (\c true) or quasi-gaussian (\c false) kernel. + \note + - The blur is computed as a 0-order Deriche filter. This is not a gaussian blur. + - This is a recursive algorithm, not depending on the values of the standard deviations. + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=false) { + if (is_empty()) return *this; + if (is_gaussian) { + if (_width>1) vanvliet(sigma_x,0,'x',boundary_conditions); + if (_height>1) vanvliet(sigma_y,0,'y',boundary_conditions); + if (_depth>1) vanvliet(sigma_z,0,'z',boundary_conditions); + } else { + if (_width>1) deriche(sigma_x,0,'x',boundary_conditions); + if (_height>1) deriche(sigma_y,0,'y',boundary_conditions); + if (_depth>1) deriche(sigma_z,0,'z',boundary_conditions); + } + return *this; + } + + //! Blur image \newinstance. + CImg get_blur(const float sigma_x, const float sigma_y, const float sigma_z, + const bool boundary_conditions=true, const bool is_gaussian=false) const { + return CImg(*this,false).blur(sigma_x,sigma_y,sigma_z,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically. + /** + \param sigma Standard deviation of the blur. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \see deriche(), vanvliet(). + **/ + CImg& blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=false) { + const float nsigma = sigma>=0?sigma:-sigma*cimg::max(_width,_height,_depth)/100; + return blur(nsigma,nsigma,nsigma,boundary_conditions,is_gaussian); + } + + //! Blur image isotropically \newinstance. + CImg get_blur(const float sigma, const bool boundary_conditions=true, const bool is_gaussian=false) const { + return CImg(*this,false).blur(sigma,boundary_conditions,is_gaussian); + } + + //! Blur image anisotropically, directed by a field of diffusion tensors. + /** + \param G Field of square roots of diffusion tensors/vectors used to drive the smoothing. + \param amplitude Amplitude of the smoothing. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + template + CImg& blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=1) { + + // Check arguments and init variables + if (!is_sameXYZ(G) || (G._spectrum!=3 && G._spectrum!=6)) + throw CImgArgumentException(_cimg_instance + "blur_anisotropic(): Invalid specified diffusion tensor field (%u,%u,%u,%u,%p).", + cimg_instance, + G._width,G._height,G._depth,G._spectrum,G._data); + + if (is_empty() || amplitude<=0 || dl<0) return *this; + const bool is_3d = (G._spectrum==6); + T val_min, val_max = max_min(val_min); + cimg_abort_init; + + if (da<=0) { // Iterated oriented Laplacians + CImg velocity(_width,_height,_depth,_spectrum); + for (unsigned int iteration = 0; iteration<(unsigned int)amplitude; ++iteration) { + Tfloat *ptrd = velocity._data, veloc_max = 0; + if (is_3d) // 3d version + cimg_forC(*this,c) { + cimg_abort_test(); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixx = Incc + Ipcc - 2*Iccc, + ixy = (Innc + Ippc - Inpc - Ipnc)/4, + ixz = (Incn + Ipcp - Incp - Ipcn)/4, + iyy = Icnc + Icpc - 2*Iccc, + iyz = (Icnn + Icpp - Icnp - Icpn)/4, + izz = Iccn + Iccp - 2*Iccc, + veloc = (Tfloat)(G(x,y,z,0)*ixx + 2*G(x,y,z,1)*ixy + 2*G(x,y,z,2)*ixz + + G(x,y,z,3)*iyy + 2*G(x,y,z,4)*iyz + G(x,y,z,5)*izz); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + else // 2d version + cimg_forZC(*this,z,c) { + cimg_abort_test(); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + veloc = (Tfloat)(G(x,y,0,0)*ixx + 2*G(x,y,0,1)*ixy + G(x,y,0,2)*iyy); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + } + if (veloc_max>0) *this+=(velocity*=dl/veloc_max); + } + } else { // LIC-based smoothing. + const ulongT whd = (ulongT)_width*_height*_depth; + const float sqrt2amplitude = (float)std::sqrt(2*amplitude); + const int dx1 = width() - 1, dy1 = height() - 1, dz1 = depth() - 1; + CImg res(_width,_height,_depth,_spectrum,0), W(_width,_height,_depth,is_3d?4:3), val(_spectrum,1,1,1,0); + int N = 0; + if (is_3d) { // 3d version + for (float phi = (180%(int)da)/2.0f; phi<=180; phi+=da) { + const float phir = (float)(phi*cimg::PI/180), datmp = (float)(da/std::cos(phir)), + da2 = datmp<1?360.0f:datmp; + for (float theta = 0; theta<360; (theta+=da2),++N) { + const float + thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)*std::cos(phir)), + vy = (float)(std::sin(thetar)*std::cos(phir)), + vz = (float)std::sin(phir); + const t + *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2), + *pd = G.data(0,0,0,3), *pe = G.data(0,0,0,4), *pf = G.data(0,0,0,5); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2), *pd3 = W.data(0,0,0,3); + cimg_forXYZ(G,xg,yg,zg) { + const t a = *(pa++), b = *(pb++), c = *(pc++), d = *(pd++), e = *(pe++), f = *(pf++); + const float + u = (float)(a*vx + b*vy + c*vz), + v = (float)(b*vx + d*vy + e*vz), + w = (float)(c*vx + e*vy + f*vz), + n = 1e-5f + cimg::hypot(u,v,w), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)(w*dln); + *(pd3++) = (Tfloat)n; + } + + cimg_abort_test(); + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=2) + firstprivate(val)) + cimg_forYZ(*this,y,z) cimg_abort_try2 { + cimg_abort_test2(); + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,z,3), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y, + Z = (float)z; + switch (interpolation_type) { + case 0 : { // Nearest neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f), + cz = (int)(Z + 0.5f); + const float + u = (float)W(cx,cy,cz,0), + v = (float)W(cx,cy,cz,1), + w = (float)W(cx,cy,cz,2); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,cz,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,cz,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u = (float)(W._linear_atXYZ(X,Y,Z,0)), + v = (float)(W._linear_atXYZ(X,Y,Z,1)), + w = (float)(W._linear_atXYZ(X,Y,Z,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + default : { // 2nd order Runge Kutta + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1 && Z>=0 && Z<=dz1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,0)), + v0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,1)), + w0 = (float)(0.5f*W._linear_atXYZ(X,Y,Z,2)), + u = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,0)), + v = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,1)), + w = (float)(W._linear_atXYZ(X + u0,Y + v0,Z + w0,2)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXYZ(X,Y,Z,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXYZ(X,Y,Z,c)); + S+=coef; + } + X+=u; Y+=v; Z+=w; + } + } break; + } + Tfloat *ptrd = res.data(x,y,z); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,z,c)); ptrd+=whd; } + } + } cimg_abort_catch2() + } + } + } else { // 2d LIC algorithm + for (float theta = (360%(int)da)/2.0f; theta<360; (theta+=da),++N) { + const float thetar = (float)(theta*cimg::PI/180), + vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar)); + const t *pa = G.data(0,0,0,0), *pb = G.data(0,0,0,1), *pc = G.data(0,0,0,2); + Tfloat *pd0 = W.data(0,0,0,0), *pd1 = W.data(0,0,0,1), *pd2 = W.data(0,0,0,2); + cimg_forXY(G,xg,yg) { + const t a = *(pa++), b = *(pb++), c = *(pc++); + const float + u = (float)(a*vx + b*vy), + v = (float)(b*vx + c*vy), + n = std::max(1e-5f,cimg::hypot(u,v)), + dln = dl/n; + *(pd0++) = (Tfloat)(u*dln); + *(pd1++) = (Tfloat)(v*dln); + *(pd2++) = (Tfloat)n; + } + + cimg_abort_test(); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256 && _height>=2) firstprivate(val)) + cimg_forY(*this,y) cimg_abort_try2 { + cimg_abort_test2(); + cimg_forX(*this,x) { + val.fill(0); + const float + n = (float)W(x,y,0,2), + fsigma = (float)(n*sqrt2amplitude), + fsigma2 = 2*fsigma*fsigma, + length = gauss_prec*fsigma; + float + S = 0, + X = (float)x, + Y = (float)y; + switch (interpolation_type) { + case 0 : { // Nearest-neighbor + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const int + cx = (int)(X + 0.5f), + cy = (int)(Y + 0.5f); + const float + u = (float)W(cx,cy,0,0), + v = (float)W(cx,cy,0,1); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)(*this)(cx,cy,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*(*this)(cx,cy,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + case 1 : { // Linear interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u = (float)(W._linear_atXY(X,Y,0,0)), + v = (float)(W._linear_atXY(X,Y,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } break; + default : { // 2nd-order Runge-kutta interpolation + for (float l = 0; l=0 && X<=dx1 && Y>=0 && Y<=dy1; l+=dl) { + const float + u0 = (float)(0.5f*W._linear_atXY(X,Y,0,0)), + v0 = (float)(0.5f*W._linear_atXY(X,Y,0,1)), + u = (float)(W._linear_atXY(X + u0,Y + v0,0,0)), + v = (float)(W._linear_atXY(X + u0,Y + v0,0,1)); + if (is_fast_approx) { cimg_forC(*this,c) val[c]+=(Tfloat)_linear_atXY(X,Y,0,c); ++S; } + else { + const float coef = (float)std::exp(-l*l/fsigma2); + cimg_forC(*this,c) val[c]+=(Tfloat)(coef*_linear_atXY(X,Y,0,c)); + S+=coef; + } + X+=u; Y+=v; + } + } + } + Tfloat *ptrd = res.data(x,y); + if (S>0) cimg_forC(res,c) { *ptrd+=val[c]/S; ptrd+=whd; } + else cimg_forC(res,c) { *ptrd+=(Tfloat)((*this)(x,y,0,c)); ptrd+=whd; } + } + } cimg_abort_catch2() + } + } + const Tfloat *ptrs = res._data; + cimg_for(*this,ptrd,T) { + const Tfloat val = *(ptrs++)/N; + *ptrd = valval_max?val_max:(T)val); + } + } + cimg_abort_test(); + return *this; + } + + //! Blur image anisotropically, directed by a field of diffusion tensors \newinstance. + template + CImg get_blur_anisotropic(const CImg& G, + const float amplitude=60, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way. + /** + \param amplitude Amplitude of the smoothing. + \param sharpness Sharpness. + \param anisotropy Anisotropy. + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param dl Spatial discretization. + \param da Angular discretization. + \param gauss_prec Precision of the diffusion process. + \param interpolation_type Interpolation scheme. + Can be { 0=nearest-neighbor | 1=linear | 2=Runge-Kutta }. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + CImg& blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, const float da=30, + const float gauss_prec=2, const unsigned int interpolation_type=0, + const bool is_fast_approx=true) { + return blur_anisotropic(get_diffusion_tensors(sharpness,anisotropy,alpha,sigma,interpolation_type!=3), + amplitude,dl,da,gauss_prec,interpolation_type,is_fast_approx); + } + + //! Blur image anisotropically, in an edge-preserving way \newinstance. + CImg get_blur_anisotropic(const float amplitude, const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const float dl=0.8f, + const float da=30, const float gauss_prec=2, + const unsigned int interpolation_type=0, + const bool is_fast_approx=true) const { + return CImg(*this,false).blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec, + interpolation_type,is_fast_approx); + } + + //! Blur image, with the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_x Amount of blur along the X-axis. + \param sigma_y Amount of blur along the Y-axis. + \param sigma_z Amount of blur along the Z-axis. + \param sigma_r Amount of blur along the value axis. + \param sampling_x Amount of downsampling along the X-axis used for the approximation. + Defaults (0) to sigma_x. + \param sampling_y Amount of downsampling along the Y-axis used for the approximation. + Defaults (0) to sigma_y. + \param sampling_z Amount of downsampling along the Z-axis used for the approximation. + Defaults (0) to sigma_z. + \param sampling_r Amount of downsampling along the value axis used for the approximation. + Defaults (0) to sigma_r. + \note This algorithm uses the optimisation technique proposed by S. Paris and F. Durand, in ECCV'2006 + (extended for 3d volumetric images). + It is based on the reference implementation http://people.csail.mit.edu/jiawen/software/bilateralFilter.m + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_bilateral(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || (!sigma_x && !sigma_y && !sigma_z)) return *this; + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return blur(sigma_x,sigma_y,sigma_z); + const float + edge_delta = (float)(edge_max - edge_min), + _sigma_x = sigma_x>=0?sigma_x:-sigma_x*_width/100, + _sigma_y = sigma_y>=0?sigma_y:-sigma_y*_height/100, + _sigma_z = sigma_z>=0?sigma_z:-sigma_z*_depth/100, + __sigma_r = sigma_r>=0?sigma_r:-sigma_r*(edge_max - edge_min)/100, + _sigma_r = cimg::max(0.1f,__sigma_r), + _sampling_x = sampling_x?sampling_x:std::max(_sigma_x,1.0f), + _sampling_y = sampling_y?sampling_y:std::max(_sigma_y,1.0f), + _sampling_z = sampling_z?sampling_z:std::max(_sigma_z,1.0f), + _sampling_r = sampling_r?sampling_r:std::max(_sigma_r,edge_delta/256), + derived_sigma_x = _sigma_x / _sampling_x, + derived_sigma_y = _sigma_y / _sampling_y, + derived_sigma_z = _sigma_z / _sampling_z, + derived_sigma_r = _sigma_r / _sampling_r; + const int + padding_x = (int)(2*derived_sigma_x) + 1, + padding_y = (int)(2*derived_sigma_y) + 1, + padding_z = (int)(2*derived_sigma_z) + 1, + padding_r = (int)(2*derived_sigma_r) + 1; + const unsigned int + bx = (unsigned int)((_width - 1)/_sampling_x + 1 + 2*padding_x), + by = (unsigned int)((_height - 1)/_sampling_y + 1 + 2*padding_y), + bz = (unsigned int)((_depth - 1)/_sampling_z + 1 + 2*padding_z), + br = (unsigned int)(edge_delta/_sampling_r + 1 + 2*padding_r); + if (bx>0 || by>0 || bz>0 || br>0) { + const bool is_3d = (_depth>1); + if (is_3d) { // 3d version of the algorithm + CImg bgrid(bx,by,bz,br), bgridw(bx,by,bz,br); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); bgridw.fill(0); + cimg_forXYZ(*this,x,y,z) { + const T val = (*this)(x,y,z,c); + const float edge = (float)_guide(x,y,z); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + Z = (int)cimg::round(z/_sampling_z) + padding_z, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,Z,R)+=(float)val; + bgridw(X,Y,Z,R)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + bgridw.blur(derived_sigma_x,derived_sigma_y,derived_sigma_z,true).deriche(derived_sigma_r,0,'c',false); + + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(size()>=4096)) + cimg_forXYZ(*this,x,y,z) { + const float edge = (float)_guide(x,y,z); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + Z = z/_sampling_z + padding_z, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid.linear_atXYZC(X,Y,Z,R), bval1 = bgridw.linear_atXYZC(X,Y,Z,R); + (*this)(x,y,z,c) = (T)(bval0/bval1); + } + } + } else { // 2d version of the algorithm + CImg bgrid(bx,by,br,2); + cimg_forC(*this,c) { + const CImg _guide = guide.get_shared_channel(c%guide._spectrum); + bgrid.fill(0); + cimg_forXY(*this,x,y) { + const T val = (*this)(x,y,c); + const float edge = (float)_guide(x,y); + const int + X = (int)cimg::round(x/_sampling_x) + padding_x, + Y = (int)cimg::round(y/_sampling_y) + padding_y, + R = (int)cimg::round((edge - edge_min)/_sampling_r) + padding_r; + bgrid(X,Y,R,0)+=(float)val; + bgrid(X,Y,R,1)+=1; + } + bgrid.blur(derived_sigma_x,derived_sigma_y,0,true).blur(0,0,derived_sigma_r,false); + + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(size()>=4096)) + cimg_forXY(*this,x,y) { + const float edge = (float)_guide(x,y); + const float + X = x/_sampling_x + padding_x, + Y = y/_sampling_y + padding_y, + R = (edge - edge_min)/_sampling_r + padding_r; + const float bval0 = bgrid.linear_atXYZ(X,Y,R,0), bval1 = bgrid.linear_atXYZ(X,Y,R,1); + (*this)(x,y,c) = (T)(bval0/bval1); + } + } + } + } + return *this; + } + + //! Blur image, with the joint bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_x, const float sigma_y, + const float sigma_z, const float sigma_r, + const float sampling_x, const float sampling_y, + const float sampling_z, const float sampling_r) const { + return CImg(*this,false).blur_bilateral(guide,sigma_x,sigma_y,sigma_z,sigma_r, + sampling_x,sampling_y,sampling_z,sampling_r); + } + + //! Blur image using the joint bilateral filter. + /** + \param guide Image used to model the smoothing weights. + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_r Amount of blur along the value axis. + \param sampling_s Amount of downsampling along the XYZ-axes used for the approximation. Defaults to sigma_s. + \param sampling_r Amount of downsampling along the value axis used for the approximation. Defaults to sigma_r. + **/ + template + CImg& blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) { + const float _sigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100; + return blur_bilateral(guide,_sigma_s,_sigma_s,_sigma_s,sigma_r,sampling_s,sampling_s,sampling_s,sampling_r); + } + + //! Blur image using the bilateral filter \newinstance. + template + CImg get_blur_bilateral(const CImg& guide, + const float sigma_s, const float sigma_r, + const float sampling_s=0, const float sampling_r=0) const { + return CImg(*this,false).blur_bilateral(guide,sigma_s,sigma_r,sampling_s,sampling_r); + } + + // [internal] Apply a box filter (used by CImg::boxfilter() and CImg::blur_box()). + /* + \param ptr the pointer of the data + \param N size of the data + \param boxsize Size of the box filter (can be subpixel). + \param off the offset between two data point + \param order the order of the filter 0 (smoothing), 1st derivtive and 2nd derivative. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + */ + static void _cimg_blur_box_apply(T *ptr, const float boxsize, const int N, const ulongT off, + const int order, const bool boundary_conditions) { + // Smooth. + if (boxsize>1) { + const int w2 = (int)(boxsize - 1)/2; + const unsigned int winsize = 2*w2 + 1U; + const double frac = (boxsize - winsize)/2.0; + CImg win(winsize); + Tfloat sum = 0; // window sum + for (int x = -w2; x<=w2; ++x) { + win[x + w2] = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,x); + sum+=win[x + w2]; + } + int ifirst = 0, ilast = 2*w2; + Tfloat + prev = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,-w2 - 1), + next = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,w2 + 1); + for (int x = 0; x < N - 1; ++x) { + const double sum2 = sum + frac * (prev + next); + ptr[x*off] = (T)(sum2/boxsize); + prev = win[ifirst]; + sum-=prev; + ifirst = (int)((ifirst + 1)%winsize); + ilast = (int)((ilast + 1)%winsize); + win[ilast] = next; + sum+=next; + next = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,x + w2 + 2); + } + const double sum2 = sum + frac * (prev + next); + ptr[(N - 1)*off] = (T)(sum2/boxsize); + } + + // Derive. + switch (order) { + case 0 : + break; + case 1 : { + Tfloat + p = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,-1), + c = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,0), + n = __cimg_blur_box_apply(ptr,N,off,boundary_conditions,1); + for (int x = 0; x=N) return boundary_conditions?ptr[(N - 1)*off]:T(); + return ptr[x*off]; + } + + // Apply box filter of order 0,1,2. + /** + \param boxsize Size of the box window (can be subpixel) + \param order the order of the filter 0,1 or 2. + \param axis Axis along which the filter is computed. Can be { 'x' | 'y' | 'z' | 'c' }. + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }. + **/ + CImg& boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true) { + if (is_empty() || !boxsize || (boxsize<=1 && !order)) return *this; + const char naxis = cimg::lowercase(axis); + const float nboxsize = boxsize>=0?boxsize:-boxsize* + (naxis=='x'?_width:naxis=='y'?_height:naxis=='z'?_depth:_spectrum)/100; + switch (naxis) { + case 'x' : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forYZC(*this,y,z,c) + _cimg_blur_box_apply(data(0,y,z,c),nboxsize,_width,1U,order,boundary_conditions); + } break; + case 'y' : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXZC(*this,x,z,c) + _cimg_blur_box_apply(data(x,0,z,c),nboxsize,_height,(ulongT)_width,order,boundary_conditions); + } break; + case 'z' : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXYC(*this,x,y,c) + _cimg_blur_box_apply(data(x,y,0,c),nboxsize,_depth,(ulongT)_width*_height,order,boundary_conditions); + } break; + default : { + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=256 && _height*_depth*_spectrum>=16)) + cimg_forXYZ(*this,x,y,z) + _cimg_blur_box_apply(data(x,y,z,0),nboxsize,_spectrum,(ulongT)_width*_height*_depth, + order,boundary_conditions); + } + } + return *this; + } + + // Apply box filter of order 0,1 or 2 \newinstance. + CImg get_boxfilter(const float boxsize, const int order, const char axis='x', + const bool boundary_conditions=true) const { + return CImg(*this,false).boxfilter(boxsize,order,axis,boundary_conditions); + } + + //! Blur image with a box filter. + /** + \param boxsize_x Size of the box window, along the X-axis (can be subpixel). + \param boxsize_y Size of the box window, along the Y-axis (can be subpixel). + \param boxsize_z Size of the box window, along the Z-axis (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { false=dirichlet | true=neumann }. + \note + - This is a recursive algorithm, not depending on the values of the box kernel size. + \see blur(). + **/ + CImg& blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true) { + if (is_empty()) return *this; + if (_width>1) boxfilter(boxsize_x,0,'x',boundary_conditions); + if (_height>1) boxfilter(boxsize_y,0,'y',boundary_conditions); + if (_depth>1) boxfilter(boxsize_z,0,'z',boundary_conditions); + return *this; + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize_x, const float boxsize_y, const float boxsize_z, + const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize_x,boxsize_y,boxsize_z,boundary_conditions); + } + + //! Blur image with a box filter. + /** + \param boxsize Size of the box window (can be subpixel). + \param boundary_conditions Boundary conditions. Can be { 0=dirichlet | 1=neumann }.a + \see deriche(), vanvliet(). + **/ + CImg& blur_box(const float boxsize, const bool boundary_conditions=true) { + const float nboxsize = boxsize>=0?boxsize:-boxsize*cimg::max(_width,_height,_depth)/100; + return blur_box(nboxsize,nboxsize,nboxsize,boundary_conditions); + } + + //! Blur image with a box filter \newinstance. + CImg get_blur_box(const float boxsize, const bool boundary_conditions=true) const { + return CImg(*this,false).blur_box(boxsize,boundary_conditions); + } + + //! Blur image, with the image guided filter. + /** + \param guide Image used to guide the smoothing process. + \param radius Spatial radius. If negative, it is expressed as a percentage of the largest image size. + \param regularization Regularization parameter. + If negative, it is expressed as a percentage of the guide value range. + \note This method implements the filtering algorithm described in: + He, Kaiming; Sun, Jian; Tang, Xiaoou, "Guided Image Filtering," Pattern Analysis and Machine Intelligence, + IEEE Transactions on , vol.35, no.6, pp.1397,1409, June 2013 + **/ + template + CImg& blur_guided(const CImg& guide, const float radius, const float regularization) { + return get_blur_guided(guide,radius,regularization).move_to(*this); + } + + //! Blur image, with the image guided filter \newinstance. + template + CImg get_blur_guided(const CImg& guide, const float radius, const float regularization) const { + if (!is_sameXYZ(guide)) + throw CImgArgumentException(_cimg_instance + "blur_guided(): Invalid size for specified guide image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data); + if (is_empty() || !radius) return *this; + const int _radius = radius>=0?(int)radius:(int)(-radius*cimg::max(_width,_height,_depth)/100); + float _regularization = regularization; + if (regularization<0) { + T edge_min, edge_max = guide.max_min(edge_min); + if (edge_min==edge_max) return *this; + _regularization = -regularization*(edge_max - edge_min)/100; + } + _regularization = std::max(_regularization,0.01f); + const unsigned int psize = (unsigned int)(1 + 2*_radius); + const CImg N = CImg(_width,_height,_depth,1,1)._blur_guided(psize); + CImg + mean_I = CImg(guide,false)._blur_guided(psize).div(N), + mean_p = CImg(*this,false)._blur_guided(psize).div(N), + cov_Ip = CImg(*this,false).mul(guide)._blur_guided(psize).div(N)-=mean_p.get_mul(mean_I), + var_I = CImg(guide,false).sqr()._blur_guided(psize).div(N)-=mean_I.get_sqr(), + &a = cov_Ip.div(var_I+=_regularization), + &b = mean_p-=a.get_mul(mean_I); + a._blur_guided(psize).div(N); + b._blur_guided(psize).div(N); + return a.mul(guide)+=b; + } + + // [internal] Perform box filter with dirichlet boundary conditions. + CImg& _blur_guided(const unsigned int psize) { + const int p1 = (int)psize/2, p2 = (int)psize - p1; + if (_depth!=1) { + CImg cumul = get_cumulate('z'), cumul2 = cumul.get_shift(0,0,p2,0,1); + (cumul.shift(0,0,-p1,0,1)-=cumul2).move_to(*this); + } + if (_height!=1) { + CImg cumul = get_cumulate('y'), cumul2 = cumul.get_shift(0,p2,0,0,1); + (cumul.shift(0,-p1,0,0,1)-=cumul2).move_to(*this); + } + if (_width!=1) { + CImg cumul = get_cumulate('x'), cumul2 = cumul.get_shift(p2,0,0,0,1); + (cumul.shift(-p1,0,0,0,1)-=cumul2).move_to(*this); + } + return *this; + } + + //! Blur image using patch-based space. + /** + \param sigma_s Amount of blur along the XYZ-axes. + \param sigma_p Amount of blur along the value axis. + \param patch_size Size of the patchs. + \param lookup_size Size of the window to search similar patchs. + \param smoothness Smoothness for the patch comparison. + \param is_fast_approx Tells if a fast approximation of the gaussian function is used or not. + **/ + CImg& blur_patch(const float sigma_s, const float sigma_p, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, const bool is_fast_approx=true) { + if (is_empty() || !patch_size || !lookup_size) return *this; + return get_blur_patch(sigma_s,sigma_p,patch_size,lookup_size,smoothness,is_fast_approx).move_to(*this); + } + + //! Blur image using patch-based space \newinstance. + CImg get_blur_patch(const float sigma_s, const float sigma_p, const unsigned int patch_size=3, + const unsigned int lookup_size=4, const float smoothness=0, + const bool is_fast_approx=true) const { + +#define _cimg_blur_patch3d_fast(N) \ + cimg_for##N##XYZ(res,x,y,z) { \ + T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,x,y,z,c,pP,T); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + float sum_weights = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (cimg::abs(img(x,y,z,0) - img(p,q,r,0))3?0.0f:1.0f; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c); \ + } \ + if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } + +#define _cimg_blur_patch3d(N) \ + cimg_for##N##XYZ(res,x,y,z) { \ + T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,x,y,z,c,pP,T); pP+=N3; } \ + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, \ + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; \ + float sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { \ + T *pQ = Q._data; cimg_forC(res,c) { cimg_get##N##x##N##x##N(img,p,q,r,c,pQ,T); pQ+=N3; } \ + float distance2 = 0; \ + pQ = Q._data; cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const float dx = (float)p - x, dy = (float)q - y, dz = (float)r - z, \ + alldist = distance2 + (dx*dx + dy*dy + dz*dz)/sigma_s2, weight = (float)std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=weight_max*(*this)(x,y,z,c); \ + if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights; \ + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); \ + } + +#define _cimg_blur_patch2d_fast(N) \ + cimg_for##N##XY(res,x,y) { \ + T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N(img,x,y,0,c,pP,T); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + float sum_weights = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (cimg::abs(img(x,y,0,0) - img(p,q,0,0))3?0.0f:1.0f; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c); \ + } \ + if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } + +#define _cimg_blur_patch2d(N) \ + cimg_for##N##XY(res,x,y) { \ + T *pP = P._data; cimg_forC(res,c) { cimg_get##N##x##N(img,x,y,0,c,pP,T); pP+=N2; } \ + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; \ + float sum_weights = 0, weight_max = 0; \ + cimg_for_in##N##XY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { \ + T *pQ = Q._data; cimg_forC(res,c) { cimg_get##N##x##N(img,p,q,0,c,pQ,T); pQ+=N2; } \ + float distance2 = 0; \ + pQ = Q._data; cimg_for(P,pP,T) { const float dI = (float)*pP - (float)*(pQ++); distance2+=dI*dI; } \ + distance2/=Pnorm; \ + const float dx = (float)p - x, dy = (float)q - y, \ + alldist = distance2 + (dx*dx+dy*dy)/sigma_s2, weight = (float)std::exp(-alldist); \ + if (weight>weight_max) weight_max = weight; \ + sum_weights+=weight; \ + cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c); \ + } \ + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=weight_max*(*this)(x,y,c); \ + if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights; \ + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); \ + } + + if (is_empty() || !patch_size || !lookup_size) return +*this; + CImg res(_width,_height,_depth,_spectrum,0); + const CImg _img = smoothness>0?get_blur(smoothness):CImg(),&img = smoothness>0?_img:*this; + CImg P(patch_size*patch_size*_spectrum), Q(P); + const float + nsigma_s = sigma_s>=0?sigma_s:-sigma_s*cimg::max(_width,_height,_depth)/100, + sigma_s2 = nsigma_s*nsigma_s, sigma_p2 = sigma_p*sigma_p, sigma_p3 = 3*sigma_p, + Pnorm = P.size()*sigma_p2; + const int rsize2 = (int)lookup_size/2, rsize1 = (int)lookup_size - rsize2 - 1; + const unsigned int N2 = patch_size*patch_size, N3 = N2*patch_size; + cimg::unused(N2,N3); + if (_depth>1) switch (patch_size) { // 3d + case 2 : if (is_fast_approx) _cimg_blur_patch3d_fast(2) else _cimg_blur_patch3d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch3d_fast(3) else _cimg_blur_patch3d(3) break; + default : { + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(res._width>=32 && res._height*res._depth>=4) + private(P,Q)) + cimg_forXYZ(res,x,y,z) { // Fast + P = img.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + float sum_weights = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (cimg::abs(img(x,y,z,0)-img(p,q,r,0))3?0.0f:1.0f; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c); + } + if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } else + cimg_pragma_openmp(parallel for collapse(2) + if (res._width>=32 && res._height*res._depth>=4) firstprivate(P,Q)) + cimg_forXYZ(res,x,y,z) { // Exact + P = img.get_crop(x - psize1,y - psize1,z - psize1,x + psize2,y + psize2,z + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, z0 = z - rsize1, + x1 = x + rsize2, y1 = y + rsize2, z1 = z + rsize2; + float sum_weights = 0, weight_max = 0; + cimg_for_inXYZ(res,x0,y0,z0,x1,y1,z1,p,q,r) if (p!=x || q!=y || r!=z) { + (Q = img.get_crop(p - psize1,q - psize1,r - psize1,p + psize2,q + psize2,r + psize2,true))-=P; + const float + dx = (float)x - p, dy = (float)y - q, dz = (float)z - r, + distance2 = (float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy + dz*dz)/sigma_s2), + weight = (float)std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,z,c)+=weight*(*this)(p,q,r,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,z,c)+=weight_max*(*this)(x,y,z,c); + if (sum_weights>0) cimg_forC(res,c) res(x,y,z,c)/=sum_weights; + else cimg_forC(res,c) res(x,y,z,c) = (Tfloat)((*this)(x,y,z,c)); + } + } + } else switch (patch_size) { // 2d + case 2 : if (is_fast_approx) _cimg_blur_patch2d_fast(2) else _cimg_blur_patch2d(2) break; + case 3 : if (is_fast_approx) _cimg_blur_patch2d_fast(3) else _cimg_blur_patch2d(3) break; + case 4 : if (is_fast_approx) _cimg_blur_patch2d_fast(4) else _cimg_blur_patch2d(4) break; + case 5 : if (is_fast_approx) _cimg_blur_patch2d_fast(5) else _cimg_blur_patch2d(5) break; + case 6 : if (is_fast_approx) _cimg_blur_patch2d_fast(6) else _cimg_blur_patch2d(6) break; + case 7 : if (is_fast_approx) _cimg_blur_patch2d_fast(7) else _cimg_blur_patch2d(7) break; + case 8 : if (is_fast_approx) _cimg_blur_patch2d_fast(8) else _cimg_blur_patch2d(8) break; + case 9 : if (is_fast_approx) _cimg_blur_patch2d_fast(9) else _cimg_blur_patch2d(9) break; + default : { // Fast + const int psize2 = (int)patch_size/2, psize1 = (int)patch_size - psize2 - 1; + if (is_fast_approx) + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=32 && res._height>=4) firstprivate(P,Q)) + cimg_forXY(res,x,y) { // 2d fast approximation. + P = img.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + float sum_weights = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) if (cimg::abs(img(x,y,0)-img(p,q,0))3?0.0f:1.0f; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c); + } + if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights; + else cimg_forC(res,c) res(x,y,c) = (Tfloat)((*this)(x,y,c)); + } else + cimg_pragma_openmp(parallel for cimg_openmp_if(res._width>=32 && res._height>=4) firstprivate(P,Q)) + cimg_forXY(res,x,y) { // 2d exact algorithm. + P = img.get_crop(x - psize1,y - psize1,x + psize2,y + psize2,true); + const int x0 = x - rsize1, y0 = y - rsize1, x1 = x + rsize2, y1 = y + rsize2; + float sum_weights = 0, weight_max = 0; + cimg_for_inXY(res,x0,y0,x1,y1,p,q) if (p!=x || q!=y) { + (Q = img.get_crop(p - psize1,q - psize1,p + psize2,q + psize2,true))-=P; + const float + dx = (float)x - p, dy = (float)y - q, + distance2 = (float)(Q.pow(2).sum()/Pnorm + (dx*dx + dy*dy)/sigma_s2), + weight = (float)std::exp(-distance2); + if (weight>weight_max) weight_max = weight; + sum_weights+=weight; + cimg_forC(res,c) res(x,y,c)+=weight*(*this)(p,q,c); + } + sum_weights+=weight_max; cimg_forC(res,c) res(x,y,c)+=weight_max*(*this)(x,y,c); + if (sum_weights>0) cimg_forC(res,c) res(x,y,c)/=sum_weights; + else cimg_forC(res,c) res(x,y,0,c) = (Tfloat)((*this)(x,y,c)); + } + } + } + return res; + } + + //! Blur image with the median filter. + /** + \param n Size of the median filter. + \param threshold Threshold used to discard pixels too far from the current pixel value in the median computation. + **/ + CImg& blur_median(const unsigned int n, const float threshold=0) { + if (!n) return *this; + return get_blur_median(n,threshold).move_to(*this); + } + + //! Blur image with the median filter \newinstance. + CImg get_blur_median(const unsigned int n, const float threshold=0) const { + if (is_empty() || n<=1) return +*this; + CImg res(_width,_height,_depth,_spectrum); + T *ptrd = res._data; + cimg::unused(ptrd); + 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)) + cimg_forXYZC(*this,x,y,z,c) { // With threshold. + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + const float val0 = (float)(*this)(x,y,z,c); + CImg values(n*n*n); + unsigned int nb_values = 0; + T *ptrd = values.data(); + cimg_for_inXYZ(*this,nx0,ny0,nz0,nx1,ny1,nz1,p,q,r) + if (cimg::abs((float)(*this)(p,q,r,c)-val0)<=threshold) { *(ptrd++) = (*this)(p,q,r,c); ++nb_values; } + res(x,y,z,c) = values.get_shared_points(0,nb_values - 1).median(); + } + else + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width>=16 && _height*_depth*_spectrum>=4)) + cimg_forXYZC(*this,x,y,z,c) { // Without threshold. + const int + x0 = x - hl, y0 = y - hl, z0 = z - hl, x1 = x + hr, y1 = y + hr, z1 = z + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, nz0 = z0<0?0:z0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1, nz1 = z1>=depth()?depth() - 1:z1; + res(x,y,z,c) = get_crop(nx0,ny0,nz0,c,nx1,ny1,nz1,c).median(); + } + } else { +#define _cimg_median_sort(a,b) if ((a)>(b)) cimg::swap(a,b) + if (res._height!=1) { // 2d + if (threshold>0) + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=16 && _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { // With threshold. + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + const float val0 = (float)(*this)(x,y,c); + CImg values(n*n); + unsigned int nb_values = 0; + T *ptrd = values.data(); + cimg_for_inXY(*this,nx0,ny0,nx1,ny1,p,q) + if (cimg::abs((float)(*this)(p,q,c)-val0)<=threshold) { *(ptrd++) = (*this)(p,q,c); ++nb_values; } + res(x,y,c) = values.get_shared_points(0,nb_values - 1).median(); + } + else switch (n) { // Without threshold. + case 3 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + T I[9] = { (T)0 }; + cimg_for3x3(*this,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6],I[7],I[8]); + } + } break; + case 5 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + T I[25] = { (T)0 }; + cimg_for5x5(*this,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4], + I[5],I[6],I[7],I[8],I[9], + I[10],I[11],I[12],I[13],I[14], + I[15],I[16],I[17],I[18],I[19], + I[20],I[21],I[22],I[23],I[24]); + } + } break; + case 7 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + T I[49] = { (T)0 }; + cimg_for7x7(*this,x,y,0,c,I,T) + res(x,y,c) = cimg::median(I[0],I[1],I[2],I[3],I[4],I[5],I[6], + I[7],I[8],I[9],I[10],I[11],I[12],I[13], + I[14],I[15],I[16],I[17],I[18],I[19],I[20], + I[21],I[22],I[23],I[24],I[25],I[26],I[27], + I[28],I[29],I[30],I[31],I[32],I[33],I[34], + I[35],I[36],I[37],I[38],I[39],I[40],I[41], + I[42],I[43],I[44],I[45],I[46],I[47],I[48]); + } + } break; + default : { + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=16 && _height*_spectrum>=4)) + cimg_forXYC(*this,x,y,c) { + const int + x0 = x - hl, y0 = y - hl, x1 = x + hr, y1 = y + hr, + nx0 = x0<0?0:x0, ny0 = y0<0?0:y0, + nx1 = x1>=width()?width() - 1:x1, ny1 = y1>=height()?height() - 1:y1; + res(x,y,c) = get_crop(nx0,ny0,0,c,nx1,ny1,0,c).median(); + } + } + } + } else { // 1d + + CImg I; + if (threshold>0) + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=16 && _spectrum>=2)) + cimg_forXC(*this,x,c) { // With threshold. + const int + x0 = x - hl, x1 = x + hr, + nx0 = x0<0?0:x0, nx1 = x1>=width()?width() - 1:x1; + const float val0 = (float)(*this)(x,c); + CImg values(n); + unsigned int nb_values = 0; + T *ptrd = values.data(); + cimg_for_inX(*this,nx0,nx1,p) + if (cimg::abs((float)(*this)(p,c)-val0)<=threshold) { *(ptrd++) = (*this)(p,c); ++nb_values; } + res(x,c) = values.get_shared_points(0,nb_values - 1).median(); + } + else switch (n) { // Without threshold. + case 2 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + I.assign(4); + cimg_for2x2(*this,x,y,0,c,I,T) res(x,c) = (T)(0.5f*(I[0] + I[1])); + } + } break; + case 3 : { + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + I.assign(9); + cimg_for3x3(*this,x,y,0,c,I,T) + res(x,c) = I[3]=16 && _spectrum>=2)) + cimg_forXC(*this,x,c) { + const int + x0 = x - hl, x1 = x + hr, + nx0 = x0<0?0:x0, nx1 = x1>=width()?width() - 1:x1; + res(x,c) = get_crop(nx0,0,0,c,nx1,0,0,c).median(); + } + } + } + } + } + return res; + } + + //! Sharpen image. + /** + \param amplitude Sharpening amplitude + \param sharpen_type Select sharpening method. Can be { false=inverse diffusion | true=shock filters }. + \param edge Edge threshold (shock filters only). + \param alpha Gradient smoothness (shock filters only). + \param sigma Tensor smoothness (shock filters only). + **/ + CImg& sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) { + if (is_empty()) return *this; + T val_min, val_max = max_min(val_min); + const float nedge = edge/2; + CImg velocity(_width,_height,_depth,_spectrum), _veloc_max(_spectrum); + + if (_depth>1) { // 3d + if (sharpen_type) { // Shock filters. + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=32 && _height*_depth>=16)) + cimg_forYZ(G,y,z) { + Tfloat *ptrG0 = G.data(0,y,z,0), *ptrG1 = G.data(0,y,z,1), + *ptrG2 = G.data(0,y,z,2), *ptrG3 = G.data(0,y,z,3); + CImg val, vec; + cimg_forX(G,x) { + G.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + if (val[2]<0) val[2] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = vec(0,2); + *(ptrG3++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1] + val[2],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=512 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + u = G(x,y,z,0), + v = G(x,y,z,1), + w = G(x,y,z,2), + amp = G(x,y,z,3), + ixx = Incc + Ipcc - 2*Iccc, + ixy = (Innc + Ippc - Inpc - Ipnc)/4, + ixz = (Incn + Ipcp - Incp - Ipcn)/4, + iyy = Icnc + Icpc - 2*Iccc, + iyz = (Icnn + Icpp - Icnp - Icpn)/4, + izz = Iccn + Iccp - 2*Iccc, + ixf = Incc - Iccc, + ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, + iyb = Iccc - Icpc, + izf = Iccn - Iccc, + izb = Iccc - Iccp, + itt = u*u*ixx + v*v*iyy + w*w*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb) + w*cimg::minmod(izf,izb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion. + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat veloc = -Ipcc - Incc - Icpc - Icnc - Iccp - Iccn + 6*Iccc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else { // 2d. + if (sharpen_type) { // Shock filters. + CImg G = (alpha>0?get_blur(alpha).get_structure_tensors():get_structure_tensors()); + if (sigma>0) G.blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=32 && _height>=16)) + cimg_forY(G,y) { + CImg val, vec; + Tfloat *ptrG0 = G.data(0,y,0,0), *ptrG1 = G.data(0,y,0,1), *ptrG2 = G.data(0,y,0,2); + cimg_forX(G,x) { + G.get_tensor_at(x,y).symmetric_eigen(val,vec); + if (val[0]<0) val[0] = 0; + if (val[1]<0) val[1] = 0; + *(ptrG0++) = vec(0,0); + *(ptrG1++) = vec(0,1); + *(ptrG2++) = 1 - (Tfloat)std::pow(1 + val[0] + val[1],-(Tfloat)nedge); + } + } + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=512 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + u = G(x,y,0), + v = G(x,y,1), + amp = G(x,y,2), + ixx = Inc + Ipc - 2*Icc, + ixy = (Inn + Ipp - Inp - Ipn)/4, + iyy = Icn + Icp - 2*Icc, + ixf = Inc - Icc, + ixb = Icc - Ipc, + iyf = Icn - Icc, + iyb = Icc - Icp, + itt = u*u*ixx + v*v*iyy + 2*u*v*ixy, + it = u*cimg::minmod(ixf,ixb) + v*cimg::minmod(iyf,iyb), + veloc = -amp*cimg::sign(itt)*cimg::abs(it); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } else // Inverse diffusion. + cimg_forC(*this,c) { + Tfloat *ptrd = velocity.data(0,0,0,c), veloc_max = 0; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat veloc = -Ipc - Inc - Icp - Icn + 4*Icc; + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } + _veloc_max[c] = veloc_max; + } + } + const Tfloat veloc_max = _veloc_max.max(); + if (veloc_max<=0) return *this; + return ((velocity*=amplitude/veloc_max)+=*this).cut(val_min,val_max).move_to(*this); + } + + //! Sharpen image \newinstance. + CImg get_sharpen(const float amplitude, const bool sharpen_type=false, const float edge=1, + const float alpha=0, const float sigma=0) const { + return (+*this).sharpen(amplitude,sharpen_type,edge,alpha,sigma); + } + + //! Return image gradient. + /** + \param axes Axes considered for the gradient computation, as a C-string (e.g "xy"). + \param scheme = Numerical scheme used for the gradient computation: + - -1 = Backward finite differences + - 0 = Centered finite differences + - 1 = Forward finite differences + - 2 = Using Sobel kernels + - 3 = Using rotation invariant kernels + - 4 = Using Deriche recusrsive filter. + - 5 = Using Van Vliet recusrsive filter. + **/ + CImgList get_gradient(const char *const axes=0, const int scheme=3) const { + CImgList grad(2,_width,_height,_depth,_spectrum); + bool is_3d = false; + if (axes) { + for (unsigned int a = 0; axes[a]; ++a) { + const char axis = cimg::lowercase(axes[a]); + switch (axis) { + case 'x' : case 'y' : break; + case 'z' : is_3d = true; break; + default : + throw CImgArgumentException(_cimg_instance + "get_gradient(): Invalid specified axis '%c'.", + cimg_instance, + axis); + } + } + } else is_3d = (_depth>1); + if (is_3d) { + CImg(_width,_height,_depth,_spectrum).move_to(grad); + switch (scheme) { // 3d. + case -1 : { // Backward finite differences. + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + const ulongT off = (ulongT)c*_width*_height*_depth; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = Iccc - Ipcc; + *(ptrd1++) = Iccc - Icpc; + *(ptrd2++) = Iccc - Iccp; + } + } + } break; + case 1 : { // Forward finite differences. + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + const ulongT off = (ulongT)c*_width*_height*_depth; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off; + CImg_2x2x2(I,Tfloat); + cimg_for2x2x2(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = Incc - Iccc; + *(ptrd1++) = Icnc - Iccc; + *(ptrd2++) = Iccn - Iccc; + } + } + } break; + case 4 : { // Deriche filter with low standard variation. + grad[0] = get_deriche(0,1,'x'); + grad[1] = get_deriche(0,1,'y'); + grad[2] = get_deriche(0,1,'z'); + } break; + case 5 : { // Van Vliet filter with low standard variation. + grad[0] = get_vanvliet(0,1,'x'); + grad[1] = get_vanvliet(0,1,'y'); + grad[2] = get_vanvliet(0,1,'z'); + } break; + default : { // Central finite differences. + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + const ulongT off = (ulongT)c*_width*_height*_depth; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off, *ptrd2 = grad[2]._data + off; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = (Incc - Ipcc)/2; + *(ptrd1++) = (Icnc - Icpc)/2; + *(ptrd2++) = (Iccn - Iccp)/2; + } + } + } + } + } else switch (scheme) { // 2d. + case -1 : { // Backward finite differences. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = Icc - Ipc; + *(ptrd1++) = Icc - Icp; + } + } + } break; + case 1 : { // Forward finite differences. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off; + CImg_2x2(I,Tfloat); + cimg_for2x2(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = Inc - Icc; + *(ptrd1++) = Icn - Icc; + } + } + } break; + case 2 : { // Sobel scheme. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = -Ipp - 2*Ipc - Ipn + Inp + 2*Inc + Inn; + *(ptrd1++) = -Ipp - 2*Icp - Inp + Ipn + 2*Icn + Inn; + } + } + } break; + case 3 : { // Rotation invariant kernel. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off; + CImg_3x3(I,Tfloat); + const Tfloat a = (Tfloat)(0.25f*(2 - std::sqrt(2.0f))), b = (Tfloat)(0.5f*(std::sqrt(2.0f) - 1)); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = -a*Ipp - b*Ipc - a*Ipn + a*Inp + b*Inc + a*Inn; + *(ptrd1++) = -a*Ipp - b*Icp - a*Inp + a*Ipn + b*Icn + a*Inn; + } + } + } break; + case 4 : { // Van Vliet filter with low standard variation + grad[0] = get_deriche(0,1,'x'); + grad[1] = get_deriche(0,1,'y'); + } break; + case 5 : { // Deriche filter with low standard variation + grad[0] = get_vanvliet(0,1,'x'); + grad[1] = get_vanvliet(0,1,'y'); + } break; + default : { // Central finite differences + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height; + Tfloat *ptrd0 = grad[0]._data + off, *ptrd1 = grad[1]._data + off; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = (Inc - Ipc)/2; + *(ptrd1++) = (Icn - Icp)/2; + } + } + } + } + if (!axes) return grad; + CImgList res; + for (unsigned int l = 0; axes[l]; ++l) { + const char axis = cimg::lowercase(axes[l]); + switch (axis) { + case 'x' : res.insert(grad[0]); break; + case 'y' : res.insert(grad[1]); break; + case 'z' : res.insert(grad[2]); break; + } + } + grad.assign(); + return res; + } + + //! Return image hessian. + /** + \param axes Axes considered for the hessian computation, as a C-string (e.g "xy"). + **/ + CImgList get_hessian(const char *const axes=0) const { + CImgList res; + const char *naxes = axes, *const def_axes2d = "xxxyyy", *const def_axes3d = "xxxyxzyyyzzz"; + if (!axes) naxes = _depth>1?def_axes3d:def_axes2d; + const unsigned int lmax = (unsigned int)std::strlen(naxes); + if (lmax%2) + throw CImgArgumentException(_cimg_instance + "get_hessian(): Invalid specified axes '%s'.", + cimg_instance, + naxes); + + res.assign(lmax/2,_width,_height,_depth,_spectrum); + if (!cimg::strcasecmp(naxes,def_axes3d)) { // 3d + + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + const ulongT off = (ulongT)c*_width*_height*_depth; + Tfloat + *ptrd0 = res[0]._data + off, *ptrd1 = res[1]._data + off, *ptrd2 = res[2]._data + off, + *ptrd3 = res[3]._data + off, *ptrd4 = res[4]._data + off, *ptrd5 = res[5]._data + off; + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = Ipcc + Incc - 2*Iccc; // Ixx + *(ptrd1++) = (Ippc + Innc - Ipnc - Inpc)/4; // Ixy + *(ptrd2++) = (Ipcp + Incn - Ipcn - Incp)/4; // Ixz + *(ptrd3++) = Icpc + Icnc - 2*Iccc; // Iyy + *(ptrd4++) = (Icpp + Icnn - Icpn - Icnp)/4; // Iyz + *(ptrd5++) = Iccn + Iccp - 2*Iccc; // Izz + } + } + } else if (!cimg::strcasecmp(naxes,def_axes2d)) { // 2d + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + const ulongT off = (ulongT)c*_width*_height*_depth + z*_width*_height; + Tfloat *ptrd0 = res[0]._data + off, *ptrd1 = res[1]._data + off, *ptrd2 = res[2]._data + off; + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) { + *(ptrd0++) = Ipc + Inc - 2*Icc; // Ixx + *(ptrd1++) = (Ipp + Inn - Ipn - Inp)/4; // Ixy + *(ptrd2++) = Icp + Icn - 2*Icc; // Iyy + } + } + } else for (unsigned int l = 0; laxis2) cimg::swap(axis1,axis2); + bool valid_axis = false; + if (axis1=='x' && axis2=='x') { // Ixx + valid_axis = true; + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + Tfloat *ptrd = res[l2].data(0,0,z,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Ipc + Inc - 2*Icc; + } + } + else if (axis1=='x' && axis2=='y') { // Ixy + valid_axis = true; + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + Tfloat *ptrd = res[l2].data(0,0,z,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = (Ipp + Inn - Ipn - Inp)/4; + } + } + else if (axis1=='x' && axis2=='z') { // Ixz + valid_axis = true; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res[l2].data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = (Ipcp + Incn - Ipcn - Incp)/4; + } + } + else if (axis1=='y' && axis2=='y') { // Iyy + valid_axis = true; + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forZC(*this,z,c) { + Tfloat *ptrd = res[l2].data(0,0,z,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Icp + Icn - 2*Icc; + } + } + else if (axis1=='y' && axis2=='z') { // Iyz + valid_axis = true; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res[l2].data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = (Icpp + Icnn - Icpn - Icnp)/4; + } + } + else if (axis1=='z' && axis2=='z') { // Izz + valid_axis = true; + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res[l2].data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Iccn + Iccp - 2*Iccc; + } + } + else if (!valid_axis) + throw CImgArgumentException(_cimg_instance + "get_hessian(): Invalid specified axes '%s'.", + cimg_instance, + naxes); + } + return res; + } + + //! Compute image laplacian. + CImg& laplacian() { + return get_laplacian().move_to(*this); + } + + //! Compute image laplacian \newinstance. + CImg get_laplacian() const { + if (is_empty()) return CImg(); + CImg res(_width,_height,_depth,_spectrum); + if (_depth>1) { // 3d + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) *(ptrd++) = Incc + Ipcc + Icnc + Icpc + Iccn + Iccp - 6*Iccc; + } + } else if (_height>1) { // 2d + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc + Icn + Icp - 4*Icc; + } + } else { // 1d + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=1048576 && _height*_depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd = res.data(0,0,0,c); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) *(ptrd++) = Inc + Ipc - 2*Icc; + } + } + return res; + } + + //! Compute the structure tensor field of an image. + /** + \param is_fwbw_scheme scheme. Can be { false=centered | true=forward-backward } + **/ + CImg& structure_tensors(const bool is_fwbw_scheme=false) { + return get_structure_tensors(is_fwbw_scheme).move_to(*this); + } + + //! Compute the structure tensor field of an image \newinstance. + CImg get_structure_tensors(const bool is_fwbw_scheme=false) const { + if (is_empty()) return *this; + CImg res; + if (_depth>1) { // 3d + res.assign(_width,_height,_depth,6,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ix = (Incc - Ipcc)/2, + iy = (Icnc - Icpc)/2, + iz = (Iccn - Iccp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=ix*iz; + *(ptrd3++)+=iy*iy; + *(ptrd4++)+=iy*iz; + *(ptrd5++)+=iz*iz; + } + } + } else { // Forward/backward finite differences. + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height*_depth>=1048576 && _spectrum>=2)) + cimg_forC(*this,c) { + Tfloat + *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2), + *ptrd3 = res.data(0,0,0,3), *ptrd4 = res.data(0,0,0,4), *ptrd5 = res.data(0,0,0,5); + CImg_3x3x3(I,Tfloat); + cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) { + const Tfloat + ixf = Incc - Iccc, ixb = Iccc - Ipcc, + iyf = Icnc - Iccc, iyb = Iccc - Icpc, + izf = Iccn - Iccc, izb = Iccc - Iccp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(ixf*izf + ixf*izb + ixb*izf + ixb*izb)/4; + *(ptrd3++)+=(iyf*iyf + iyb*iyb)/2; + *(ptrd4++)+=(iyf*izf + iyf*izb + iyb*izf + iyb*izb)/4; + *(ptrd5++)+=(izf*izf + izb*izb)/2; + } + } + } + } else { // 2d + res.assign(_width,_height,_depth,3,0); + if (!is_fwbw_scheme) { // Classical central finite differences + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ix = (Inc - Ipc)/2, + iy = (Icn - Icp)/2; + *(ptrd0++)+=ix*ix; + *(ptrd1++)+=ix*iy; + *(ptrd2++)+=iy*iy; + } + } + } else { // Forward/backward finite differences (version 2). + cimg_pragma_openmp(parallel for cimg_openmp_if(_width*_height>=1048576 && _depth*_spectrum>=2)) + cimg_forC(*this,c) { + Tfloat *ptrd0 = res.data(0,0,0,0), *ptrd1 = res.data(0,0,0,1), *ptrd2 = res.data(0,0,0,2); + CImg_3x3(I,Tfloat); + cimg_for3x3(*this,x,y,0,c,I,Tfloat) { + const Tfloat + ixf = Inc - Icc, ixb = Icc - Ipc, + iyf = Icn - Icc, iyb = Icc - Icp; + *(ptrd0++)+=(ixf*ixf + ixb*ixb)/2; + *(ptrd1++)+=(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb)/4; + *(ptrd2++)+=(iyf*iyf + iyb*iyb)/2; + } + } + } + } + return res; + } + + //! Compute field of diffusion tensors for edge-preserving smoothing. + /** + \param sharpness Sharpness + \param anisotropy Anisotropy + \param alpha Standard deviation of the gradient blur. + \param sigma Standard deviation of the structure tensor blur. + \param is_sqrt Tells if the square root of the tensor field is computed instead. + **/ + CImg& diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) { + CImg res; + const float + nsharpness = std::max(sharpness,1e-5f), + power1 = (is_sqrt?0.5f:1)*nsharpness, + power2 = power1/(1e-7f + 1 - anisotropy); + blur(alpha).normalize(0,(T)255); + + if (_depth>1) { // 3d + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=256 && _height*_depth>=256)) + cimg_forYZ(*this,y,z) { + Tfloat + *ptrd0 = res.data(0,y,z,0), *ptrd1 = res.data(0,y,z,1), *ptrd2 = res.data(0,y,z,2), + *ptrd3 = res.data(0,y,z,3), *ptrd4 = res.data(0,y,z,4), *ptrd5 = res.data(0,y,z,5); + CImg val(3), vec(3,3); + cimg_forX(*this,x) { + res.get_tensor_at(x,y,z).symmetric_eigen(val,vec); + const float + _l1 = val[2], _l2 = val[1], _l3 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, l3 = _l3>0?_l3:0, + ux = vec(0,0), uy = vec(0,1), uz = vec(0,2), + vx = vec(1,0), vy = vec(1,1), vz = vec(1,2), + wx = vec(2,0), wy = vec(2,1), wz = vec(2,2), + n1 = (float)std::pow(1 + l1 + l2 + l3,-power1), + n2 = (float)std::pow(1 + l1 + l2 + l3,-power2); + *(ptrd0++) = n1*(ux*ux + vx*vx) + n2*wx*wx; + *(ptrd1++) = n1*(ux*uy + vx*vy) + n2*wx*wy; + *(ptrd2++) = n1*(ux*uz + vx*vz) + n2*wx*wz; + *(ptrd3++) = n1*(uy*uy + vy*vy) + n2*wy*wy; + *(ptrd4++) = n1*(uy*uz + vy*vz) + n2*wy*wz; + *(ptrd5++) = n1*(uz*uz + vz*vz) + n2*wz*wz; + } + } + } else { // for 2d images + get_structure_tensors().move_to(res).blur(sigma); + cimg_pragma_openmp(parallel for cimg_openmp_if(_width>=256 && _height>=256)) + cimg_forY(*this,y) { + Tfloat *ptrd0 = res.data(0,y,0,0), *ptrd1 = res.data(0,y,0,1), *ptrd2 = res.data(0,y,0,2); + CImg val(2), vec(2,2); + cimg_forX(*this,x) { + res.get_tensor_at(x,y).symmetric_eigen(val,vec); + const float + _l1 = val[1], _l2 = val[0], + l1 = _l1>0?_l1:0, l2 = _l2>0?_l2:0, + ux = vec(1,0), uy = vec(1,1), + vx = vec(0,0), vy = vec(0,1), + n1 = (float)std::pow(1 + l1 + l2,-power1), + n2 = (float)std::pow(1 + l1 + l2,-power2); + *(ptrd0++) = n1*ux*ux + n2*vx*vx; + *(ptrd1++) = n1*ux*uy + n2*vx*vy; + *(ptrd2++) = n1*uy*uy + n2*vy*vy; + } + } + } + return res.move_to(*this); + } + + //! Compute field of diffusion tensors for edge-preserving smoothing \newinstance. + CImg get_diffusion_tensors(const float sharpness=0.7f, const float anisotropy=0.6f, + const float alpha=0.6f, const float sigma=1.1f, const bool is_sqrt=false) const { + return CImg(*this,false).diffusion_tensors(sharpness,anisotropy,alpha,sigma,is_sqrt); + } + + //! Estimate displacement field between two images. + /** + \param source Reference image. + \param smoothness Smoothness of estimated displacement field. + \param precision Precision required for algorithm convergence. + \param nb_scales Number of scales used to estimate the displacement field. + \param iteration_max Maximum number of iterations allowed for one scale. + \param is_backward If false, match I2(X + U(X)) = I1(X), else match I2(X) = I1(X - U(X)). + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + **/ + CImg& displacement(const CImg& source, const float smoothness=0.1f, const float precision=5.0f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) { + return get_displacement(source,smoothness,precision,nb_scales,iteration_max,is_backward,guide). + move_to(*this); + } + + //! Estimate displacement field between two images \newinstance. + CImg get_displacement(const CImg& source, + const float smoothness=0.1f, const float precision=5.0f, + const unsigned int nb_scales=0, const unsigned int iteration_max=10000, + const bool is_backward=false, + const CImg& guide=CImg::const_empty()) const { + if (is_empty() || !source) return +*this; + if (!is_sameXYZC(source)) + throw CImgArgumentException(_cimg_instance + "displacement(): Instance and source image (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + source._width,source._height,source._depth,source._spectrum,source._data); + if (precision<0) + throw CImgArgumentException(_cimg_instance + "displacement(): Invalid specified precision %g " + "(should be >=0)", + cimg_instance, + precision); + + const bool is_3d = source._depth>1; + const unsigned int constraint = is_3d?3:2; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum0?nb_scales: + (unsigned int)cimg::round(std::log(mins/8.0)/std::log(1.5),1,1); + + const float _precision = (float)std::pow(10.0,-(double)precision); + float sm, sM = source.max_min(sm), tm, tM = max_min(tm); + const float sdelta = sm==sM?1:(sM - sm), tdelta = tm==tM?1:(tM - tm); + + CImg U, V; + floatT bound = 0; + for (int scale = (int)_nb_scales - 1; scale>=0; --scale) { + const float factor = (float)std::pow(1.5,(double)scale); + const unsigned int + _sw = (unsigned int)(_width/factor), sw = _sw?_sw:1, + _sh = (unsigned int)(_height/factor), sh = _sh?_sh:1, + _sd = (unsigned int)(_depth/factor), sd = _sd?_sd:1; + if (sw<5 && sh<5 && (!is_3d || sd<5)) continue; // skip too small scales. + const CImg + I1 = (source.get_resize(sw,sh,sd,-100,2)-=sm)/=sdelta, + I2 = (get_resize(I1,2)-=tm)/=tdelta; + if (guide._spectrum>constraint) guide.get_resize(I2._width,I2._height,I2._depth,-100,1).move_to(V); + if (U) (U*=1.5f).resize(I2._width,I2._height,I2._depth,-100,3); + else { + if (guide) + guide.get_shared_channels(0,is_3d?2:1).get_resize(I2._width,I2._height,I2._depth,-100,2).move_to(U); + else U.assign(I2._width,I2._height,I2._depth,is_3d?3:2,0); + } + + float dt = 2, energy = cimg::type::max(); + const CImgList dI = is_backward?I1.get_gradient():I2.get_gradient(); + + for (unsigned int iteration = 0; iteration=0) // Isotropic regularization. + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_height*_depth>=8 && _width>=16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,x,y,z) if (V(x,y,z,3)) { // Apply constraints. + U(x,y,z,0) = V(x,y,z,0)/factor; + U(x,y,z,1) = V(x,y,z,1)/factor; + U(x,y,z,2) = V(x,y,z,2)/factor; + } + } else { // Anisotropic regularization. + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_height*_depth>=8 && _width>=16) + reduction(+:_energy)) + cimg_forYZ(U,y,z) { + const int + _p1y = y?y - 1:0, _n1y = yx) U(x,y,z,0) = (float)x; + if (U(x,y,z,1)>y) U(x,y,z,1) = (float)y; + if (U(x,y,z,2)>z) U(x,y,z,2) = (float)z; + bound = (float)x - _width; if (U(x,y,z,0)<=bound) U(x,y,z,0) = bound; + bound = (float)y - _height; if (U(x,y,z,1)<=bound) U(x,y,z,1) = bound; + bound = (float)z - _depth; if (U(x,y,z,2)<=bound) U(x,y,z,2) = bound; + } else { + if (U(x,y,z,0)<-x) U(x,y,z,0) = -(float)x; + if (U(x,y,z,1)<-y) U(x,y,z,1) = -(float)y; + if (U(x,y,z,2)<-z) U(x,y,z,2) = -(float)z; + bound = (float)_width - x; if (U(x,y,z,0)>=bound) U(x,y,z,0) = bound; + bound = (float)_height - y; if (U(x,y,z,1)>=bound) U(x,y,z,1) = bound; + bound = (float)_depth - z; if (U(x,y,z,2)>=bound) U(x,y,z,2) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forXYZ(V,x,y,z) if (V(x,y,z,3)) { // Apply constraints. + U(x,y,z,0) = V(x,y,z,0)/factor; + U(x,y,z,1) = V(x,y,z,1)/factor; + U(x,y,z,2) = V(x,y,z,2)/factor; + } + } + } + } else { // 2d version. + if (smoothness>=0) // Isotropic regularization. + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=8 && _width>=16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + smoothness*_energy_regul; + } + if (V) cimg_forX(V,x) if (V(x,y,2)) { // Apply constraints. + U(x,y,0) = V(x,y,0)/factor; + U(x,y,1) = V(x,y,1)/factor; + } + } else { // Anisotropic regularization. + const float nsmoothness = -smoothness; + cimg_pragma_openmp(parallel for cimg_openmp_if(_height>=8 && _width>=16) reduction(+:_energy)) + cimg_forY(U,y) { + const int _p1y = y?y - 1:0, _n1y = yx) U(x,y,0) = (float)x; + if (U(x,y,1)>y) U(x,y,1) = (float)y; + bound = (float)x - _width; if (U(x,y,0)<=bound) U(x,y,0) = bound; + bound = (float)y - _height; if (U(x,y,1)<=bound) U(x,y,1) = bound; + } else { + if (U(x,y,0)<-x) U(x,y,0) = -(float)x; + if (U(x,y,1)<-y) U(x,y,1) = -(float)y; + bound = (float)_width - x; if (U(x,y,0)>=bound) U(x,y,0) = bound; + bound = (float)_height - y; if (U(x,y,1)>=bound) U(x,y,1) = bound; + } + _energy+=delta_I*delta_I + nsmoothness*_energy_regul; + } + if (V) cimg_forX(V,x) if (V(x,y,2)) { // Apply constraints. + U(x,y,0) = V(x,y,0)/factor; + U(x,y,1) = V(x,y,1)/factor; + } + } + } + } + const float d_energy = (_energy - energy)/(sw*sh*sd); + if (d_energy<=0 && -d_energy<_precision) break; + if (d_energy>0) dt*=0.5f; + energy = _energy; + } + } + return U; + } + + //! Compute correspondence map between two images, using the patch-match algorithm. + /** + \param patch_image The image containing the reference patches to match with the instance image. + \param patch_width Width of the patch used for matching. + \param patch_height Height of the patch used for matching. + \param patch_depth Depth of the patch used for matching. + \param nb_iterations Number of patch-match iterations. + \param nb_randoms Number of randomization attempts (per pixel). + \param guide Image used as the initial correspondence estimate for the algorithm. + 'guide' may have a last channel with boolean values (0=false | other=true) that + tells for each pixel if its correspondence vector is constrained to its initial value (constraint mask). + \param[out] matching_score Returned as the image of matching scores. + \note + The patch-match algorithm is described in this paper: + Connelly Barnes, Eli Shechtman, Adam Finkelstein, Dan B Goldman(2009), + PatchMatch: A Randomized Correspondence Algorithm for Structural Image Editing + **/ + template + CImg& patchmatch(const CImg& 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 &guide, + CImg &matching_score) { + return get_patchmatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,guide,matching_score).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \newinstance. + template + CImg get_patchmatch(const CImg& 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 &guide, + CImg &matching_score) const { + 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. + template + CImg& patchmatch(const CImg& 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 &guide) { + return get_patchmatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms,guide).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + template + CImg get_patchmatch(const CImg& 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 &guide) const { + return _patchmatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms, + guide,false,CImg::empty()); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + CImg& patchmatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth=1, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5) { + return get_patchmatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms).move_to(*this); + } + + //! Compute correspondence map between two images, using the patch-match algorithm \overloading. + CImg get_patchmatch(const CImg& patch_image, + const unsigned int patch_width, + const unsigned int patch_height, + const unsigned int patch_depth=1, + const unsigned int nb_iterations=5, + const unsigned int nb_randoms=5) const { + return _patchmatch(patch_image,patch_width,patch_height,patch_depth, + nb_iterations,nb_randoms, + CImg::const_empty(), + false,CImg::empty()); + } + + template + CImg _patchmatch(const CImg& 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 &guide, + const bool is_matching_score, + CImg &matching_score) const { + if (is_empty()) return CImg::const_empty(); + if (patch_image._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "patchmatch(): Instance image and specified patch image (%u,%u,%u,%u,%p) " + "have different spectrums.", + cimg_instance, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + if (patch_width>_width || patch_height>_height || patch_depth>_depth) + throw CImgArgumentException(_cimg_instance + "patchmatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the instance image.", + cimg_instance,patch_width,patch_height,patch_depth); + if (patch_width>patch_image._width || patch_height>patch_image._height || patch_depth>patch_image._depth) + throw CImgArgumentException(_cimg_instance + "patchmatch(): Specified patch size %ux%ux%u is bigger than the dimensions " + "of the patch image image (%u,%u,%u,%u,%p).", + cimg_instance,patch_width,patch_height,patch_depth, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + const unsigned int + _constraint = patch_image._depth>1?3:2, + constraint = guide._spectrum>_constraint?_constraint:0; + + if (guide && + (guide._width!=_width || guide._height!=_height || guide._depth!=_depth || guide._spectrum<_constraint)) + throw CImgArgumentException(_cimg_instance + "patchmatch(): Specified guide (%u,%u,%u,%u,%p) has invalid dimensions " + "considering instance and patch image image (%u,%u,%u,%u,%p).", + cimg_instance, + guide._width,guide._height,guide._depth,guide._spectrum,guide._data, + patch_image._width,patch_image._height,patch_image._depth,patch_image._spectrum, + patch_image._data); + + CImg map(_width,_height,_depth,patch_image._depth>1?3:2); + CImg score(_width,_height,_depth); + const int + psizew = (int)patch_width, psizew1 = psizew/2, psizew2 = psizew - psizew1 - 1, + psizeh = (int)patch_height, psizeh1 = psizeh/2, psizeh2 = psizeh - psizeh1 - 1, + psized = (int)patch_depth, psized1 = psized/2, psized2 = psized - psized1 - 1; + + if (_depth>1 || patch_image._depth>1) { // 3d version. + + // Initialize correspondence map. + if (guide) cimg_forXYZ(*this,x,y,z) { // User-defined initialization. + const int + cx1 = x<=psizew1?x:(x::inf()); + } else cimg_forXYZ(*this,x,y,z) { // Random initialization. + const int + cx1 = x<=psizew1?x:(x::inf()); + } + + // Start iteration loop. + for (unsigned int iter = 0; iter64 && iter0) { // Compare with left neighbor. + const int u = map(x - 1,y,z,0), v = map(x - 1,y,z,1), w = map(x - 1,y,z,2); + if (u>=cx1 - 1 && u=cy1 && v=cz1 && w0) { // Compare with up neighbor. + const int u = map(x,y - 1,z,0), v = map(x,y - 1,z,1), w = map(x,y - 1,z,2); + if (u>=cx1 && u=cy1 - 1 && v=cz1 && w0) { // Compare with backward neighbor. + const int u = map(x,y,z - 1,0), v = map(x,y,z - 1,1), w = map(x,y,z - 1,2); + if (u>=cx1 && u=cy1 && v=cz1 - 1 && w=cx1 + 1 && u=cy1 && v=cz1 && w=cx1 && u=cy1 + 1 && v=cz1 && w=cx1 && u=cy1 && v=cz1 + 1 && w::inf()); + } else cimg_forXY(*this,x,y) { // Random initialization. + const int + cx1 = x<=psizew1?x:(x::inf()); + } + + // Start iteration loop. + for (unsigned int iter = 0; iter64 && iter0) { // Compare with left neighbor. + const int u = map(x - 1,y,0), v = map(x - 1,y,1); + if (u>=cx1 - 1 && u=cy1 && v0) { // Compare with up neighbor. + const int u = map(x,y - 1,0), v = map(x,y - 1,1); + if (u>=cx1 && u=cy1 - 1 && v=cx1 + 1 && u=cy1 && v=cx1 && u=cy1 + 1 && v& img1, const CImg& img2, + const unsigned int psizew, const unsigned int psizeh, + const int x1, const int y1, + const int x2, const int y2, + const float max_ssd) { // 2d version. + const T *p1 = img1.data(x1,y1), *p2 = img2.data(x2,y2); + const ulongT + offx1 = (ulongT)img1._width - psizew, + offx2 = (ulongT)img2._width - psizew, + offy1 = (ulongT)img1._width*img1._height - psizeh*img1._width, + offy2 = (ulongT)img2._width*img2._height - psizeh*img2._width; + float ssd = 0; + cimg_forC(img1,c) { + for (unsigned int j = 0; jmax_ssd) return max_ssd; + p1+=offx1; p2+=offx2; + } + p1+=offy1; p2+=offy2; + } + return ssd; + } + + static float _patchmatch(const CImg& img1, const CImg& img2, + const unsigned int psizew, const unsigned int psizeh, const unsigned int psized, + const int x1, const int y1, const int z1, + const int x2, const int y2, const int z2, + const float max_ssd) { // 3d version. + const T *p1 = img1.data(x1,y1,z1), *p2 = img2.data(x2,y2,z2); + const ulongT + offx1 = (ulongT)img1._width - psizew, + offx2 = (ulongT)img2._width - psizew, + offy1 = (ulongT)img1._width*img1._height - psizeh*img1._width - psizew, + offy2 = (ulongT)img2._width*img2._height - psizeh*img2._width - psizew, + offz1 = (ulongT)img1._width*img1._height*img1._depth - psized*img1._width*img1._height - + psizeh*img1._width - psizew, + offz2 = (ulongT)img2._width*img2._height*img2._depth - psized*img2._width*img2._height - + psizeh*img2._width - psizew; + float ssd = 0; + cimg_forC(img1,c) { + for (unsigned int k = 0; kmax_ssd) return max_ssd; + p1+=offx1; p2+=offx2; + } + p1+=offy1; p2+=offy2; + } + p1+=offz1; p2+=offz2; + } + return ssd; + } + + //! Compute Euclidean distance function to a specified value. + /** + \param value Reference value. + \param metric Type of metric. Can be { 0=Chebyshev | 1=Manhattan | 2=Euclidean | 3=Squared-euclidean }. + \note + The distance transform implementation has been submitted by A. Meijster, and implements + the article 'W.H. Hesselink, A. Meijster, J.B.T.M. Roerdink, + "A general algorithm for computing distance transforms in linear time.", + In: Mathematical Morphology and its Applications to Image and Signal Processing, + J. Goutsias, L. Vincent, and D.S. Bloomberg (eds.), Kluwer, 2000, pp. 331-340.' + The submitted code has then been modified to fit CImg coding style and constraints. + **/ + CImg& distance(const T& value, const unsigned int metric=2) { + if (is_empty()) return *this; + if (cimg::type::string()!=cimg::type::string()) // For datatype < int. + return CImg(*this,false).distance((Tint)value,metric). + cut((Tint)cimg::type::min(),(Tint)cimg::type::max()).move_to(*this); + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,(T)0:(T)std::max(0,99999999); // (avoid VC++ warning) + if (!is_value) return fill(cimg::type::max()); + switch (metric) { + case 0 : return _distance_core(_distance_sep_cdt,_distance_dist_cdt); // Chebyshev. + case 1 : return _distance_core(_distance_sep_mdt,_distance_dist_mdt); // Manhattan. + case 3 : return _distance_core(_distance_sep_edt,_distance_dist_edt); // Squared Euclidean. + default : return _distance_core(_distance_sep_edt,_distance_dist_edt).sqrt(); // Euclidean. + } + return *this; + } + + //! Compute distance to a specified value \newinstance. + CImg get_distance(const T& value, const unsigned int metric=2) const { + return CImg(*this,false).distance((Tfloat)value,metric); + } + + static longT _distance_sep_edt(const longT i, const longT u, const longT *const g) { + return (u*u - i*i + g[u] - g[i])/(2*(u - i)); + } + + static longT _distance_dist_edt(const longT x, const longT i, const longT *const g) { + return (x - i)*(x - i) + g[i]; + } + + static longT _distance_sep_mdt(const longT i, const longT u, const longT *const g) { + return (u - i<=g[u] - g[i]?999999999:(g[u] - g[i] + u + i)/2); + } + + static longT _distance_dist_mdt(const longT x, const longT i, const longT *const g) { + return (x=0) && f(t[q],s[q],g)>f(t[q],u,g)) { --q; } + if (q<0) { q = 0; s[0] = u; } + else { const longT w = 1 + sep(s[q], u, g); if (w<(longT)len) { ++q; s[q] = u; t[q] = w; }} + } + for (int u = (int)len - 1; u>=0; --u) { dt[u] = f(u,s[q],g); if (u==t[q]) --q; } // Backward scan. + } + + CImg& _distance_core(longT (*const sep)(const longT, const longT, const longT *const), + longT (*const f)(const longT, const longT, const longT *const)) { + // Check for g++ 4.9.X, as OpenMP seems to crash for this particular function. I have no clues why. +#define cimg_is_gcc49x (__GNUC__==4 && __GNUC_MINOR__==9) + + const ulongT wh = (ulongT)_width*_height; +#if defined(cimg_use_openmp) && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) +#endif + cimg_forC(*this,c) { + CImg g(_width), dt(_width), s(_width), t(_width); + CImg img = get_shared_channel(c); +#if defined(cimg_use_openmp) && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_width>=512 && _height*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forYZ(*this,y,z) { // Over X-direction. + cimg_forX(*this,x) g[x] = (longT)img(x,y,z,0,wh); + _distance_scan(_width,g,sep,f,s,t,dt); + cimg_forX(*this,x) img(x,y,z,0,wh) = (T)dt[x]; + } + if (_height>1) { + g.assign(_height); dt.assign(_height); s.assign(_height); t.assign(_height); +#if defined(cimg_use_openmp) && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_height>=512 && _width*_depth>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXZ(*this,x,z) { // Over Y-direction. + cimg_forY(*this,y) g[y] = (longT)img(x,y,z,0,wh); + _distance_scan(_height,g,sep,f,s,t,dt); + cimg_forY(*this,y) img(x,y,z,0,wh) = (T)dt[y]; + } + } + if (_depth>1) { + g.assign(_depth); dt.assign(_depth); s.assign(_depth); t.assign(_depth); +#if defined(cimg_use_openmp) && !cimg_is_gcc49x + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if(_depth>=512 && _width*_height>=16) + firstprivate(g,dt,s,t)) +#endif + cimg_forXY(*this,x,y) { // Over Z-direction. + cimg_forZ(*this,z) g[z] = (longT)img(x,y,z,0,wh); + _distance_scan(_depth,g,sep,f,s,t,dt); + cimg_forZ(*this,z) img(x,y,z,0,wh) = (T)dt[z]; + } + } + } + return *this; + } + + //! Compute chamfer distance to a specified value, with a custom metric. + /** + \param value Reference value. + \param metric_mask Metric mask. + \note The algorithm code has been initially proposed by A. Meijster, and modified by D. Tschumperlé. + **/ + template + CImg& distance(const T& value, const CImg& metric_mask) { + if (is_empty()) return *this; + bool is_value = false; + cimg_for(*this,ptr,T) *ptr = *ptr==value?is_value=true,0:(T)999999999; + if (!is_value) return fill(cimg::type::max()); + const ulongT wh = (ulongT)_width*_height; + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2)) + cimg_forC(*this,c) { + CImg img = get_shared_channel(c); + cimg_pragma_openmp(parallel for collapse(3) cimg_openmp_if(_width*_height*_depth>=1024)) + cimg_forXYZ(metric_mask,dx,dy,dz) { + const t weight = metric_mask(dx,dy,dz); + if (weight) { + for (int z = dz, nz = 0; z=0; --z,--nz) { // Backward scan. + for (int y = height() - 1 - dy, ny = height() - 1; y>=0; --y,--ny) { + for (int x = width() - 1 - dx, nx = width() - 1; x>=0; --x,--nx) { + const T dd = img(nx,ny,nz,0,wh) + weight; + if (dd + CImg get_distance(const T& value, const CImg& metric_mask) const { + return CImg(*this,false).distance(value,metric_mask); + } + + //! Compute distance to a specified value, according to a custom metric (use dijkstra algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + \param is_high_connectivity Tells if the algorithm uses low or high connectivity. + **/ + template + CImg& distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) { + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm) \newinstance. + template + CImg::type> + get_distance_dijkstra(const T& value, const CImg& metric, const bool is_high_connectivity, + CImg& return_path) const { + if (is_empty()) return return_path.assign(); + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_dijkstra(): image instance and metric map (%u,%u,%u,%u) " + "have incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + typedef typename cimg::superset::type td; // Type used for computing cumulative distances. + CImg result(_width,_height,_depth,_spectrum), Q; + CImg is_queued(_width,_height,_depth,1); + if (return_path) return_path.assign(_width,_height,_depth,_spectrum); + + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + CImg path = return_path?return_path.get_shared_channel(c):CImg(); + unsigned int sizeQ = 0; + + // Detect initial seeds. + is_queued.fill(0); + cimg_forXYZ(img,x,y,z) if (img(x,y,z)==value) { + Q._priority_queue_insert(is_queued,sizeQ,0,x,y,z); + res(x,y,z) = 0; + if (path) path(x,y,z) = (to)0; + } + + // Start distance propagation. + while (sizeQ) { + + // Get and remove point with minimal potential from the queue. + const int x = (int)Q(0,1), y = (int)Q(0,2), z = (int)Q(0,3); + const td P = (td)-Q(0,0); + Q._priority_queue_remove(sizeQ); + + // Update neighbors. + td npot = 0; + if (x - 1>=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x - 1,y,z) + P),x - 1,y,z)) { + res(x - 1,y,z) = npot; if (path) path(x - 1,y,z) = (to)2; + } + if (x + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y - 1,z) + P),x,y - 1,z)) { + res(x,y - 1,z) = npot; if (path) path(x,y - 1,z) = (to)8; + } + if (y + 1=0 && Q._priority_queue_insert(is_queued,sizeQ,-(npot=met(x,y,z - 1) + P),x,y,z - 1)) { + res(x,y,z - 1) = npot; if (path) path(x,y,z - 1) = (to)32; + } + if (z + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y - 1,z) + P)),x - 1,y - 1,z)) { + res(x - 1,y - 1,z) = npot; if (path) path(x - 1,y - 1,z) = (to)10; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x + 1,y - 1,z) + P)),x + 1,y - 1,z)) { + res(x + 1,y - 1,z) = npot; if (path) path(x + 1,y - 1,z) = (to)9; + } + if (x - 1>=0 && y + 1=0) { // Diagonal neighbors on slice z - 1. + if (x - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z - 1) + P)),x - 1,y,z - 1)) { + res(x - 1,y,z - 1) = npot; if (path) path(x - 1,y,z - 1) = (to)34; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z - 1) + P)),x,y - 1,z - 1)) { + res(x,y - 1,z - 1) = npot; if (path) path(x,y - 1,z - 1) = (to)40; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z - 1) + P)), + x - 1,y - 1,z - 1)) { + res(x - 1,y - 1,z - 1) = npot; if (path) path(x - 1,y - 1,z - 1) = (to)42; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z - 1) + P)), + x + 1,y - 1,z - 1)) { + res(x + 1,y - 1,z - 1) = npot; if (path) path(x + 1,y - 1,z - 1) = (to)41; + } + if (x - 1>=0 && y + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x - 1,y,z + 1) + P)),x - 1,y,z + 1)) { + res(x - 1,y,z + 1) = npot; if (path) path(x - 1,y,z + 1) = (to)18; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt2*met(x,y - 1,z + 1) + P)),x,y - 1,z + 1)) { + res(x,y - 1,z + 1) = npot; if (path) path(x,y - 1,z + 1) = (to)24; + } + if (y + 1=0 && y - 1>=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x - 1,y - 1,z + 1) + P)), + x - 1,y - 1,z + 1)) { + res(x - 1,y - 1,z + 1) = npot; if (path) path(x - 1,y - 1,z + 1) = (to)26; + } + if (x + 1=0 && + Q._priority_queue_insert(is_queued,sizeQ,-(npot=(td)(sqrt3*met(x + 1,y - 1,z + 1) + P)), + x + 1,y - 1,z + 1)) { + res(x + 1,y - 1,z + 1) = npot; if (path) path(x + 1,y - 1,z + 1) = (to)25; + } + if (x - 1>=0 && y + 1 + CImg& distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) { + return get_distance_dijkstra(value,metric,is_high_connectivity).move_to(*this); + } + + //! Compute distance map to a specified value, according to a custom metric (use dijkstra algorithm). \newinstance. + template + CImg get_distance_dijkstra(const T& value, const CImg& metric, + const bool is_high_connectivity=false) const { + CImg return_path; + return get_distance_dijkstra(value,metric,is_high_connectivity,return_path); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + /** + \param value Reference value. + \param metric Field of distance potentials. + **/ + template + CImg& distance_eikonal(const T& value, const CImg& metric) { + return get_distance_eikonal(value,metric).move_to(*this); + } + + //! Compute distance map to one source point, according to a custom metric (use fast marching algorithm). + template + CImg get_distance_eikonal(const T& value, const CImg& metric) const { + if (is_empty()) return *this; + if (!is_sameXYZ(metric)) + throw CImgArgumentException(_cimg_instance + "distance_eikonal(): image instance and metric map (%u,%u,%u,%u) have " + "incompatible dimensions.", + cimg_instance, + metric._width,metric._height,metric._depth,metric._spectrum); + CImg result(_width,_height,_depth,_spectrum,cimg::type::max()), Q; + CImg state(_width,_height,_depth); // -1=far away, 0=narrow, 1=frozen. + + cimg_pragma_openmp(parallel for cimg_openmp_if(_spectrum>=2) firstprivate(Q,state)) + cimg_forC(*this,c) { + const CImg img = get_shared_channel(c); + const CImg met = metric.get_shared_channel(c%metric._spectrum); + CImg res = result.get_shared_channel(c); + unsigned int sizeQ = 0; + state.fill(-1); + + // Detect initial seeds. + Tfloat *ptr1 = res._data; char *ptr2 = state._data; + cimg_for(img,ptr0,T) { if (*ptr0==value) { *ptr1 = 0; *ptr2 = 1; } ++ptr1; ++ptr2; } + + // Initialize seeds neighbors. + ptr2 = state._data; + cimg_forXYZ(img,x,y,z) if (*(ptr2++)==1) { + if (x - 1>=0 && state(x - 1,y,z)==-1) { + const Tfloat dist = res(x - 1,y,z) = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x - 1,y,z); + } + if (x + 1=0 && state(x,y - 1,z)==-1) { + const Tfloat dist = res(x,y - 1,z) = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y - 1,z); + } + if (y + 1=0 && state(x,y,z - 1)==-1) { + const Tfloat dist = res(x,y,z - 1) = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + Q._eik_priority_queue_insert(state,sizeQ,-dist,x,y,z - 1); + } + if (z + 1=0) { + if (x - 1>=0 && state(x - 1,y,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x - 1,y,z),x - 1,y,z); + if (dist=0 && state(x,y - 1,z)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y - 1,z),x,y - 1,z); + if (dist=0 && state(x,y,z - 1)!=1) { + const Tfloat dist = __distance_eikonal(res,met(x,y,z - 1),x,y,z - 1); + if (dist& res, const Tfloat P, + const int x=0, const int y=0, const int z=0) const { + const Tfloat M = (Tfloat)cimg::type::max(); + T T1 = (T)std::min(x - 1>=0?res(x - 1,y,z):M,x + 11) { // 3d. + T + T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1=0?res(x,y,z - 1):M,z + 1T2) cimg::swap(T1,T2); + if (T2>T3) cimg::swap(T2,T3); + if (T1>T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T31) { // 2d. + T T2 = (T)std::min(y - 1>=0?res(x,y - 1,z):M,y + 1T2) cimg::swap(T1,T2); + if (P<=0) return (Tfloat)T1; + if (T2 + void _eik_priority_queue_insert(CImg& state, unsigned int& siz, const t value, + const unsigned int x, const unsigned int y, const unsigned int z) { + if (state(x,y,z)>0) return; + state(x,y,z) = 0; + if (++siz>=_width) { if (!is_empty()) resize(_width*2,4,1,1,0); else assign(64,4); } + (*this)(siz - 1,0) = (T)value; (*this)(siz - 1,1) = (T)x; (*this)(siz - 1,2) = (T)y; (*this)(siz - 1,3) = (T)z; + for (unsigned int pos = siz - 1, par = 0; pos && value>(*this)(par=(pos + 1)/2 - 1,0); pos = par) { + cimg::swap((*this)(pos,0),(*this)(par,0)); cimg::swap((*this)(pos,1),(*this)(par,1)); + cimg::swap((*this)(pos,2),(*this)(par,2)); cimg::swap((*this)(pos,3),(*this)(par,3)); + } + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE. + /** + \param nb_iterations Number of PDE iterations. + \param band_size Size of the narrow band. + \param time_step Time step of the PDE iterations. + **/ + CImg& distance_eikonal(const unsigned int nb_iterations, const float band_size=0, const float time_step=0.5f) { + if (is_empty()) return *this; + CImg velocity(*this); + for (unsigned int iteration = 0; iteration1) { // 3d + CImg_3x3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3x3(*this,x,y,z,c,I,Tfloat) if (band_size<=0 || cimg::abs(Iccc)0?(Incc - Iccc):(Iccc - Ipcc), + iy = gy*sgn>0?(Icnc - Iccc):(Iccc - Icpc), + iz = gz*sgn>0?(Iccn - Iccc):(Iccc - Iccp), + ng = 1e-5f + cimg::hypot(gx,gy,gz), + ngx = gx/ng, + ngy = gy/ng, + ngz = gz/ng, + veloc = sgn*(ngx*ix + ngy*iy + ngz*iz - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } else { // 2d version + CImg_3x3(I,Tfloat); + cimg_forC(*this,c) cimg_for3x3(*this,x,y,0,c,I,Tfloat) if (band_size<=0 || cimg::abs(Icc)0?(Inc - Icc):(Icc - Ipc), + iy = gy*sgn>0?(Icn - Icc):(Icc - Icp), + ng = std::max((Tfloat)1e-5,cimg::hypot(gx,gy)), + ngx = gx/ng, + ngy = gy/ng, + veloc = sgn*(ngx*ix + ngy*iy - 1); + *(ptrd++) = veloc; + if (veloc>veloc_max) veloc_max = veloc; else if (-veloc>veloc_max) veloc_max = -veloc; + } else *(ptrd++) = 0; + } + if (veloc_max>0) *this+=(velocity*=time_step/veloc_max); + } + return *this; + } + + //! Compute distance function to 0-valued isophotes, using the Eikonal PDE \newinstance. + CImg get_distance_eikonal(const unsigned int nb_iterations, const float band_size=0, + const float time_step=0.5f) const { + return CImg(*this,false).distance_eikonal(nb_iterations,band_size,time_step); + } + + //! Compute Haar multiscale wavelet transform. + /** + \param axis Axis considered for the transform. + \param invert Set inverse of direct transform. + \param nb_scales Number of scales used for the transform. + **/ + CImg& haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(axis,invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const { + if (is_empty() || !nb_scales) return +*this; + CImg res; + const Tfloat sqrt2 = std::sqrt(2.0f); + if (nb_scales==1) { + switch (cimg::lowercase(axis)) { // Single scale transform + case 'x' : { + const unsigned int w = _width/2; + if (w) { + if ((w%2) && w!=1) + throw CImgInstanceException(_cimg_instance + "haar(): Sub-image width %u is not even.", + cimg_instance, + w); + + res.assign(_width,_height,_depth,_spectrum); + if (invert) cimg_forYZC(*this,y,z,c) { // Inverse transform along X + for (unsigned int x = 0, xw = w, x2 = 0; x& haar(const bool invert=false, const unsigned int nb_scales=1) { + return get_haar(invert,nb_scales).move_to(*this); + } + + //! Compute Haar multiscale wavelet transform \newinstance. + CImg get_haar(const bool invert=false, const unsigned int nb_scales=1) const { + CImg res; + if (nb_scales==1) { // Single scale transform + if (_width>1) get_haar('x',invert,1).move_to(res); + if (_height>1) { if (res) res.haar('y',invert,1); else get_haar('y',invert,1).move_to(res); } + if (_depth>1) { if (res) res.haar('z',invert,1); else get_haar('z',invert,1).move_to(res); } + if (res) return res; + } else { // Multi-scale transform + if (invert) { // Inverse transform + res.assign(*this); + if (_width>1) { + if (_height>1) { + if (_depth>1) { + unsigned int w = _width, h = _height, d = _depth; + for (unsigned int s = 1; w && h && d && s1) { + unsigned int w = _width, d = _depth; + for (unsigned int s = 1; w && d && s1) { + if (_depth>1) { + unsigned int h = _height, d = _depth; + for (unsigned int s = 1; h && d && s1) { + unsigned int d = _depth; + for (unsigned int s = 1; d && s1) { + if (_height>1) { + if (_depth>1) + for (unsigned int s = 1, w = _width/2, h = _height/2, d = _depth/2; w && h && d && s1) for (unsigned int s = 1, w = _width/2, d = _depth/2; w && d && s1) { + if (_depth>1) + for (unsigned int s = 1, h = _height/2, d = _depth/2; h && d && s1) for (unsigned int s = 1, d = _depth/2; d && s get_FFT(const char axis, const bool is_invert=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],axis,is_invert); + return res; + } + + //! Compute n-d Fast Fourier Transform. + /* + \param is_invert Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + CImgList get_FFT(const bool is_invert=false) const { + CImgList res(*this,CImg()); + CImg::FFT(res[0],res[1],is_invert); + return res; + } + + //! Compute 1d Fast Fourier Transform, along a specified axis. + /** + \param[in,out] real Real part of the pixel values. + \param[in,out] imag Imaginary part of the pixel values. + \param axis Axis along which the FFT is computed. + \param is_invert Tells if the forward (\c false) or inverse (\c true) FFT is computed. + **/ + static void FFT(CImg& real, CImg& imag, const char axis, const bool is_invert=false) { + if (!real) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part is empty.", + pixel_type()); + + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImg<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); +#ifdef cimg_use_fftw3 + cimg::mutex(12); + fftw_complex *data_in; + fftw_plan data_plan; + + switch (cimg::lowercase(axis)) { + case 'x' : { // Fourier along X, using FFTW library. + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width); + if (!data_in) throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u) along the X-axis.", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width), + real._width,real._height,real._depth,real._spectrum); + + data_plan = fftw_plan_dft_1d(real._width,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forYZC(real,y,z,c) { + T *ptrr = real.data(0,y,z,c), *ptri = imag.data(0,y,z,c); + double *ptrd = (double*)data_in; + cimg_forX(real,x) { *(ptrd++) = (double)*(ptrr++); *(ptrd++) = (double)*(ptri++); } + fftw_execute(data_plan); + const unsigned int fact = real._width; + if (is_invert) cimg_forX(real,x) { *(--ptri) = (T)(*(--ptrd)/fact); *(--ptrr) = (T)(*(--ptrd)/fact); } + else cimg_forX(real,x) { *(--ptri) = (T)*(--ptrd); *(--ptrr) = (T)*(--ptrd); } + } + } break; + case 'y' : { // Fourier along Y, using FFTW library. + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * real._height); + if (!data_in) throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u) along the Y-axis.", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._height), + real._width,real._height,real._depth,real._spectrum); + + data_plan = fftw_plan_dft_1d(real._height,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + const unsigned int off = real._width; + cimg_forXZC(real,x,z,c) { + T *ptrr = real.data(x,0,z,c), *ptri = imag.data(x,0,z,c); + double *ptrd = (double*)data_in; + cimg_forY(real,y) { *(ptrd++) = (double)*ptrr; *(ptrd++) = (double)*ptri; ptrr+=off; ptri+=off; } + fftw_execute(data_plan); + const unsigned int fact = real._height; + if (is_invert) + cimg_forY(real,y) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); } + else cimg_forY(real,y) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); } + } + } break; + case 'z' : { // Fourier along Z, using FFTW library. + data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * real._depth); + if (!data_in) throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u) along the Z-axis.", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._depth), + real._width,real._height,real._depth,real._spectrum); + + data_plan = fftw_plan_dft_1d(real._depth,data_in,data_in,is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + const ulongT off = (ulongT)real._width*real._height; + cimg_forXYC(real,x,y,c) { + T *ptrr = real.data(x,y,0,c), *ptri = imag.data(x,y,0,c); + double *ptrd = (double*)data_in; + cimg_forZ(real,z) { *(ptrd++) = (double)*ptrr; *(ptrd++) = (double)*ptri; ptrr+=off; ptri+=off; } + fftw_execute(data_plan); + const unsigned int fact = real._depth; + if (is_invert) + cimg_forZ(real,z) { ptrr-=off; ptri-=off; *ptri = (T)(*(--ptrd)/fact); *ptrr = (T)(*(--ptrd)/fact); } + else cimg_forZ(real,z) { ptrr-=off; ptri-=off; *ptri = (T)*(--ptrd); *ptrr = (T)*(--ptrd); } + } + } break; + default : + throw CImgArgumentException("CImgList<%s>::FFT(): Invalid specified axis '%c' for real and imaginary parts " + "(%u,%u,%u,%u) " + "(should be { x | y | z }).", + pixel_type(),axis, + real._width,real._height,real._depth,real._spectrum); + } + fftw_destroy_plan(data_plan); + fftw_free(data_in); + cimg::mutex(12,0); +#else + switch (cimg::lowercase(axis)) { + case 'x' : { // Fourier along X, using built-in functions. + const unsigned int N = real._width, N2 = N>>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the X-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forYZC(real,y,z,c) { + cimg::swap(real(i,y,z,c),real(j,y,z,c)); + cimg::swap(imag(i,y,z,c),imag(j,y,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = delta>>1; + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Y-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXZC(real,x,z,c) { + cimg::swap(real(x,i,z,c),real(x,j,z,c)); + cimg::swap(imag(x,i,z,c),imag(x,j,z,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i>1; + if (((N - 1)&N) && N!=1) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) " + "have non 2^N dimension along the Z-axis.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum); + + for (unsigned int i = 0, j = 0; ii) cimg_forXYC(real,x,y,c) { + cimg::swap(real(x,y,i,c),real(x,y,j,c)); + cimg::swap(imag(x,y,i,c),imag(x,y,j,c)); + if (j=m; j-=m, m = n, n>>=1) {} + } + for (unsigned int delta = 2; delta<=N; delta<<=1) { + const unsigned int delta2 = (delta>>1); + for (unsigned int i = 0; i::FFT(): Invalid specified axis '%c' for real and imaginary parts " + "(%u,%u,%u,%u) " + "(should be { x | y | z }).", + pixel_type(),axis, + real._width,real._height,real._depth,real._spectrum); + } +#endif + } + + //! Compute n-d Fast Fourier Transform. + /** + \param[in,out] real Real part of the pixel values. + \param[in,out] imag Imaginary part of the pixel values. + \param is_invert Tells if the forward (\c false) or inverse (\c true) FFT is computed. + \param nb_threads Number of parallel threads used for the computation. + Use \c 0 to set this to the number of available cpus. + **/ + static void FFT(CImg& real, CImg& imag, const bool is_invert=false, const unsigned int nb_threads=0) { + if (!real) + throw CImgInstanceException("CImgList<%s>::FFT(): Empty specified real part.", + pixel_type()); + + if (!imag) imag.assign(real._width,real._height,real._depth,real._spectrum,(T)0); + if (!real.is_sameXYZC(imag)) + throw CImgInstanceException("CImgList<%s>::FFT(): Specified real part (%u,%u,%u,%u,%p) and " + "imaginary part (%u,%u,%u,%u,%p) have different dimensions.", + pixel_type(), + real._width,real._height,real._depth,real._spectrum,real._data, + imag._width,imag._height,imag._depth,imag._spectrum,imag._data); + +#ifdef cimg_use_fftw3 + cimg::mutex(12); +#ifndef cimg_use_fftw3_singlethread + const unsigned int _nb_threads = nb_threads?nb_threads:cimg::nb_cpus(); + static int fftw_st = fftw_init_threads(); + cimg::unused(fftw_st); + fftw_plan_with_nthreads(_nb_threads); +#else + cimg::unused(nb_threads); +#endif + fftw_complex *data_in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*real._width*real._height*real._depth); + if (!data_in) throw CImgInstanceException("CImgList<%s>::FFT(): Failed to allocate memory (%s) " + "for computing FFT of image (%u,%u,%u,%u).", + pixel_type(), + cimg::strbuffersize(sizeof(fftw_complex)*real._width* + real._height*real._depth*real._spectrum), + real._width,real._height,real._depth,real._spectrum); + + fftw_plan data_plan; + const ulongT w = (ulongT)real._width, wh = w*real._height, whd = wh*real._depth; + data_plan = fftw_plan_dft_3d(real._width,real._height,real._depth,data_in,data_in, + is_invert?FFTW_BACKWARD:FFTW_FORWARD,FFTW_ESTIMATE); + cimg_forC(real,c) { + T *ptrr = real.data(0,0,0,c), *ptri = imag.data(0,0,0,c); + double *ptrd = (double*)data_in; + for (unsigned int x = 0; x1) FFT(real,imag,'z',is_invert); + if (real._height>1) FFT(real,imag,'y',is_invert); + if (real._width>1) FFT(real,imag,'x',is_invert); +#endif + } + + //@} + //------------------------------------- + // + //! \name 3d Objects Management + //@{ + //------------------------------------- + + //! Shift 3d object's vertices. + /** + \param tx X-coordinate of the 3d displacement vector. + \param ty Y-coordinate of the 3d displacement vector. + \param tz Z-coordinate of the 3d displacement vector. + **/ + CImg& shift_object3d(const float tx, const float ty=0, const float tz=0) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3d vertices.", + cimg_instance); + + get_shared_row(0)+=tx; get_shared_row(1)+=ty; get_shared_row(2)+=tz; + return *this; + } + + //! Shift 3d object's vertices \newinstance. + CImg get_shift_object3d(const float tx, const float ty=0, const float tz=0) const { + return CImg(*this,false).shift_object3d(tx,ty,tz); + } + + //! Shift 3d object's vertices, so that it becomes centered. + /** + \note The object center is computed as its barycenter. + **/ + CImg& shift_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "shift_object3d(): Instance is not a set of 3d vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + xcoords-=(xm + xM)/2; ycoords-=(ym + yM)/2; zcoords-=(zm + zM)/2; + return *this; + } + + //! Shift 3d object's vertices, so that it becomes centered \newinstance. + CImg get_shift_object3d() const { + return CImg(*this,false).shift_object3d(); + } + + //! Resize 3d object. + /** + \param sx Width of the 3d object's bounding box. + \param sy Height of the 3d object's bounding box. + \param sz Depth of the 3d object's bounding box. + **/ + CImg& resize_object3d(const float sx, const float sy=-100, const float sz=-100) { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3d vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + if (xm0) xcoords*=sx/(xM-xm); else xcoords*=-sx/100; } + if (ym0) ycoords*=sy/(yM-ym); else ycoords*=-sy/100; } + if (zm0) zcoords*=sz/(zM-zm); else zcoords*=-sz/100; } + return *this; + } + + //! Resize 3d object \newinstance. + CImg get_resize_object3d(const float sx, const float sy=-100, const float sz=-100) const { + return CImg(*this,false).resize_object3d(sx,sy,sz); + } + + //! Resize 3d object to unit size. + CImg resize_object3d() { + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "resize_object3d(): Instance is not a set of 3d vertices.", + cimg_instance); + + CImg xcoords = get_shared_row(0), ycoords = get_shared_row(1), zcoords = get_shared_row(2); + float + xm, xM = (float)xcoords.max_min(xm), + ym, yM = (float)ycoords.max_min(ym), + zm, zM = (float)zcoords.max_min(zm); + const float dx = xM - xm, dy = yM - ym, dz = zM - zm, dmax = cimg::max(dx,dy,dz); + if (dmax>0) { xcoords/=dmax; ycoords/=dmax; zcoords/=dmax; } + return *this; + } + + //! Resize 3d object to unit size \newinstance. + CImg get_resize_object3d() const { + return CImg(*this,false).resize_object3d(); + } + + //! Merge two 3d objects together. + /** + \param[in,out] primitives Primitives data of the current 3d object. + \param obj_vertices Vertices data of the additional 3d object. + \param obj_primitives Primitives data of the additional 3d object. + **/ + template + CImg& append_object3d(CImgList& primitives, const CImg& obj_vertices, + const CImgList& obj_primitives) { + if (!obj_vertices || !obj_primitives) return *this; + if (obj_vertices._height!=3 || obj_vertices._depth>1 || obj_vertices._spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Specified vertice image (%u,%u,%u,%u,%p) is not a " + "set of 3d vertices.", + cimg_instance, + obj_vertices._width,obj_vertices._height, + obj_vertices._depth,obj_vertices._spectrum,obj_vertices._data); + + if (is_empty()) { primitives.assign(obj_primitives); return assign(obj_vertices); } + if (_height!=3 || _depth>1 || _spectrum>1) + throw CImgInstanceException(_cimg_instance + "append_object3d(): Instance is not a set of 3d vertices.", + cimg_instance); + + const unsigned int P = _width; + append(obj_vertices,'x'); + const unsigned int N = primitives._width; + primitives.insert(obj_primitives); + for (unsigned int i = N; i &p = primitives[i]; + switch (p.size()) { + case 1 : p[0]+=P; break; // Point. + case 5 : p[0]+=P; p[1]+=P; break; // Sphere. + case 2 : case 6 : p[0]+=P; p[1]+=P; break; // Segment. + case 3 : case 9 : p[0]+=P; p[1]+=P; p[2]+=P; break; // Triangle. + case 4 : case 12 : p[0]+=P; p[1]+=P; p[2]+=P; p[3]+=P; break; // Rectangle. + } + } + return *this; + } + + //! Texturize primitives of a 3d object. + /** + \param[in,out] primitives Primitives data of the 3d object. + \param[in,out] colors Colors data of the 3d object. + \param texture Texture image to map to 3d object. + \param coords Texture-mapping coordinates. + **/ + template + const CImg& texturize_object3d(CImgList& primitives, CImgList& colors, + const CImg& texture, const CImg& coords=CImg::const_empty()) const { + if (is_empty()) return *this; + if (_height!=3) + throw CImgInstanceException(_cimg_instance + "texturize_object3d(): image instance is not a set of 3d points.", + cimg_instance); + if (coords && (coords._width!=_width || coords._height!=2)) + throw CImgArgumentException(_cimg_instance + "texturize_object3d(): Invalid specified texture coordinates (%u,%u,%u,%u,%p).", + cimg_instance, + coords._width,coords._height,coords._depth,coords._spectrum,coords._data); + CImg _coords; + if (!coords) { // If no texture coordinates specified, do a default XY-projection. + _coords.assign(_width,2); + float + xmin, xmax = (float)get_shared_row(0).max_min(xmin), + ymin, ymax = (float)get_shared_row(1).max_min(ymin), + dx = xmax>xmin?xmax-xmin:1, + dy = ymax>ymin?ymax-ymin:1; + cimg_forX(*this,p) { + _coords(p,0) = (int)(((*this)(p,0) - xmin)*texture._width/dx); + _coords(p,1) = (int)(((*this)(p,1) - ymin)*texture._height/dy); + } + } else _coords = coords; + + int texture_ind = -1; + cimglist_for(primitives,l) { + CImg &p = primitives[l]; + const unsigned int siz = p.size(); + switch (siz) { + case 1 : { // Point. + const unsigned int i0 = (unsigned int)p[0]; + const int x0 = _coords(i0,0), y0 = _coords(i0,1); + texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0).move_to(colors[l]); + } break; + case 2 : case 6 : { // Line. + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,x0,y0,x1,y1).move_to(p); + } break; + case 3 : case 9 : { // Triangle. + const unsigned int i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,x0,y0,x1,y1,x2,y2).move_to(p); + } break; + case 4 : case 12 : { // Quadrangle. + const unsigned int + i0 = (unsigned int)p[0], i1 = (unsigned int)p[1], i2 = (unsigned int)p[2], i3 = (unsigned int)p[3]; + const int + x0 = _coords(i0,0), y0 = _coords(i0,1), + x1 = _coords(i1,0), y1 = _coords(i1,1), + x2 = _coords(i2,0), y2 = _coords(i2,1), + x3 = _coords(i3,0), y3 = _coords(i3,1); + if (texture_ind<0) colors[texture_ind=l].assign(texture,false); + else colors[l].assign(colors[texture_ind],true); + CImg::vector(i0,i1,i2,i3,x0,y0,x1,y1,x2,y2,x3,y3).move_to(p); + } break; + } + } + return *this; + } + + //! Generate a 3d elevation of the image instance. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param[out] colors The returned list of the 3d object colors. + \param elevation The input elevation map. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + CImgList colors3d; + const CImg points3d = img.get_elevation3d(faces3d,colors3d,img.get_norm()*0.2); + CImg().display_object3d("Elevation3d",points3d,faces3d,colors3d); + \endcode + \image html ref_elevation3d.jpg + **/ + template + CImg get_elevation3d(CImgList& primitives, CImgList& colors, const CImg& elevation) const { + if (!is_sameXY(elevation) || elevation._depth>1 || elevation._spectrum>1) + throw CImgArgumentException(_cimg_instance + "get_elevation3d(): Instance and specified elevation (%u,%u,%u,%u,%p) " + "have incompatible dimensions.", + cimg_instance, + elevation._width,elevation._height,elevation._depth, + elevation._spectrum,elevation._data); + if (is_empty()) return *this; + float m, M = (float)max_min(m); + if (M==m) ++M; + colors.assign(); + const unsigned int size_x1 = _width - 1, size_y1 = _height - 1; + for (unsigned int y = 0; y1?((*this)(x,y,1) - m)*255/(M-m):r), + b = (unsigned char)(_spectrum>2?((*this)(x,y,2) - m)*255/(M-m):_spectrum>1?0:r); + CImg::vector((tc)r,(tc)g,(tc)b).move_to(colors); + } + const typename CImg::_functor2d_int func(elevation); + return elevation3d(primitives,func,0,0,_width - 1.0f,_height - 1.0f,_width,_height); + } + + //! Generate the 3d projection planes of the image instance. + /** + \param[out] primitives Primitives data of the returned 3d object. + \param[out] colors Colors data of the returned 3d object. + \param x0 X-coordinate of the projection point. + \param y0 Y-coordinate of the projection point. + \param z0 Z-coordinate of the projection point. + \param normalize_colors Tells if the created textures have normalized colors. + **/ + template + CImg get_projections3d(CImgList& primitives, CImgList& colors, + const unsigned int x0, const unsigned int y0, const unsigned int z0, + const bool normalize_colors=false) const { + float m = 0, M = 0, delta = 1; + if (normalize_colors) { m = (float)min_max(M); delta = 255/(m==M?1:M-m); } + const unsigned int + _x0 = (x0>=_width)?_width - 1:x0, + _y0 = (y0>=_height)?_height - 1:y0, + _z0 = (z0>=_depth)?_depth - 1:z0; + CImg img_xy, img_xz, img_yz; + if (normalize_colors) { + ((get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1)-=m)*=delta).move_to(img_xy); + ((get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_width,_depth,1,-100,-1). + move_to(img_xz); + ((get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1)-=m)*=delta).resize(_height,_depth,1,-100,-1). + move_to(img_yz); + } else { + get_crop(0,0,_z0,0,_width - 1,_height - 1,_z0,_spectrum - 1).move_to(img_xy); + get_crop(0,_y0,0,0,_width - 1,_y0,_depth - 1,_spectrum - 1).resize(_width,_depth,1,-100,-1).move_to(img_xz); + get_crop(_x0,0,0,0,_x0,_height - 1,_depth - 1,_spectrum - 1).resize(_height,_depth,1,-100,-1).move_to(img_yz); + } + CImg points(12,3,1,1, + 0,_width - 1,_width - 1,0, 0,_width - 1,_width - 1,0, _x0,_x0,_x0,_x0, + 0,0,_height - 1,_height - 1, _y0,_y0,_y0,_y0, 0,_height - 1,_height - 1,0, + _z0,_z0,_z0,_z0, 0,0,_depth - 1,_depth - 1, 0,0,_depth - 1,_depth - 1); + primitives.assign(); + CImg::vector(0,1,2,3,0,0,img_xy._width - 1,0,img_xy._width - 1,img_xy._height - 1,0,img_xy._height - 1). + move_to(primitives); + CImg::vector(4,5,6,7,0,0,img_xz._width - 1,0,img_xz._width - 1,img_xz._height - 1,0,img_xz._height - 1). + move_to(primitives); + CImg::vector(8,9,10,11,0,0,img_yz._width - 1,0,img_yz._width - 1,img_yz._height - 1,0,img_yz._height - 1). + move_to(primitives); + colors.assign(); + img_xy.move_to(colors); + img_xz.move_to(colors); + img_yz.move_to(colors); + return points; + } + + //! Generate a isoline of the image instance as a 3d object. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3d object colors. + \param size_x The number of subdivisions along the X-axis. + \param size_y The number of subdisivions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img("reference.jpg"); + CImgList faces3d; + const CImg points3d = img.get_isoline3d(faces3d,100); + CImg().display_object3d("Isoline3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isoline3d.jpg + **/ + template + CImg get_isoline3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a scalar image.", + cimg_instance); + if (_depth>1) + throw CImgInstanceException(_cimg_instance + "get_isoline3d(): Instance is not a 2d image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100) || (size_x==width() && size_y==height())) { + const _functor2d_int func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.0f,height() - 1.0f,width(),height()); + } else { + const _functor2d_float func(*this); + vertices = isoline3d(primitives,func,isovalue,0,0,width() - 1.0f,height() - 1.0f,size_x,size_y); + } + return vertices; + } + + //! Generate an isosurface of the image instance as a 3d object. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param isovalue The returned list of the 3d object colors. + \param size_x Number of subdivisions along the X-axis. + \param size_y Number of subdisivions along the Y-axis. + \param size_z Number of subdisivions along the Z-axis. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + const CImg img = CImg("reference.jpg").resize(-100,-100,20); + CImgList faces3d; + const CImg points3d = img.get_isosurface3d(faces3d,100); + CImg().display_object3d("Isosurface3d",points3d,faces3d,colors3d); + \endcode + \image html ref_isosurface3d.jpg + **/ + template + CImg get_isosurface3d(CImgList& primitives, const float isovalue, + const int size_x=-100, const int size_y=-100, const int size_z=-100) const { + if (_spectrum>1) + throw CImgInstanceException(_cimg_instance + "get_isosurface3d(): Instance is not a scalar image.", + cimg_instance); + primitives.assign(); + if (is_empty()) return *this; + CImg vertices; + if ((size_x==-100 && size_y==-100 && size_z==-100) || (size_x==width() && size_y==height() && size_z==depth())) { + const _functor3d_int func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.0f,height() - 1.0f,depth() - 1.0f, + width(),height(),depth()); + } else { + const _functor3d_float func(*this); + vertices = isosurface3d(primitives,func,isovalue,0,0,0,width() - 1.0f,height() - 1.0f,depth() - 1.0f, + size_x,size_y,size_z); + } + return vertices; + } + + //! Compute 3d elevation of a function as a 3d object. + /** + \param[out] primitives Primitives data of the resulting 3d object. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + **/ + template + static CImg elevation3d(CImgList& primitives, const tfunc& func, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const float + nx0 = x0=0?size_x:(nx1-nx0)*-size_x/100), + nsize_x = _nsize_x?_nsize_x:1, nsize_x1 = nsize_x - 1, + _nsize_y = (unsigned int)(size_y>=0?size_y:(ny1-ny0)*-size_y/100), + nsize_y = _nsize_y?_nsize_y:1, nsize_y1 = nsize_y - 1; + if (nsize_x<2 || nsize_y<2) + throw CImgArgumentException("CImg<%s>::elevation3d(): Invalid specified size (%d,%d).", + pixel_type(), + nsize_x,nsize_y); + + CImg vertices(nsize_x*nsize_y,3); + floatT *ptr_x = vertices.data(0,0), *ptr_y = vertices.data(0,1), *ptr_z = vertices.data(0,2); + for (unsigned int y = 0; y + static CImg elevation3d(CImgList& primitives, const char *const expression, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return elevation3d(primitives,func,x0,y0,x1,y1,size_x,size_y); + } + + //! Compute 0-isolines of a function, as a 3d object. + /** + \param[out] primitives Primitives data of the resulting 3d object. + \param func Elevation function. Is of type float (*func)(const float x,const float y). + \param isovalue Isovalue to extract from function. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param size_x Resolution of the function along the X-axis. + \param size_y Resolution of the function along the Y-axis. + \note Use the marching squares algorithm for extracting the isolines. + **/ + template + static CImg isoline3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + static const unsigned int edges[16] = { 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc, + 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 }; + static const int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 }, + { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 }, + { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 }, + { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } }; + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nxm1 = nx - 1, + nym1 = ny - 1; + primitives.assign(); + if (!nxm1 || !nym1) return CImg(); + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1; + CImgList vertices; + CImg indices1(nx,1,1,2,-1), indices2(nx,1,1,2); + CImg values1(nx), values2(nx); + float X = x0, Y = y0, nX = X + dx, nY = Y + dy; + + // Fill first line with values + cimg_forX(values1,x) { values1(x) = (float)func(X,Y); X+=dx; } + + // Run the marching squares algorithm + for (unsigned int yi = 0, nyi = 1; yi::vector(Xi,Y,0).move_to(vertices); + } + if ((edge&2) && indices1(nxi,1)<0) { + const float Yi = Y + (isovalue-val1)*dy/(val2-val1); + indices1(nxi,1) = vertices.width(); + CImg::vector(nX,Yi,0).move_to(vertices); + } + if ((edge&4) && indices2(xi,0)<0) { + const float Xi = X + (isovalue-val3)*dx/(val2-val3); + indices2(xi,0) = vertices.width(); + CImg::vector(Xi,nY,0).move_to(vertices); + } + if ((edge&8) && indices1(xi,1)<0) { + const float Yi = Y + (isovalue-val0)*dy/(val3-val0); + indices1(xi,1) = vertices.width(); + CImg::vector(X,Yi,0).move_to(vertices); + } + + // Create segments + for (const int *segment = segments[configuration]; *segment!=-1; ) { + const unsigned int p0 = (unsigned int)*(segment++), p1 = (unsigned int)*(segment++); + const tf + i0 = (tf)(_isoline3d_indice(p0,indices1,indices2,xi,nxi)), + i1 = (tf)(_isoline3d_indice(p1,indices1,indices2,xi,nxi)); + CImg::vector(i0,i1).move_to(primitives); + } + } + } + values1.swap(values2); + indices1.swap(indices2); + } + return vertices>'x'; + } + + //! Compute isolines of a function, as a 3d object \overloading. + template + static CImg isoline3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float x1, const float y1, + const int size_x=256, const int size_y=256) { + const _functor2d_expr func(expression); + return isoline3d(primitives,func,isovalue,x0,y0,x1,y1,size_x,size_y); + } + + template + static int _isoline3d_indice(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int nx) { + switch (edge) { + case 0 : return (int)indices1(x,0); + case 1 : return (int)indices1(nx,1); + case 2 : return (int)indices2(x,0); + case 3 : return (int)indices1(x,1); + } + return 0; + } + + //! Compute isosurface of a function, as a 3d object. + /** + \param[out] primitives Primitives data of the resulting 3d object. + \param func Implicit function. Is of type float (*func)(const float x, const float y, const float z). + \param isovalue Isovalue to extract. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point. + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param size_x Resolution of the elevation function along the X-axis. + \param size_y Resolution of the elevation function along the Y-axis. + \param size_z Resolution of the elevation function along the Z-axis. + \note Use the marching cubes algorithm for extracting the isosurface. + **/ + template + static CImg isosurface3d(CImgList& primitives, const tfunc& func, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int size_x=32, const int size_y=32, const int size_z=32) { + static const unsigned int edges[256] = { + 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, + 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, + 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, + 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, + 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, + 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, + 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, + 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, + 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, + 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, + 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, + 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460, + 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0, + 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230, + 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190, + 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 + }; + + static const int triangles[256][16] = { + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, + { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, + { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, + { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, + { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, + { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, + { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, + { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, + { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, + { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, + { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, + { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, + { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, + { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, + { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, + { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, + { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, + { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, + { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, + { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, + { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, + { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, + { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, + { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, + { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, + { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, + { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, + { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, + { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, + { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, + { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, + { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, + { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, + { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, + { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, + { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, + { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, + { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, + { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, + { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, + { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, + { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, + { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, + { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, + { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, + { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, + { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, + { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, + { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, + { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, + { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, + { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, + { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, + { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, + { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, + { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, + { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, + { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, + { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, + { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, + { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, + { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, + { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, + { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, + { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, + { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, + { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, + { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, + { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, + { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, + { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, + { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, + { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, + { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, + { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, + { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, + { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, + { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, + { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, + { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, + { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, + { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, + { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, + { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, + { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, + { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, + { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, + { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, + { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, + { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, + { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, + { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, + { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, + { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, + { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, + { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, + { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, + { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, + { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, + { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, + { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } + }; + + const unsigned int + _nx = (unsigned int)(size_x>=0?size_x:cimg::round((x1-x0)*-size_x/100 + 1)), + _ny = (unsigned int)(size_y>=0?size_y:cimg::round((y1-y0)*-size_y/100 + 1)), + _nz = (unsigned int)(size_z>=0?size_z:cimg::round((z1-z0)*-size_z/100 + 1)), + nx = _nx?_nx:1, + ny = _ny?_ny:1, + nz = _nz?_nz:1, + nxm1 = nx - 1, + nym1 = ny - 1, + nzm1 = nz - 1; + primitives.assign(); + if (!nxm1 || !nym1 || !nzm1) return CImg(); + const float dx = (x1 - x0)/nxm1, dy = (y1 - y0)/nym1, dz = (z1 - z0)/nzm1; + CImgList vertices; + CImg indices1(nx,ny,1,3,-1), indices2(indices1); + CImg values1(nx,ny), values2(nx,ny); + float X = 0, Y = 0, Z = 0, nX = 0, nY = 0, nZ = 0; + + // Fill the first plane with function values + Y = y0; + cimg_forY(values1,y) { + X = x0; + cimg_forX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=dx; } + Y+=dy; + } + + // Run Marching Cubes algorithm + Z = z0; nZ = Z + dz; + for (unsigned int zi = 0; zi::vector(Xi,Y,Z).move_to(vertices); + } + if ((edge&2) && indices1(nxi,yi,1)<0) { + const float Yi = Y + (isovalue-val1)*dy/(val2-val1); + indices1(nxi,yi,1) = vertices.width(); + CImg::vector(nX,Yi,Z).move_to(vertices); + } + if ((edge&4) && indices1(xi,nyi,0)<0) { + const float Xi = X + (isovalue-val3)*dx/(val2-val3); + indices1(xi,nyi,0) = vertices.width(); + CImg::vector(Xi,nY,Z).move_to(vertices); + } + if ((edge&8) && indices1(xi,yi,1)<0) { + const float Yi = Y + (isovalue-val0)*dy/(val3-val0); + indices1(xi,yi,1) = vertices.width(); + CImg::vector(X,Yi,Z).move_to(vertices); + } + if ((edge&16) && indices2(xi,yi,0)<0) { + const float Xi = X + (isovalue-val4)*dx/(val5-val4); + indices2(xi,yi,0) = vertices.width(); + CImg::vector(Xi,Y,nZ).move_to(vertices); + } + if ((edge&32) && indices2(nxi,yi,1)<0) { + const float Yi = Y + (isovalue-val5)*dy/(val6-val5); + indices2(nxi,yi,1) = vertices.width(); + CImg::vector(nX,Yi,nZ).move_to(vertices); + } + if ((edge&64) && indices2(xi,nyi,0)<0) { + const float Xi = X + (isovalue-val7)*dx/(val6-val7); + indices2(xi,nyi,0) = vertices.width(); + CImg::vector(Xi,nY,nZ).move_to(vertices); + } + if ((edge&128) && indices2(xi,yi,1)<0) { + const float Yi = Y + (isovalue-val4)*dy/(val7-val4); + indices2(xi,yi,1) = vertices.width(); + CImg::vector(X,Yi,nZ).move_to(vertices); + } + if ((edge&256) && indices1(xi,yi,2)<0) { + const float Zi = Z+ (isovalue-val0)*dz/(val4-val0); + indices1(xi,yi,2) = vertices.width(); + CImg::vector(X,Y,Zi).move_to(vertices); + } + if ((edge&512) && indices1(nxi,yi,2)<0) { + const float Zi = Z + (isovalue-val1)*dz/(val5-val1); + indices1(nxi,yi,2) = vertices.width(); + CImg::vector(nX,Y,Zi).move_to(vertices); + } + if ((edge&1024) && indices1(nxi,nyi,2)<0) { + const float Zi = Z + (isovalue-val2)*dz/(val6-val2); + indices1(nxi,nyi,2) = vertices.width(); + CImg::vector(nX,nY,Zi).move_to(vertices); + } + if ((edge&2048) && indices1(xi,nyi,2)<0) { + const float Zi = Z + (isovalue-val3)*dz/(val7-val3); + indices1(xi,nyi,2) = vertices.width(); + CImg::vector(X,nY,Zi).move_to(vertices); + } + + // Create triangles + for (const int *triangle = triangles[configuration]; *triangle!=-1; ) { + const unsigned int + p0 = (unsigned int)*(triangle++), + p1 = (unsigned int)*(triangle++), + p2 = (unsigned int)*(triangle++); + const tf + i0 = (tf)(_isosurface3d_indice(p0,indices1,indices2,xi,yi,nxi,nyi)), + i1 = (tf)(_isosurface3d_indice(p1,indices1,indices2,xi,yi,nxi,nyi)), + i2 = (tf)(_isosurface3d_indice(p2,indices1,indices2,xi,yi,nxi,nyi)); + CImg::vector(i0,i2,i1).move_to(primitives); + } + } + } + } + cimg::swap(values1,values2); + cimg::swap(indices1,indices2); + } + return vertices>'x'; + } + + //! Compute isosurface of a function, as a 3d object \overloading. + template + static CImg isosurface3d(CImgList& primitives, const char *const expression, const float isovalue, + const float x0, const float y0, const float z0, + const float x1, const float y1, const float z1, + const int dx=32, const int dy=32, const int dz=32) { + const _functor3d_expr func(expression); + return isosurface3d(primitives,func,isovalue,x0,y0,z0,x1,y1,z1,dx,dy,dz); + } + + template + static int _isosurface3d_indice(const unsigned int edge, const CImg& indices1, const CImg& indices2, + const unsigned int x, const unsigned int y, + const unsigned int nx, const unsigned int ny) { + switch (edge) { + case 0 : return indices1(x,y,0); + case 1 : return indices1(nx,y,1); + case 2 : return indices1(x,ny,0); + case 3 : return indices1(x,y,1); + case 4 : return indices2(x,y,0); + case 5 : return indices2(nx,y,1); + case 6 : return indices2(x,ny,0); + case 7 : return indices2(x,y,1); + case 8 : return indices1(x,y,2); + case 9 : return indices1(nx,y,2); + case 10 : return indices1(nx,ny,2); + case 11 : return indices1(x,ny,2); + } + return 0; + } + + // Define functors for accessing image values (used in previous functions). + struct _functor2d_int { + const CImg& ref; + _functor2d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref((int)x,(int)y); + } + }; + + struct _functor2d_float { + const CImg& ref; + _functor2d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y) const { + return (float)ref._linear_atXY(x,y); + } + }; + + struct _functor2d_expr { + _cimg_math_parser *mp; + _functor2d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + ~_functor2d_expr() { delete mp; } + float operator()(const float x, const float y) const { + return (float)(*mp)(x,y,0,0); + } + }; + + struct _functor3d_int { + const CImg& ref; + _functor3d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref((int)x,(int)y,(int)z); + } + }; + + struct _functor3d_float { + const CImg& ref; + _functor3d_float(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z) const { + return (float)ref._linear_atXYZ(x,y,z); + } + }; + + struct _functor3d_expr { + _cimg_math_parser *mp; + ~_functor3d_expr() { delete mp; } + _functor3d_expr(const char *const expr):mp(0) { + mp = new _cimg_math_parser(expr,0,CImg::const_empty(),0); + } + float operator()(const float x, const float y, const float z) const { + return (float)(*mp)(x,y,z,0); + } + }; + + struct _functor4d_int { + const CImg& ref; + _functor4d_int(const CImg& pref):ref(pref) {} + float operator()(const float x, const float y, const float z, const unsigned int c) const { + return (float)ref((int)x,(int)y,(int)z,c); + } + }; + + //! Generate a 3d box object. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the box (dimension along the X-axis). + \param size_y The height of the box (dimension along the Y-axis). + \param size_z The depth of the box (dimension along the Z-axis). + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::box3d(faces3d,10,20,30); + CImg().display_object3d("Box3d",points3d,faces3d); + \endcode + \image html ref_box3d.jpg + **/ + template + static CImg box3d(CImgList& primitives, + const float size_x=200, const float size_y=100, const float size_z=100) { + primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 0,1,5,4, 3,7,6,2, 0,4,7,3, 1,2,6,5); + return CImg(8,3,1,1, + 0.,size_x,size_x, 0., 0.,size_x,size_x, 0., + 0., 0.,size_y,size_y, 0., 0.,size_y,size_y, + 0., 0., 0., 0.,size_z,size_z,size_z,size_z); + } + + //! Generate a 3d cone. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cone basis. + \param size_z The cone's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cone3d(faces3d,50); + CImg().display_object3d("Cone3d",points3d,faces3d); + \endcode + \image html ref_cone3d.jpg + **/ + template + static CImg cone3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,size_z, + 0.,0.,0.); + for (float delta = 360.0f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0).move_to(vertices); + } + const unsigned int nbr = vertices._width - 2; + for (unsigned int p = 0; p::vector(1,next,curr).move_to(primitives); + CImg::vector(0,curr,next).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3d cylinder. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the cylinder basis. + \param size_z The cylinder's height. + \param subdivisions The number of basis angular subdivisions. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::cylinder3d(faces3d,50); + CImg().display_object3d("Cylinder3d",points3d,faces3d); + \endcode + \image html ref_cylinder3d.jpg + **/ + template + static CImg cylinder3d(CImgList& primitives, + const float radius=50, const float size_z=100, const unsigned int subdivisions=24) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImgList vertices(2,1,3,1,1, + 0.,0.,0., + 0.,0.,size_z); + for (float delta = 360.0f/subdivisions, angle = 0; angle<360; angle+=delta) { + const float a = (float)(angle*cimg::PI/180); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),0.0f).move_to(vertices); + CImg::vector((float)(radius*std::cos(a)),(float)(radius*std::sin(a)),size_z).move_to(vertices); + } + const unsigned int nbr = (vertices._width - 2)/2; + for (unsigned int p = 0; p::vector(0,next,curr).move_to(primitives); + CImg::vector(1,curr + 1,next + 1).move_to(primitives); + CImg::vector(curr,next,next + 1,curr + 1).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3d torus. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius1 The large radius. + \param radius2 The small radius. + \param subdivisions1 The number of angular subdivisions for the large radius. + \param subdivisions2 The number of angular subdivisions for the small radius. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::torus3d(faces3d,20,4); + CImg().display_object3d("Torus3d",points3d,faces3d); + \endcode + \image html ref_torus3d.jpg + **/ + template + static CImg torus3d(CImgList& primitives, + const float radius1=100, const float radius2=30, + const unsigned int subdivisions1=24, const unsigned int subdivisions2=12) { + primitives.assign(); + if (!subdivisions1 || !subdivisions2) return CImg(); + CImgList vertices; + for (unsigned int v = 0; v::vector(x,y,z).move_to(vertices); + } + } + for (unsigned int vv = 0; vv::vector(svv + nu,svv + uu,snv + uu,snv + nu).move_to(primitives); + } + } + return vertices>'x'; + } + + //! Generate a 3d XY-plane. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param size_x The width of the plane (dimension along the X-axis). + \param size_y The height of the plane (dimensions along the Y-axis). + \param subdivisions_x The number of planar subdivisions along the X-axis. + \param subdivisions_y The number of planar subdivisions along the Y-axis. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::plane3d(faces3d,100,50); + CImg().display_object3d("Plane3d",points3d,faces3d); + \endcode + \image html ref_plane3d.jpg + **/ + template + static CImg plane3d(CImgList& primitives, + const float size_x=100, const float size_y=100, + const unsigned int subdivisions_x=10, const unsigned int subdivisions_y=10) { + primitives.assign(); + if (!subdivisions_x || !subdivisions_y) return CImg(); + CImgList vertices; + const unsigned int w = subdivisions_x + 1, h = subdivisions_y + 1; + const float fx = (float)size_x/w, fy = (float)size_y/h; + for (unsigned int y = 0; y::vector(fx*x,fy*y,0).move_to(vertices); + for (unsigned int y = 0; y::vector(off1,off4,off3,off2).move_to(primitives); + } + return vertices>'x'; + } + + //! Generate a 3d sphere. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param radius The radius of the sphere (dimension along the X-axis). + \param subdivisions The number of recursive subdivisions from an initial icosahedron. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg points3d = CImg::sphere3d(faces3d,100,4); + CImg().display_object3d("Sphere3d",points3d,faces3d); + \endcode + \image html ref_sphere3d.jpg + **/ + template + static CImg sphere3d(CImgList& primitives, + const float radius=50, const unsigned int subdivisions=3) { + + // Create initial icosahedron + primitives.assign(); + const double tmp = (1 + std::sqrt(5.0f))/2, a = 1.0/std::sqrt(1 + tmp*tmp), b = tmp*a; + CImgList vertices(12,1,3,1,1, b,a,0.0, -b,a,0.0, -b,-a,0.0, b,-a,0.0, a,0.0,b, a,0.0,-b, + -a,0.0,-b, -a,0.0,b, 0.0,b,a, 0.0,-b,a, 0.0,-b,-a, 0.0,b,-a); + primitives.assign(20,1,3,1,1, 4,8,7, 4,7,9, 5,6,11, 5,10,6, 0,4,3, 0,3,5, 2,7,1, 2,1,6, + 8,0,11, 8,11,1, 9,10,3, 9,2,10, 8,4,0, 11,0,5, 4,9,3, + 5,3,10, 7,8,1, 6,1,11, 7,2,9, 6,10,2); + // edge - length/2 + float he = (float)a; + + // Recurse subdivisions + for (unsigned int i = 0; i::vector(nx0,ny0,nz0).move_to(vertices); i0 = vertices.width() - 1; } + if (i1<0) { CImg::vector(nx1,ny1,nz1).move_to(vertices); i1 = vertices.width() - 1; } + if (i2<0) { CImg::vector(nx2,ny2,nz2).move_to(vertices); i2 = vertices.width() - 1; } + primitives.remove(0); + CImg::vector(p0,i0,i1).move_to(primitives); + CImg::vector((tf)i0,(tf)p1,(tf)i2).move_to(primitives); + CImg::vector((tf)i1,(tf)i2,(tf)p2).move_to(primitives); + CImg::vector((tf)i1,(tf)i0,(tf)i2).move_to(primitives); + } + } + return (vertices>'x')*=radius; + } + + //! Generate a 3d ellipsoid. + /** + \param[out] primitives The returned list of the 3d object primitives + (template type \e tf should be at least \e unsigned \e int). + \param tensor The tensor which gives the shape and size of the ellipsoid. + \param subdivisions The number of recursive subdivisions from an initial stretched icosahedron. + \return The N vertices (xi,yi,zi) of the 3d object as a Nx3 CImg image (0<=i<=N - 1). + \par Example + \code + CImgList faces3d; + const CImg tensor = CImg::diagonal(10,7,3), + points3d = CImg::ellipsoid3d(faces3d,tensor,4); + CImg().display_object3d("Ellipsoid3d",points3d,faces3d); + \endcode + \image html ref_ellipsoid3d.jpg + **/ + template + static CImg ellipsoid3d(CImgList& primitives, + const CImg& tensor, const unsigned int subdivisions=3) { + primitives.assign(); + if (!subdivisions) return CImg(); + CImg S, V; + tensor.symmetric_eigen(S,V); + const float orient = + (V(0,1)*V(1,2) - V(0,2)*V(1,1))*V(2,0) + + (V(0,2)*V(1,0) - V(0,0)*V(1,2))*V(2,1) + + (V(0,0)*V(1,1) - V(0,1)*V(1,0))*V(2,2); + if (orient<0) { V(2,0) = -V(2,0); V(2,1) = -V(2,1); V(2,2) = -V(2,2); } + const float l0 = S[0], l1 = S[1], l2 = S[2]; + CImg vertices = sphere3d(primitives,1.0,subdivisions); + vertices.get_shared_row(0)*=l0; + vertices.get_shared_row(1)*=l1; + vertices.get_shared_row(2)*=l2; + return V*vertices; + } + + //! Convert 3d object into a CImg3d representation. + /** + \param primitives Primitives data of the 3d object. + \param colors Colors data of the 3d object. + \param opacities Opacities data of the 3d object. + \param full_check Tells if full checking of the 3d object must be performed. + **/ + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert 3d object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,colors,full_check).move_to(*this); + } + + //! Convert 3d object into a CImg3d representation \overloading. + template + CImg& object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) { + return get_object3dtoCImg3d(primitives,full_check).move_to(*this); + } + + //! Convert 3d object into a CImg3d representation \overloading. + CImg& object3dtoCImg3d(const bool full_check=true) { + return get_object3dtoCImg3d(full_check).move_to(*this); + } + + //! Convert 3d object into a CImg3d representation \newinstance. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "object3dtoCImg3d(): Invalid specified 3d object (%u,%u) (%s).", + cimg_instance,_width,primitives._width,error_message.data()); + CImg res(1,_size_object3dtoCImg3d(primitives,colors,opacities)); + float *ptrd = res._data; + + // Put magick number. + *(ptrd++) = 'C' + 0.5f; *(ptrd++) = 'I' + 0.5f; *(ptrd++) = 'm' + 0.5f; + *(ptrd++) = 'g' + 0.5f; *(ptrd++) = '3' + 0.5f; *(ptrd++) = 'd' + 0.5f; + + // Put number of vertices and primitives. + *(ptrd++) = cimg::uint2float(_width); + *(ptrd++) = cimg::uint2float(primitives._width); + + // Put vertex data. + if (is_empty() || !primitives) return res; + const T *ptrx = data(0,0), *ptry = data(0,1), *ptrz = data(0,2); + cimg_forX(*this,p) { + *(ptrd++) = (float)*(ptrx++); + *(ptrd++) = (float)*(ptry++); + *(ptrd++) = (float)*(ptrz++); + } + + // Put primitive data. + cimglist_for(primitives,p) { + *(ptrd++) = (float)primitives[p].size(); + const tp *ptrp = primitives[p]._data; + cimg_foroff(primitives[p],i) *(ptrd++) = cimg::uint2float((unsigned int)*(ptrp++)); + } + + // Put color/texture data. + const unsigned int csiz = std::min(colors._width,primitives._width); + for (int c = 0; c<(int)csiz; ++c) { + const CImg& color = colors[c]; + const tc *ptrc = color._data; + if (color.size()==3) { *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*(ptrc++); *(ptrd++) = (float)*ptrc; } + else { + *(ptrd++) = -128.0f; + int shared_ind = -1; + if (color.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImgList& opacities, float *ptrd) const { + cimglist_for(opacities,o) { + const CImg& opacity = opacities[o]; + const to *ptro = opacity._data; + if (opacity.size()==1) *(ptrd++) = (float)*ptro; + else { + *(ptrd++) = -128.0f; + int shared_ind = -1; + if (opacity.is_shared()) for (int i = 0; i + float* _object3dtoCImg3d(const CImg& opacities, float *ptrd) const { + const to *ptro = opacities._data; + cimg_foroff(opacities,o) *(ptrd++) = (float)*(ptro++); + return ptrd; + } + + template + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImgList& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + if (colors[c].is_shared()) siz+=4; + else { const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; } + } + if (colors._width + unsigned int _size_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const CImg& opacities) const { + unsigned int siz = 8U + 3*_width; + cimglist_for(primitives,p) siz+=primitives[p].size() + 1; + for (int c = std::min(primitives.width(),colors.width()) - 1; c>=0; --c) { + const unsigned int csiz = colors[c].size(); siz+=(csiz!=3)?4 + csiz:3; + } + if (colors._width + CImg get_object3dtoCImg3d(const CImgList& primitives, + const CImgList& colors, + const bool full_check=true) const { + CImgList opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3d object into a CImg3d representation \overloading. + template + CImg get_object3dtoCImg3d(const CImgList& primitives, + const bool full_check=true) const { + CImgList colors, opacities; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert 3d object into a CImg3d representation \overloading. + CImg get_object3dtoCImg3d(const bool full_check=true) const { + CImgList opacities, colors; + CImgList primitives(width(),1,1,1,1); + cimglist_for(primitives,p) primitives(p,0) = p; + return get_object3dtoCImg3d(primitives,colors,opacities,full_check); + } + + //! Convert CImg3d representation into a 3d object. + /** + \param[out] primitives Primitives data of the 3d object. + \param[out] colors Colors data of the 3d object. + \param[out] opacities Opacities data of the 3d object. + \param full_check Tells if full checking of the 3d object must be performed. + **/ + template + CImg& CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) { + return get_CImg3dtoobject3d(primitives,colors,opacities,full_check).move_to(*this); + } + + //! Convert CImg3d representation into a 3d object \newinstance. + template + CImg get_CImg3dtoobject3d(CImgList& primitives, + CImgList& colors, + CImgList& opacities, + const bool full_check=true) const { + CImg error_message(1024); + if (!is_CImg3d(full_check,error_message)) + throw CImgInstanceException(_cimg_instance + "CImg3dtoobject3d(): image instance is not a CImg3d (%s).", + cimg_instance,error_message.data()); + const T *ptrs = _data + 6; + const unsigned int + nb_points = cimg::float2uint((float)*(ptrs++)), + nb_primitives = cimg::float2uint((float)*(ptrs++)); + const CImg points = CImg(ptrs,3,nb_points,1,1,true).get_transpose(); + ptrs+=3*nb_points; + primitives.assign(nb_primitives); + cimglist_for(primitives,p) { + const unsigned int nb_inds = (unsigned int)*(ptrs++); + primitives[p].assign(1,nb_inds); + tp *ptrp = primitives[p]._data; + for (unsigned int i = 0; i + CImg& _draw_scanline(const int x0, const int x1, const int y, + const tc *const color, const float opacity, + const float brightness, + const float nopacity, const float copacity, const ulongT whd) { + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const int nx0 = x0>0?x0:0, nx1 = x1=0) { + const tc *col = color; + const ulongT off = whd - dx - 1; + T *ptrd = data(nx0,y); + if (opacity>=1) { // ** Opaque drawing ** + if (brightness==1) { // Brightness==1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)*(col++); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)*(col++); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else if (brightness<1) { // Brightness<1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)(*(col++)*brightness); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } else { // Brightness>1 + if (sizeof(T)!=1) cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*maxval); + for (int x = dx; x>=0; --x) *(ptrd++) = val; + ptrd+=off; + } else cimg_forC(*this,c) { + const T val = (T)((2-brightness)**(col++) + (brightness - 1)*maxval); + std::memset(ptrd,(int)val,dx + 1); + ptrd+=whd; + } + } + } else { // ** Transparent drawing ** + if (brightness==1) { // Brightness==1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else if (brightness<=1) { // Brightness<1 + cimg_forC(*this,c) { + const Tfloat val = *(col++)*brightness*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } else { // Brightness>1 + cimg_forC(*this,c) { + const Tfloat val = ((2-brightness)**(col++) + (brightness - 1)*maxval)*nopacity; + for (int x = dx; x>=0; --x) { *ptrd = (T)(val + *ptrd*copacity); ++ptrd; } + ptrd+=off; + } + } + } + } + return *this; + } + + //! Draw a 3d point. + /** + \param x0 X-coordinate of the point. + \param y0 Y-coordinate of the point. + \param z0 Z-coordinate of the point. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \note + - To set pixel values without clipping needs, you should use the faster CImg::operator()() function. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_point(50,50,color); + \endcode + **/ + template + CImg& draw_point(const int x0, const int y0, const int z0, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_point(): Specified color is (null).", + cimg_instance); + if (x0>=0 && y0>=0 && z0>=0 && x0=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } + } + return *this; + } + + //! Draw a 2d point \simplification. + template + CImg& draw_point(const int x0, const int y0, + const tc *const color, const float opacity=1) { + return draw_point(x0,y0,0,color,opacity); + } + + // Draw a points cloud. + /** + \param points Image of vertices coordinates. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_point(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_point(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),color,opacity); + } break; + default : { + cimg_forX(points,i) draw_point((int)points(i,0),(int)points(i,1),(int)points(i,2),color,opacity); + } + } + return *this; + } + + //! Draw a 2d line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + \note + - Line routine uses Bresenham's algorithm. + - Set \p init_hatch = false to draw consecutive hatched segments without breaking the line pattern. + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,color); + \endcode + **/ + template + CImg& draw_line(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_line(): Specified color is (null).", + cimg_instance); + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + const bool xdir = x0=width()) return *this; + if (xleft<0) { yleft-=(int)((float)xleft*((float)yright - yleft)/((float)xright - xleft)); xleft = 0; } + if (xright>=width()) { + yright-=(int)(((float)xright - width())*((float)yright - yleft)/((float)xright - xleft)); + xright = width() - 1; + } + if (ydown<0 || yup>=height()) return *this; + if (yup<0) { xup-=(int)((float)yup*((float)xdown - xup)/((float)ydown - yup)); yup = 0; } + if (ydown>=height()) { + xdown-=(int)(((float)ydown - height())*((float)xdown - xup)/((float)ydown - yup)); + ydown = height() - 1; + } + T *ptrd0 = data(nx0,ny0); + int dx = xright - xleft, dy = ydown - yup; + const bool steep = dy>dx; + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); + const longT + offx = (longT)(nx0=1) { + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + T *ptrd = ptrd0; const tc* col = color; + cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=wh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + T *ptrd = ptrd0; const tc* col = color; cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=wh; } + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } + } else { + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + T *ptrd = ptrd0; const tc* col = color; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + T *ptrd = ptrd0; const tc* col = color; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } + } + return *this; + } + + //! Draw a 2d line, with z-buffering. + /** + \param zbuffer Zbuffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + **/ + template + CImg& draw_line(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_line(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + const bool xdir = x0=width()) return *this; + if (xleft<0) { + const float D = (float)xright - xleft; + yleft-=(int)((float)xleft*((float)yright - yleft)/D); + zleft-=(tzfloat)xleft*(zright - zleft)/D; + xleft = 0; + } + if (xright>=width()) { + const float d = (float)xright - width(), D = (float)xright - xleft; + yright-=(int)(d*((float)yright - yleft)/D); + zright-=(tzfloat)d*(zright - zleft)/D; + xright = width() - 1; + } + if (ydown<0 || yup>=height()) return *this; + if (yup<0) { + const float D = (float)ydown - yup; + xup-=(int)((float)yup*((float)xdown - xup)/D); + zup-=(tzfloat)yup*(zdown - zup)/D; + yup = 0; + } + if (ydown>=height()) { + const float d = (float)ydown - height(), D = (float)ydown - yup; + xdown-=(int)(d*((float)xdown - xup)/D); + zdown-=(tzfloat)d*(zdown - zup)/D; + ydown = height() - 1; + } + T *ptrd0 = data(nx0,ny0); + tz *ptrz = zbuffer.data(nx0,ny0); + int dx = xright - xleft, dy = ydown - yup; + const bool steep = dy>dx; + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); + const longT + offx = (longT)(nx00?dx:1); + if (opacity>=1) { + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz && pattern&hatch) { + *ptrz = (tz)z; + T *ptrd = ptrd0; const tc *col = color; + cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=wh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz) { + *ptrz = (tz)z; + T *ptrd = ptrd0; const tc *col = color; + cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=wh; } + } + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } + } else { + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz && pattern&hatch) { + *ptrz = (tz)z; + T *ptrd = ptrd0; const tc *col = color; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz) { + *ptrz = (tz)z; + T *ptrd = ptrd0; const tc *col = color; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=wh; } + } + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } + } + return *this; + } + + //! Draw a 3d line. + /** + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if a reinitialization of the hash state must be done. + **/ + template + CImg& draw_line(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_line(): Specified color is (null).", + cimg_instance); + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + int nx0 = x0, ny0 = y0, nz0 = z0, nx1 = x1, ny1 = y1, nz1 = z1; + if (nx0>nx1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); + if (nx1<0 || nx0>=width()) return *this; + if (nx0<0) { + const float D = 1.0f + nx1 - nx0; + ny0-=(int)((float)nx0*(1.0f + ny1 - ny0)/D); + nz0-=(int)((float)nx0*(1.0f + nz1 - nz0)/D); + nx0 = 0; + } + if (nx1>=width()) { + const float d = (float)nx1 - width(), D = 1.0f + nx1 - nx0; + ny1+=(int)(d*(1.0f + ny0 - ny1)/D); + nz1+=(int)(d*(1.0f + nz0 - nz1)/D); + nx1 = width() - 1; + } + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); + if (ny1<0 || ny0>=height()) return *this; + if (ny0<0) { + const float D = 1.0f + ny1 - ny0; + nx0-=(int)((float)ny0*(1.0f + nx1 - nx0)/D); + nz0-=(int)((float)ny0*(1.0f + nz1 - nz0)/D); + ny0 = 0; + } + if (ny1>=height()) { + const float d = (float)ny1 - height(), D = 1.0f + ny1 - ny0; + nx1+=(int)(d*(1.0f + nx0 - nx1)/D); + nz1+=(int)(d*(1.0f + nz0 - nz1)/D); + ny1 = height() - 1; + } + if (nz0>nz1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); + if (nz1<0 || nz0>=depth()) return *this; + if (nz0<0) { + const float D = 1.0f + nz1 - nz0; + nx0-=(int)((float)nz0*(1.0f + nx1 - nx0)/D); + ny0-=(int)((float)nz0*(1.0f + ny1 - ny0)/D); + nz0 = 0; + } + if (nz1>=depth()) { + const float d = (float)nz1 - depth(), D = 1.0f + nz1 - nz0; + nx1+=(int)(d*(1.0f + nx0 - nx1)/D); + ny1+=(int)(d*(1.0f + ny0 - ny1)/D); + nz1 = depth() - 1; + } + const unsigned int dmax = (unsigned int)cimg::max(cimg::abs(nx1 - nx0),cimg::abs(ny1 - ny0),nz1 - nz0); + const ulongT whd = (ulongT)_width*_height*_depth; + const float px = (nx1 - nx0)/(float)dmax, py = (ny1 - ny0)/(float)dmax, pz = (nz1 - nz0)/(float)dmax; + float x = (float)nx0, y = (float)ny0, z = (float)nz0; + if (opacity>=1) for (unsigned int t = 0; t<=dmax; ++t) { + if (!(~pattern) || (~pattern && pattern&hatch)) { + T* ptrd = data((unsigned int)x,(unsigned int)y,(unsigned int)z); + const tc *col = color; cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } + } + x+=px; y+=py; z+=pz; if (pattern) { hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); } + } else { + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + for (unsigned int t = 0; t<=dmax; ++t) { + if (!(~pattern) || (~pattern && pattern&hatch)) { + T* ptrd = data((unsigned int)x,(unsigned int)y,(unsigned int)z); + const tc *col = color; cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } + } + x+=px; y+=py; z+=pz; if (pattern) { hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); } + } + } + return *this; + } + + //! Draw a textured 2d line. + /** + \param x0 X-coordinate of the starting line point. + \param y0 Y-coordinate of the starting line point. + \param x1 X-coordinate of the ending line point. + \param y1 Y-coordinate of the ending line point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + \note + - Line routine uses the well known Bresenham's algorithm. + \par Example: + \code + CImg img(100,100,1,3,0), texture("texture256x256.ppm"); + const unsigned char color[] = { 255,128,64 }; + img.draw_line(40,40,80,70,texture,0,0,255,255); + \endcode + **/ + template + CImg& draw_line(const int x0, const int y0, + const int x1, const int y1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_line(x0,y0,x1,y1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + const bool xdir = x0=width()) return *this; + if (xleft<0) { + const float D = (float)xright - xleft; + yleft-=(int)((float)xleft*((float)yright - yleft)/D); + txleft-=(int)((float)xleft*((float)txright - txleft)/D); + tyleft-=(int)((float)xleft*((float)tyright - tyleft)/D); + xleft = 0; + } + if (xright>=width()) { + const float d = (float)xright - width(), D = (float)xright - xleft; + yright-=(int)(d*((float)yright - yleft)/D); + txright-=(int)(d*((float)txright - txleft)/D); + tyright-=(int)(d*((float)tyright - tyleft)/D); + xright = width() - 1; + } + if (ydown<0 || yup>=height()) return *this; + if (yup<0) { + const float D = (float)ydown - yup; + xup-=(int)((float)yup*((float)xdown - xup)/D); + txup-=(int)((float)yup*((float)txdown - txup)/D); + tyup-=(int)((float)yup*((float)tydown - tyup)/D); + yup = 0; + } + if (ydown>=height()) { + const float d = (float)ydown - height(), D = (float)ydown - yup; + xdown-=(int)(d*((float)xdown - xup)/D); + txdown-=(int)(d*((float)txdown - txup)/D); + tydown-=(int)(d*((float)tydown - tyup)/D); + ydown = height() - 1; + } + T *ptrd0 = data(nx0,ny0); + int dx = xright - xleft, dy = ydown - yup; + const bool steep = dy>dx; + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); + const longT + offx = (longT)(nx00?dx:1); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height; + + if (opacity>=1) { + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + T *ptrd = ptrd0; + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; + const tc *col = &texture._atXY(tx,ty); + cimg_forC(*this,c) { *ptrd = (T)*col; ptrd+=whd; col+=twh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + T *ptrd = ptrd0; + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; + const tc *col = &texture._atXY(tx,ty); + cimg_forC(*this,c) { *ptrd = (T)*col; ptrd+=whd; col+=twh; } + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } + } else { + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + T *ptrd = ptrd0; + if (pattern&hatch) { + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; + const tc *col = &texture._atXY(tx,ty); + cimg_forC(*this,c) { *ptrd = (T)(nopacity**col + *ptrd*copacity); ptrd+=whd; col+=twh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + T *ptrd = ptrd0; + const int tx = tx0 + x*dtx/ndx, ty = ty0 + x*dty/ndx; + const tc *col = &texture._atXY(tx,ty); + cimg_forC(*this,c) { *ptrd = (T)(nopacity**col + *ptrd*copacity); ptrd+=whd; col+=twh; } + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } + } + return *this; + } + + //! Draw a textured 2d line, with perspective correction. + /** + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() && z0<=0 && z1<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + const bool xdir = x0=width()) return *this; + if (xleft<0) { + const float D = (float)xright - xleft; + yleft-=(int)((float)xleft*((float)yright - yleft)/D); + zleft-=(float)xleft*(zright - zleft)/D; + txleft-=(float)xleft*(txright - txleft)/D; + tyleft-=(float)xleft*(tyright - tyleft)/D; + xleft = 0; + } + if (xright>=width()) { + const float d = (float)xright - width(), D = (float)xright - xleft; + yright-=(int)(d*((float)yright - yleft)/D); + zright-=d*(zright - zleft)/D; + txright-=d*(txright - txleft)/D; + tyright-=d*(tyright - tyleft)/D; + xright = width() - 1; + } + if (ydown<0 || yup>=height()) return *this; + if (yup<0) { + const float D = (float)ydown - yup; + xup-=(int)((float)yup*((float)xdown - xup)/D); + zup-=(float)yup*(zdown - zup)/D; + txup-=(float)yup*(txdown - txup)/D; + tyup-=(float)yup*(tydown - tyup)/D; + yup = 0; + } + if (ydown>=height()) { + const float d = (float)ydown - height(), D = (float)ydown - yup; + xdown-=(int)(d*((float)xdown - xup)/D); + zdown-=d*(zdown - zup)/D; + txdown-=d*(txdown - txup)/D; + tydown-=d*(tydown - tyup)/D; + ydown = height() - 1; + } + T *ptrd0 = data(nx0,ny0); + int dx = xright - xleft, dy = ydown - yup; + const bool steep = dy>dx; + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); + const longT + offx = (longT)(nx00?dx:1); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height; + + if (opacity>=1) { + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)*col; ptrd+=whd; col+=twh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)*col; ptrd+=whd; col+=twh; } + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } + } else { + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**col + *ptrd*copacity); ptrd+=whd; col+=twh; } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + const float z = Z0 + x*dz/ndx, tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**col + *ptrd*copacity); ptrd+=whd; col+=twh; } + ptrd0+=offx; + if ((error-=dy)<0) { ptrd0+=offy; error+=dx; } + } + } + return *this; + } + + //! Draw a textured 2d line, with perspective correction and z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the starting point. + \param y0 Y-coordinate of the starting point. + \param z0 Z-coordinate of the starting point + \param x1 X-coordinate of the ending point. + \param y1 Y-coordinate of the ending point. + \param z1 Z-coordinate of the ending point. + \param texture Texture image defining the pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch Tells if the hash variable must be reinitialized. + **/ + template + CImg& draw_line(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_line(zbuffer,x0,y0,z0,x1,y1,z1,+texture,tx0,ty0,tx1,ty1,opacity,pattern,init_hatch); + static unsigned int hatch = ~0U - (~0U>>1); + if (init_hatch) hatch = ~0U - (~0U>>1); + const bool xdir = x0=width()) return *this; + if (xleft<0) { + const float D = (float)xright - xleft; + yleft-=(int)((float)xleft*((float)yright - yleft)/D); + zleft-=(float)xleft*(zright - zleft)/D; + txleft-=(float)xleft*(txright - txleft)/D; + tyleft-=(float)xleft*(tyright - tyleft)/D; + xleft = 0; + } + if (xright>=width()) { + const float d = (float)xright - width(), D = (float)xright - xleft; + yright-=(int)(d*((float)yright - yleft)/D); + zright-=d*(zright - zleft)/D; + txright-=d*(txright - txleft)/D; + tyright-=d*(tyright - tyleft)/D; + xright = width() - 1; + } + if (ydown<0 || yup>=height()) return *this; + if (yup<0) { + const float D = (float)ydown - yup; + xup-=(int)((float)yup*((float)xdown - xup)/D); + zup-=yup*(zdown - zup)/D; + txup-=yup*(txdown - txup)/D; + tyup-=yup*(tydown - tyup)/D; + yup = 0; + } + if (ydown>=height()) { + const float d = (float)ydown - height(), D = (float)ydown - yup; + xdown-=(int)(d*((float)xdown - xup)/D); + zdown-=d*(zdown - zup)/D; + txdown-=d*(txdown - txup)/D; + tydown-=d*(tydown - tyup)/D; + ydown = height() - 1; + } + T *ptrd0 = data(nx0,ny0); + tz *ptrz = zbuffer.data(nx0,ny0); + int dx = xright - xleft, dy = ydown - yup; + const bool steep = dy>dx; + if (steep) cimg::swap(nx0,ny0,nx1,ny1,dx,dy); + const longT + offx = (longT)(nx00?dx:1); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height; + + if (opacity>=1) { + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz) { + *ptrz = (tz)z; + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)*col; ptrd+=whd; col+=twh; } + } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz) { + *ptrz = (tz)z; + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)*col; ptrd+=whd; col+=twh; } + } + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } + } else { + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (~pattern) for (int error = dx>>1, x = 0; x<=dx; ++x) { + if (pattern&hatch) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz) { + *ptrz = (tz)z; + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**col + *ptrd*copacity); ptrd+=whd; col+=twh; } + } + } + hatch>>=1; if (!hatch) hatch = ~0U - (~0U>>1); + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } else for (int error = dx>>1, x = 0; x<=dx; ++x) { + const tzfloat z = Z0 + x*dz/ndx; + if (z>=(tzfloat)*ptrz) { + *ptrz = (tz)z; + const float tx = Tx0 + x*dtx/ndx, ty = Ty0 + x*dty/ndx; + const tc *col = &texture._atXY((int)(tx/z),(int)(ty/z)); + T *ptrd = ptrd0; + cimg_forC(*this,c) { *ptrd = (T)(nopacity**col + *ptrd*copacity); ptrd+=whd; col+=twh; } + } + ptrd0+=offx; ptrz+=offx; + if ((error-=dy)<0) { ptrd0+=offy; ptrz+=offy; error+=dx; } + } + } + return *this; + } + + //! Draw a set of consecutive lines. + /** + \param points Coordinates of vertices, stored as a list of vectors. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If set to true, init hatch motif. + \note + - This function uses several call to the single CImg::draw_line() procedure, + depending on the vectors size in \p points. + **/ + template + CImg& draw_line(const CImg& points, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_line(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + case 2 : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + int ox = x0, oy = y0; + for (unsigned int i = 1; i + CImg& draw_arrow(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1, + const float angle=30, const float length=-10, + const unsigned int pattern=~0U) { + if (is_empty()) return *this; + const float u = (float)(x0 - x1), v = (float)(y0 - y1), sq = u*u + v*v, + deg = (float)(angle*cimg::PI/180), ang = (sq>0)?(float)std::atan2(v,u):0.0f, + l = (length>=0)?length:-length*(float)std::sqrt(sq)/100; + if (sq>0) { + const float + cl = (float)std::cos(ang - deg), sl = (float)std::sin(ang - deg), + cr = (float)std::cos(ang + deg), sr = (float)std::sin(ang + deg); + const int + xl = x1 + (int)(l*cl), yl = y1 + (int)(l*sl), + xr = x1 + (int)(l*cr), yr = y1 + (int)(l*sr), + xc = x1 + (int)((l + 1)*(cl + cr))/2, yc = y1 + (int)((l + 1)*(sl + sr))/2; + draw_line(x0,y0,xc,yc,color,opacity,pattern).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity); + } else draw_point(x0,y0,color,opacity); + return *this; + } + + //! Draw a 2d spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + \note + - The curve is a 2d cubic Bezier spline, from the set of specified starting/ending points + and corresponding velocity vectors. + - The spline is drawn as a serie of connected segments. The \p precision parameter sets the + average number of pixels in each drawn segment. + - A cubic Bezier curve is sometimes defined by a set of 4 points { (\p x0,\p y0), (\p xa,\p ya), + (\p xb,\p yb), (\p x1,\p y1) } where (\p x0,\p y0) is the starting point, (\p x1,\p y1) is the ending point + and (\p xa,\p ya), (\p xb,\p yb) are two + \e control points. + The starting and ending velocities (\p u0,\p v0) and (\p u1,\p v1) can be deduced easily from + the control points as + \p u0 = (\p xa - \p x0), \p v0 = (\p ya - \p y0), \p u1 = (\p x1 - \p xb) and \p v1 = (\p y1 - \p yb). + \par Example: + \code + CImg img(100,100,1,3,0); + const unsigned char color[] = { 255,255,255 }; + img.draw_spline(30,30,0,100,90,40,0,-100,color); + \endcode + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const tc *const color, const float opacity=1, + const float precision=0.25, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Specified color is (null).", + cimg_instance); + if (x0==x1 && y0==y1) return draw_point(x0,y0,color,opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0; + for (float t = 0; t<1; t+=_precision) { + const float t2 = t*t, t3 = t2*t; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), + ny = (int)(ay*t3 + by*t2 + v0*t + y0); + draw_line(ox,oy,nx,ny,color,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; + } + return draw_line(ox,oy,x1,y1,color,opacity,pattern,false); + } + + //! Draw a 3d spline \overloading. + /** + \note + - Similar to CImg::draw_spline() for a 3d spline in a volumetric image. + **/ + template + CImg& draw_spline(const int x0, const int y0, const int z0, const float u0, const float v0, const float w0, + const int x1, const int y1, const int z1, const float u1, const float v1, const float w1, + const tc *const color, const float opacity=1, + const float precision=4, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Specified color is (null).", + cimg_instance); + if (x0==x1 && y0==y1 && z0==z1) return draw_point(x0,y0,z0,color,opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + az = w0 + w1 + 2*(z0 - z1), + bz = 3*(z1 - z0) - 2*w0 - w1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0, oz = z0; + for (float t = 0; t<1; t+=_precision) { + const float t2 = t*t, t3 = t2*t; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t + x0), + ny = (int)(ay*t3 + by*t2 + v0*t + y0), + nz = (int)(az*t3 + bz*t2 + w0*t + z0); + draw_line(ox,oy,oz,nx,ny,nz,color,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; oz = nz; + } + return draw_line(ox,oy,oz,x1,y1,z1,color,opacity,pattern,false); + } + + //! Draw a textured 2d spline. + /** + \param x0 X-coordinate of the starting curve point + \param y0 Y-coordinate of the starting curve point + \param u0 X-coordinate of the starting velocity + \param v0 Y-coordinate of the starting velocity + \param x1 X-coordinate of the ending curve point + \param y1 Y-coordinate of the ending curve point + \param u1 X-coordinate of the ending velocity + \param v1 Y-coordinate of the ending velocity + \param texture Texture image defining line pixel colors. + \param tx0 X-coordinate of the starting texture point. + \param ty0 Y-coordinate of the starting texture point. + \param tx1 X-coordinate of the ending texture point. + \param ty1 Y-coordinate of the ending texture point. + \param precision Curve drawing precision. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch if \c true, reinit hatch motif. + **/ + template + CImg& draw_spline(const int x0, const int y0, const float u0, const float v0, + const int x1, const int y1, const float u1, const float v1, + const CImg& texture, + const int tx0, const int ty0, const int tx1, const int ty1, + const float opacity=1, + const float precision=4, const unsigned int pattern=~0U, + const bool init_hatch=true) { + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_empty()) return *this; + if (is_overlapped(texture)) + return draw_spline(x0,y0,u0,v0,x1,y1,u1,v1,+texture,tx0,ty0,tx1,ty1,precision,opacity,pattern,init_hatch); + if (x0==x1 && y0==y1) + return draw_point(x0,y0,texture.get_vector_at(x0<=0?0:x0>=texture.width()?texture.width() - 1:x0, + y0<=0?0:y0>=texture.height()?texture.height() - 1:y0),opacity); + bool ninit_hatch = init_hatch; + const float + ax = u0 + u1 + 2*(x0 - x1), + bx = 3*(x1 - x0) - 2*u0 - u1, + ay = v0 + v1 + 2*(y0 - y1), + by = 3*(y1 - y0) - 2*v0 - v1, + _precision = 1/(cimg::hypot((float)x0 - x1,(float)y0 - y1)*(precision>0?precision:1)); + int ox = x0, oy = y0, otx = tx0, oty = ty0; + for (float t1 = 0; t1<1; t1+=_precision) { + const float t2 = t1*t1, t3 = t2*t1; + const int + nx = (int)(ax*t3 + bx*t2 + u0*t1 + x0), + ny = (int)(ay*t3 + by*t2 + v0*t1 + y0), + ntx = tx0 + (int)((tx1 - tx0)*t1), + nty = ty0 + (int)((ty1 - ty0)*t1); + draw_line(ox,oy,nx,ny,texture,otx,oty,ntx,nty,opacity,pattern,ninit_hatch); + ninit_hatch = false; + ox = nx; oy = ny; otx = ntx; oty = nty; + } + return draw_line(ox,oy,x1,y1,texture,otx,oty,tx1,ty1,opacity,pattern,false); + } + + //! Draw a set of consecutive splines. + /** + \param points Vertices data. + \param tangents Tangents data. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param is_closed_set Tells if the drawn spline set is closed. + \param precision Precision of the drawing. + \param pattern An integer whose bits describe the line pattern. + \param init_hatch If \c true, init hatch motif. + **/ + template + CImg& draw_spline(const CImg& points, const CImg& tangents, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || !tangents || points._width<2 || tangents._width<2) return *this; + bool ninit_hatch = init_hatch; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + + case 2 : { + const int x0 = (int)points(0,0), y0 = (int)points(0,1); + const float u0 = (float)tangents(0,0), v0 = (float)tangents(0,1); + int ox = x0, oy = y0; + float ou = u0, ov = v0; + for (unsigned int i = 1; i + CImg& draw_spline(const CImg& points, + const tc *const color, const float opacity=1, + const bool is_closed_set=false, const float precision=4, + const unsigned int pattern=~0U, const bool init_hatch=true) { + if (is_empty() || !points || points._width<2) return *this; + CImg tangents; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_spline(): Invalid specified point set (%u,%u,%u,%u,%p).", + cimg_instance, + points._width,points._height,points._depth,points._spectrum,points._data); + case 2 : { + tangents.assign(points._width,points._height); + cimg_forX(points,p) { + const unsigned int + p0 = is_closed_set?(p + points._width - 1)%points._width:(p?p - 1:0), + p1 = is_closed_set?(p + 1)%points._width:(p + 1=0?x0:(x0 - y0*(x2 - x0)/(y2 - y0)), \ + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0 - y0*(x1 - x0)/(y1 - y0))):(x1 - y1*(x2 - x1)/(y2 - y1)), \ + _sxn=1, \ + _sxr=1, \ + _sxl=1, \ + _dxn = x2>x1?x2-x1:(_sxn=-1,x1 - x2), \ + _dxr = x2>x0?x2-x0:(_sxr=-1,x0 - x2), \ + _dxl = x1>x0?x1-x0:(_sxl=-1,x0 - x1), \ + _dyn = y2-y1, \ + _dyr = y2-y0, \ + _dyl = y1-y0, \ + _counter = (_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ + std::min((int)(img)._height - y - 1,y2 - y)), \ + _errn = _dyn/2, \ + _errr = _dyr/2, \ + _errl = _dyl/2, \ + _rxn = _dyn?(x2-x1)/_dyn:0, \ + _rxr = _dyr?(x2-x0)/_dyr:0, \ + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn); \ + _counter>=0; --_counter, ++y, \ + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ + xl+=(y!=y1)?_rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0): \ + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) + +#define _cimg_for_triangle2(img,xl,cl,xr,cr,y,x0,y0,c0,x1,y1,c1,x2,y2,c2) \ + for (int y = y0<0?0:y0, \ + xr = y0>=0?x0:(x0 - y0*(x2 - x0)/(y2 - y0)), \ + cr = y0>=0?c0:(c0 - y0*(c2 - c0)/(y2 - y0)), \ + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0 - y0*(x1 - x0)/(y1 - y0))):(x1 - y1*(x2 - x1)/(y2 - y1)), \ + cl = y1>=0?(y0>=0?(y0==y1?c1:c0):(c0 - y0*(c1 - c0)/(y1 - y0))):(c1 - y1*(c2 - c1)/(y2 - y1)), \ + _sxn=1, _scn=1, \ + _sxr=1, _scr=1, \ + _sxl=1, _scl=1, \ + _dxn = x2>x1?x2-x1:(_sxn=-1,x1 - x2), \ + _dxr = x2>x0?x2-x0:(_sxr=-1,x0 - x2), \ + _dxl = x1>x0?x1-x0:(_sxl=-1,x0 - x1), \ + _dcn = c2>c1?c2-c1:(_scn=-1,c1 - c2), \ + _dcr = c2>c0?c2-c0:(_scr=-1,c0 - c2), \ + _dcl = c1>c0?c1-c0:(_scl=-1,c0 - c1), \ + _dyn = y2-y1, \ + _dyr = y2-y0, \ + _dyl = y1-y0, \ + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ + _dcn-=_dyn?_dyn*(_dcn/_dyn):0, \ + _dcr-=_dyr?_dyr*(_dcr/_dyr):0, \ + _dcl-=_dyl?_dyl*(_dcl/_dyl):0, \ + std::min((int)(img)._height - y - 1,y2 - y)), \ + _errn = _dyn/2, _errcn = _errn, \ + _errr = _dyr/2, _errcr = _errr, \ + _errl = _dyl/2, _errcl = _errl, \ + _rxn = _dyn?(x2 - x1)/_dyn:0, \ + _rcn = _dyn?(c2 - c1)/_dyn:0, \ + _rxr = _dyr?(x2 - x0)/_dyr:0, \ + _rcr = _dyr?(c2 - c0)/_dyr:0, \ + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1-x0)/_dyl:0): \ + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ + _rcl = (y0!=y1 && y1>0)?(_dyl?(c1-c0)/_dyl:0): \ + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcn ); \ + _counter>=0; --_counter, ++y, \ + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ + cr+=_rcr+((_errcr-=_dcr)<0?_errcr+=_dyr,_scr:0), \ + xl+=(y!=y1)?(cl+=_rcl+((_errcl-=_dcl)<0?(_errcl+=_dyl,_scl):0), \ + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcl=_rcn, cl=c1, \ + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1-xl)) + +#define _cimg_for_triangle3(img,xl,txl,tyl,xr,txr,tyr,y,x0,y0,tx0,ty0,x1,y1,tx1,ty1,x2,y2,tx2,ty2) \ + for (int y = y0<0?0:y0, \ + xr = y0>=0?x0:(x0 - y0*(x2 - x0)/(y2 - y0)), \ + txr = y0>=0?tx0:(tx0 - y0*(tx2 - tx0)/(y2 - y0)), \ + tyr = y0>=0?ty0:(ty0 - y0*(ty2 - ty0)/(y2 - y0)), \ + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0 - y0*(x1 - x0)/(y1 - y0))):(x1 - y1*(x2 - x1)/(y2 - y1)), \ + txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0 - y0*(tx1 - tx0)/(y1 - y0))):(tx1 - y1*(tx2 - tx1)/(y2 - y1)), \ + tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0 - y0*(ty1 - ty0)/(y1 - y0))):(ty1 - y1*(ty2 - ty1)/(y2 - y1)), \ + _sxn=1, _stxn=1, _styn=1, \ + _sxr=1, _stxr=1, _styr=1, \ + _sxl=1, _stxl=1, _styl=1, \ + _dxn = x2>x1?x2 - x1:(_sxn=-1,x1 - x2), \ + _dxr = x2>x0?x2 - x0:(_sxr=-1,x0 - x2), \ + _dxl = x1>x0?x1 - x0:(_sxl=-1,x0 - x1), \ + _dtxn = tx2>tx1?tx2 - tx1:(_stxn=-1,tx1 - tx2), \ + _dtxr = tx2>tx0?tx2 - tx0:(_stxr=-1,tx0 - tx2), \ + _dtxl = tx1>tx0?tx1 - tx0:(_stxl=-1,tx0 - tx1), \ + _dtyn = ty2>ty1?ty2 - ty1:(_styn=-1,ty1 - ty2), \ + _dtyr = ty2>ty0?ty2 - ty0:(_styr=-1,ty0 - ty2), \ + _dtyl = ty1>ty0?ty1 - ty0:(_styl=-1,ty0 - ty1), \ + _dyn = y2-y1, \ + _dyr = y2-y0, \ + _dyl = y1-y0, \ + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ + _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \ + _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \ + _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \ + _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \ + _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \ + _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \ + std::min((int)(img)._height - y - 1,y2 - y)), \ + _errn = _dyn/2, _errtxn = _errn, _errtyn = _errn, \ + _errr = _dyr/2, _errtxr = _errr, _errtyr = _errr, \ + _errl = _dyl/2, _errtxl = _errl, _errtyl = _errl, \ + _rxn = _dyn?(x2 - x1)/_dyn:0, \ + _rtxn = _dyn?(tx2 - tx1)/_dyn:0, \ + _rtyn = _dyn?(ty2 - ty1)/_dyn:0, \ + _rxr = _dyr?(x2 - x0)/_dyr:0, \ + _rtxr = _dyr?(tx2 - tx0)/_dyr:0, \ + _rtyr = _dyr?(ty2 - ty0)/_dyr:0, \ + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1 - x0)/_dyl:0): \ + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ + _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1 - tx0)/_dyl:0): \ + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \ + _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1 - ty0)/_dyl:0): \ + (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ); \ + _counter>=0; --_counter, ++y, \ + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ + txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \ + tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \ + xl+=(y!=y1)?(txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \ + tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \ + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \ + _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1,\ + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1 - xl)) + +#define _cimg_for_triangle4(img,xl,cl,txl,tyl,xr,cr,txr,tyr,y,x0,y0,c0,tx0,ty0,x1,y1,c1,tx1,ty1,x2,y2,c2,tx2,ty2) \ + for (int y = y0<0?0:y0, \ + xr = y0>=0?x0:(x0 - y0*(x2 - x0)/(y2 - y0)), \ + cr = y0>=0?c0:(c0 - y0*(c2 - c0)/(y2 - y0)), \ + txr = y0>=0?tx0:(tx0 - y0*(tx2 - tx0)/(y2 - y0)), \ + tyr = y0>=0?ty0:(ty0 - y0*(ty2 - ty0)/(y2 - y0)), \ + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0 - y0*(x1 - x0)/(y1 - y0))):(x1 - y1*(x2 - x1)/(y2 - y1)), \ + cl = y1>=0?(y0>=0?(y0==y1?c1:c0):(c0 - y0*(c1 - c0)/(y1 - y0))):(c1 - y1*(c2 - c1)/(y2 - y1)), \ + txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0 - y0*(tx1 - tx0)/(y1 - y0))):(tx1 - y1*(tx2 - tx1)/(y2 - y1)), \ + tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0 - y0*(ty1 - ty0)/(y1 - y0))):(ty1 - y1*(ty2 - ty1)/(y2 - y1)), \ + _sxn=1, _scn=1, _stxn=1, _styn=1, \ + _sxr=1, _scr=1, _stxr=1, _styr=1, \ + _sxl=1, _scl=1, _stxl=1, _styl=1, \ + _dxn = x2>x1?x2 - x1:(_sxn=-1,x1 - x2), \ + _dxr = x2>x0?x2 - x0:(_sxr=-1,x0 - x2), \ + _dxl = x1>x0?x1 - x0:(_sxl=-1,x0 - x1), \ + _dcn = c2>c1?c2 - c1:(_scn=-1,c1 - c2), \ + _dcr = c2>c0?c2 - c0:(_scr=-1,c0 - c2), \ + _dcl = c1>c0?c1 - c0:(_scl=-1,c0 - c1), \ + _dtxn = tx2>tx1?tx2 - tx1:(_stxn=-1,tx1 - tx2), \ + _dtxr = tx2>tx0?tx2 - tx0:(_stxr=-1,tx0 - tx2), \ + _dtxl = tx1>tx0?tx1 - tx0:(_stxl=-1,tx0 - tx1), \ + _dtyn = ty2>ty1?ty2 - ty1:(_styn=-1,ty1 - ty2), \ + _dtyr = ty2>ty0?ty2 - ty0:(_styr=-1,ty0 - ty2), \ + _dtyl = ty1>ty0?ty1 - ty0:(_styl=-1,ty0 - ty1), \ + _dyn = y2 - y1, \ + _dyr = y2 - y0, \ + _dyl = y1 - y0, \ + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ + _dcn-=_dyn?_dyn*(_dcn/_dyn):0, \ + _dcr-=_dyr?_dyr*(_dcr/_dyr):0, \ + _dcl-=_dyl?_dyl*(_dcl/_dyl):0, \ + _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \ + _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \ + _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \ + _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \ + _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \ + _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \ + std::min((int)(img)._height - y - 1,y2 - y)), \ + _errn = _dyn/2, _errcn = _errn, _errtxn = _errn, _errtyn = _errn, \ + _errr = _dyr/2, _errcr = _errr, _errtxr = _errr, _errtyr = _errr, \ + _errl = _dyl/2, _errcl = _errl, _errtxl = _errl, _errtyl = _errl, \ + _rxn = _dyn?(x2 - x1)/_dyn:0, \ + _rcn = _dyn?(c2 - c1)/_dyn:0, \ + _rtxn = _dyn?(tx2 - tx1)/_dyn:0, \ + _rtyn = _dyn?(ty2 - ty1)/_dyn:0, \ + _rxr = _dyr?(x2 - x0)/_dyr:0, \ + _rcr = _dyr?(c2 - c0)/_dyr:0, \ + _rtxr = _dyr?(tx2 - tx0)/_dyr:0, \ + _rtyr = _dyr?(ty2 - ty0)/_dyr:0, \ + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1 - x0)/_dyl:0): \ + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ + _rcl = (y0!=y1 && y1>0)?(_dyl?(c1 - c0)/_dyl:0): \ + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcn ), \ + _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1 - tx0)/_dyl:0): \ + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \ + _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1 - ty0)/_dyl:0): \ + (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ); \ + _counter>=0; --_counter, ++y, \ + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ + cr+=_rcr+((_errcr-=_dcr)<0?_errcr+=_dyr,_scr:0), \ + txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \ + tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \ + xl+=(y!=y1)?(cl+=_rcl+((_errcl-=_dcl)<0?(_errcl+=_dyl,_scl):0), \ + txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \ + tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \ + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ + (_errcl=_errcn, _dcl=_dcn, _dyl=_dyn, _scl=_scn, _rcl=_rcn, cl=c1, \ + _errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \ + _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1, \ + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1 - xl)) + +#define _cimg_for_triangle5(img,xl,txl,tyl,lxl,lyl,xr,txr,tyr,lxr,lyr,y,x0,y0,\ + tx0,ty0,lx0,ly0,x1,y1,tx1,ty1,lx1,ly1,x2,y2,tx2,ty2,lx2,ly2) \ + for (int y = y0<0?0:y0, \ + xr = y0>=0?x0:(x0 - y0*(x2 - x0)/(y2 - y0)), \ + txr = y0>=0?tx0:(tx0 - y0*(tx2 - tx0)/(y2 - y0)), \ + tyr = y0>=0?ty0:(ty0 - y0*(ty2 - ty0)/(y2 - y0)), \ + lxr = y0>=0?lx0:(lx0 - y0*(lx2 - lx0)/(y2 - y0)), \ + lyr = y0>=0?ly0:(ly0 - y0*(ly2 - ly0)/(y2 - y0)), \ + xl = y1>=0?(y0>=0?(y0==y1?x1:x0):(x0 - y0*(x1 - x0)/(y1 - y0))):(x1 - y1*(x2 - x1)/(y2 - y1)), \ + txl = y1>=0?(y0>=0?(y0==y1?tx1:tx0):(tx0 - y0*(tx1 - tx0)/(y1 - y0))):(tx1 - y1*(tx2 - tx1)/(y2 - y1)), \ + tyl = y1>=0?(y0>=0?(y0==y1?ty1:ty0):(ty0 - y0*(ty1 - ty0)/(y1 - y0))):(ty1 - y1*(ty2 - ty1)/(y2 - y1)), \ + lxl = y1>=0?(y0>=0?(y0==y1?lx1:lx0):(lx0 - y0*(lx1 - lx0)/(y1 - y0))):(lx1 - y1*(lx2 - lx1)/(y2 - y1)), \ + lyl = y1>=0?(y0>=0?(y0==y1?ly1:ly0):(ly0 - y0*(ly1 - ly0)/(y1 - y0))):(ly1 - y1*(ly2 - ly1)/(y2 - y1)), \ + _sxn=1, _stxn=1, _styn=1, _slxn=1, _slyn=1, \ + _sxr=1, _stxr=1, _styr=1, _slxr=1, _slyr=1, \ + _sxl=1, _stxl=1, _styl=1, _slxl=1, _slyl=1, \ + _dxn = x2>x1?x2 - x1:(_sxn=-1,x1 - x2), _dyn = y2 - y1, \ + _dxr = x2>x0?x2 - x0:(_sxr=-1,x0 - x2), _dyr = y2 - y0, \ + _dxl = x1>x0?x1 - x0:(_sxl=-1,x0 - x1), _dyl = y1 - y0, \ + _dtxn = tx2>tx1?tx2 - tx1:(_stxn=-1,tx1 - tx2), \ + _dtxr = tx2>tx0?tx2 - tx0:(_stxr=-1,tx0 - tx2), \ + _dtxl = tx1>tx0?tx1 - tx0:(_stxl=-1,tx0 - tx1), \ + _dtyn = ty2>ty1?ty2 - ty1:(_styn=-1,ty1 - ty2), \ + _dtyr = ty2>ty0?ty2 - ty0:(_styr=-1,ty0 - ty2), \ + _dtyl = ty1>ty0?ty1 - ty0:(_styl=-1,ty0 - ty1), \ + _dlxn = lx2>lx1?lx2 - lx1:(_slxn=-1,lx1 - lx2), \ + _dlxr = lx2>lx0?lx2 - lx0:(_slxr=-1,lx0 - lx2), \ + _dlxl = lx1>lx0?lx1 - lx0:(_slxl=-1,lx0 - lx1), \ + _dlyn = ly2>ly1?ly2 - ly1:(_slyn=-1,ly1 - ly2), \ + _dlyr = ly2>ly0?ly2 - ly0:(_slyr=-1,ly0 - ly2), \ + _dlyl = ly1>ly0?ly1 - ly0:(_slyl=-1,ly0 - ly1), \ + _counter =(_dxn-=_dyn?_dyn*(_dxn/_dyn):0, \ + _dxr-=_dyr?_dyr*(_dxr/_dyr):0, \ + _dxl-=_dyl?_dyl*(_dxl/_dyl):0, \ + _dtxn-=_dyn?_dyn*(_dtxn/_dyn):0, \ + _dtxr-=_dyr?_dyr*(_dtxr/_dyr):0, \ + _dtxl-=_dyl?_dyl*(_dtxl/_dyl):0, \ + _dtyn-=_dyn?_dyn*(_dtyn/_dyn):0, \ + _dtyr-=_dyr?_dyr*(_dtyr/_dyr):0, \ + _dtyl-=_dyl?_dyl*(_dtyl/_dyl):0, \ + _dlxn-=_dyn?_dyn*(_dlxn/_dyn):0, \ + _dlxr-=_dyr?_dyr*(_dlxr/_dyr):0, \ + _dlxl-=_dyl?_dyl*(_dlxl/_dyl):0, \ + _dlyn-=_dyn?_dyn*(_dlyn/_dyn):0, \ + _dlyr-=_dyr?_dyr*(_dlyr/_dyr):0, \ + _dlyl-=_dyl?_dyl*(_dlyl/_dyl):0, \ + std::min((int)(img)._height - y - 1,y2 - y)), \ + _errn = _dyn/2, _errtxn = _errn, _errtyn = _errn, _errlxn = _errn, _errlyn = _errn, \ + _errr = _dyr/2, _errtxr = _errr, _errtyr = _errr, _errlxr = _errr, _errlyr = _errr, \ + _errl = _dyl/2, _errtxl = _errl, _errtyl = _errl, _errlxl = _errl, _errlyl = _errl, \ + _rxn = _dyn?(x2 - x1)/_dyn:0, \ + _rtxn = _dyn?(tx2 - tx1)/_dyn:0, \ + _rtyn = _dyn?(ty2 - ty1)/_dyn:0, \ + _rlxn = _dyn?(lx2 - lx1)/_dyn:0, \ + _rlyn = _dyn?(ly2 - ly1)/_dyn:0, \ + _rxr = _dyr?(x2 - x0)/_dyr:0, \ + _rtxr = _dyr?(tx2 - tx0)/_dyr:0, \ + _rtyr = _dyr?(ty2 - ty0)/_dyr:0, \ + _rlxr = _dyr?(lx2 - lx0)/_dyr:0, \ + _rlyr = _dyr?(ly2 - ly0)/_dyr:0, \ + _rxl = (y0!=y1 && y1>0)?(_dyl?(x1 - x0)/_dyl:0): \ + (_errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxn), \ + _rtxl = (y0!=y1 && y1>0)?(_dyl?(tx1 - tx0)/_dyl:0): \ + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxn ), \ + _rtyl = (y0!=y1 && y1>0)?(_dyl?(ty1 - ty0)/_dyl:0): \ + (_errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyn ), \ + _rlxl = (y0!=y1 && y1>0)?(_dyl?(lx1 - lx0)/_dyl:0): \ + (_errlxl=_errlxn, _dlxl=_dlxn, _dyl=_dyn, _slxl=_slxn, _rlxn ), \ + _rlyl = (y0!=y1 && y1>0)?(_dyl?(ly1 - ly0)/_dyl:0): \ + (_errlyl=_errlyn, _dlyl=_dlyn, _dyl=_dyn, _slyl=_slyn, _rlyn ); \ + _counter>=0; --_counter, ++y, \ + xr+=_rxr+((_errr-=_dxr)<0?_errr+=_dyr,_sxr:0), \ + txr+=_rtxr+((_errtxr-=_dtxr)<0?_errtxr+=_dyr,_stxr:0), \ + tyr+=_rtyr+((_errtyr-=_dtyr)<0?_errtyr+=_dyr,_styr:0), \ + lxr+=_rlxr+((_errlxr-=_dlxr)<0?_errlxr+=_dyr,_slxr:0), \ + lyr+=_rlyr+((_errlyr-=_dlyr)<0?_errlyr+=_dyr,_slyr:0), \ + xl+=(y!=y1)?(txl+=_rtxl+((_errtxl-=_dtxl)<0?(_errtxl+=_dyl,_stxl):0), \ + tyl+=_rtyl+((_errtyl-=_dtyl)<0?(_errtyl+=_dyl,_styl):0), \ + lxl+=_rlxl+((_errlxl-=_dlxl)<0?(_errlxl+=_dyl,_slxl):0), \ + lyl+=_rlyl+((_errlyl-=_dlyl)<0?(_errlyl+=_dyl,_slyl):0), \ + _rxl+((_errl-=_dxl)<0?(_errl+=_dyl,_sxl):0)): \ + (_errtxl=_errtxn, _dtxl=_dtxn, _dyl=_dyn, _stxl=_stxn, _rtxl=_rtxn, txl=tx1, \ + _errtyl=_errtyn, _dtyl=_dtyn, _dyl=_dyn, _styl=_styn, _rtyl=_rtyn, tyl=ty1, \ + _errlxl=_errlxn, _dlxl=_dlxn, _dyl=_dyn, _slxl=_slxn, _rlxl=_rlxn, lxl=lx1, \ + _errlyl=_errlyn, _dlyl=_dlyn, _dyl=_dyn, _slyl=_slyn, _rlyl=_rlyn, lyl=ly1, \ + _errl=_errn, _dxl=_dxn, _dyl=_dyn, _sxl=_sxn, _rxl=_rxn, x1 - xl)) + + // [internal] Draw a filled triangle. + template + CImg& _draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity, + const float brightness) { + cimg_init_scanline(color,opacity); + const float nbrightness = cimg::cut(brightness,0,2); + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2); + if (ny0=0) { + if ((nx1 - nx0)*(ny2 - ny0) - (nx2 - nx0)*(ny1 - ny0)<0) + _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2) + cimg_draw_scanline(xl,xr,y,color,opacity,nbrightness); + else + _cimg_for_triangle1(*this,xl,xr,y,nx0,ny0,nx1,ny1,nx2,ny2) + cimg_draw_scanline(xr,xl,y,color,opacity,nbrightness); + } + return *this; + } + + //! Draw a filled 2d triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + _draw_triangle(x0,y0,x1,y1,x2,y2,color,opacity,1); + return *this; + } + + //! Draw a outlined 2d triangle. + /** + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + draw_line(x0,y0,x1,y1,color,opacity,pattern,true). + draw_line(x1,y1,x2,y2,color,opacity,pattern,false). + draw_line(x2,y2,x0,y0,color,opacity,pattern,false); + return *this; + } + + //! Draw a filled 2d triangle, with z-buffering. + /** + \param zbuffer Z-buffer image. + \param x0 X-coordinate of the first vertex. + \param y0 Y-coordinate of the first vertex. + \param z0 Z-coordinate of the first vertex. + \param x1 X-coordinate of the second vertex. + \param y1 Y-coordinate of the second vertex. + \param z1 Z-coordinate of the second vertex. + \param x2 X-coordinate of the third vertex. + \param y2 Y-coordinate of the third vertex. + \param z2 Z-coordinate of the third vertex. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + \param brightness Brightness factor. + **/ + template + CImg& draw_triangle(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const tc *const color, const float opacity=1, + const float brightness=1) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float + nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f), + nbrightness = cimg::cut(brightness,0,2); + const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; + tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nz0,nz2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nz1,nz2); + if (ny0>=height() || ny2<0) return *this; + tzfloat + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); + _cimg_for_triangle1(*this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) { + if (y==ny1) { zl = nz1; pzl = pzn; } + int xleft = xleft0, xright = xright0; + tzfloat zleft = zl, zright = zr; + if (xright=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + tz *ptrz = xleft<=xright?zbuffer.data(xleft,y):0; + if (opacity>=1) { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } + ptrd-=offx; + } + zleft+=pentez; + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; cimg_forC(*this,c) { *ptrd = (T)(nbrightness*(*col++)); ptrd+=whd; } + ptrd-=offx; + } + zleft+=pentez; + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + cimg_forC(*this,c) { *ptrd = (T)((2 - nbrightness)**(col++) + (nbrightness - 1)*maxval); ptrd+=whd; } + ptrd-=offx; + } + zleft+=pentez; + } + } else { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; cimg_forC(*this,c) { *ptrd = (T)(nopacity**(col++) + *ptrd*copacity); ptrd+=whd; } + ptrd-=offx; + } + zleft+=pentez; + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + cimg_forC(*this,c) { *ptrd = (T)(nopacity*nbrightness**(col++) + *ptrd*copacity); ptrd+=whd; } + ptrd-=offx; + } + zleft+=pentez; + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + cimg_forC(*this,c) { + const T val = (T)((2 - nbrightness)**(col++) + (nbrightness - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; + } + ptrd-=offx; + } + zleft+=pentez; + } + } + zr+=pzr; zl+=pzl; + } + return *this; + } + + //! Draw a Gouraud-shaded 2d triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param brightness0 Brightness factor of the first vertex (in [0,2]). + \param brightness1 brightness factor of the second vertex (in [0,2]). + \param brightness2 brightness factor of the third vertex (in [0,2]). + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, + const float brightness0, + const float brightness1, + const float brightness2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f), + nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f), + nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f); + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nc0,nc1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nc0,nc2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nc1,nc2); + if (ny0>=height() || ny2<0) return *this; + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { + int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0; + if (xrightcleft?cright - cleft:cleft - cright, + rc = dx?(cright - cleft)/dx:0, + sc = cright>cleft?1:-1, + ndc = dc - (dx?dx*(dc/dx):0); + int errc = dx>>1; + if (xleft<0 && dx) cleft-=xleft*(cright - cleft)/dx; + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y); + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { + const tc *col = color; + cimg_forC(*this,c) { + *ptrd = (T)(cleft<256?cleft**(col++)/256:((512 - cleft)**(col++)+(cleft - 256)*maxval)/256); + ptrd+=whd; + } + ptrd-=offx; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } else for (int x = xleft; x<=xright; ++x) { + const tc *col = color; + cimg_forC(*this,c) { + const T val = (T)(cleft<256?cleft**(col++)/256:((512 - cleft)**(col++)+(cleft - 256)*maxval)/256); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; + } + ptrd-=offx; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } + } + return *this; + } + + //! Draw a Gouraud-shaded 2d triangle, with z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const tc *const color, + const float brightness0, + const float brightness1, + const float brightness2, + const float opacity=1) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const longT whd = (longT)width()*height()*depth(), offx = spectrum()*whd; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f), + nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f), + nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f); + tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1,nc0,nc1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nz0,nz2,nc0,nc2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nz1,nz2,nc1,nc2); + if (ny0>=height() || ny2<0) return *this; + tzfloat + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { + if (y==ny1) { zl = nz1; pzl = pzn; } + int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0; + tzfloat zleft = zl, zright = zr; + if (xrightcleft?cright - cleft:cleft - cright, + rc = dx?(cright - cleft)/dx:0, + sc = cright>cleft?1:-1, + ndc = dc - (dx?dx*(dc/dx):0); + const tzfloat pentez = (zright - zleft)/dx; + int errc = dx>>1; + if (xleft<0 && dx) { + cleft-=xleft*(cright - cleft)/dx; + zleft-=xleft*(zright - zleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T *ptrd = data(xleft,y); + tz *ptrz = xleft<=xright?zbuffer.data(xleft,y):0; + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + cimg_forC(*this,c) { + *ptrd = (T)(cleft<256?cleft**(col++)/256:((512 - cleft)**(col++)+(cleft - 256)*maxval)/256); + ptrd+=whd; + } + ptrd-=offx; + } + zleft+=pentez; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } else for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + cimg_forC(*this,c) { + const T val = (T)(cleft<256?cleft**(col++)/256:((512 - cleft)**(col++)+(cleft - 256)*maxval)/256); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; + } + ptrd-=offx; + } + zleft+=pentez; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } + zr+=pzr; zl+=pzl; + } + return *this; + } + + //! Draw a color-interpolated 2d triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color1 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the first vertex. + \param color2 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the seconf vertex. + \param color3 Pointer to \c spectrum() consecutive values of type \c T, defining the color of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc1 *const color1, + const tc2 *const color2, + const tc3 *const color3, + const float opacity=1) { + const unsigned char one = 1; + cimg_forC(*this,c) + get_shared_channel(c).draw_triangle(x0,y0,x1,y1,x2,y2,&one,color1[c],color2[c],color3[c],opacity); + return *this; + } + + //! Draw a textured 2d triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param opacity Drawing opacity. + \param brightness Brightness factor of the drawing (in [0,2]). + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + static const T maxval = (T)std::min(cimg::type::max(),cimg::type::max()); + const float + nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f), + nbrightness = cimg::cut(brightness,0,2); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + offx = _spectrum*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2); + if (ny0>=height() || ny2<0) return *this; + _cimg_for_triangle3(*this,xleft0,txleft0,tyleft0,xright0,txright0,tyright0,y, + nx0,ny0,ntx0,nty0,nx1,ny1,ntx1,nty1,nx2,ny2,ntx2,nty2) { + int + xleft = xleft0, xright = xright0, + txleft = txleft0, txright = txright0, + tyleft = tyleft0, tyright = tyright0; + if (xrighttxleft?txright - txleft:txleft - txright, + dty = tyright>tyleft?tyright - tyleft:tyleft - tyright, + rtx = dx?(txright - txleft)/dx:0, + rty = dx?(tyright - tyleft)/dx:0, + stx = txright>txleft?1:-1, + sty = tyright>tyleft?1:-1, + ndtx = dtx - (dx?dx*(dtx/dx):0), + ndty = dty - (dx?dx*(dty/dx):0); + int errtx = dx>>1, errty = errtx; + if (xleft<0 && dx) { + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + *ptrd = (T)*col; + ptrd+=whd; col+=twh; + } + ptrd-=offx; + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + *ptrd = (T)(nbrightness**col); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } else for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + *ptrd = (T)((2 - nbrightness)**(col++) + (nbrightness - 1)*maxval); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } + } else { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + *ptrd = (T)(nopacity**col + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } else for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + const T val = (T)((2 - nbrightness)**(col++) + (nbrightness - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } + } + } + return *this; + } + + //! Draw a 2d textured triangle, with perspective correction. + template + CImg& draw_triangle(const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const float opacity=1, + const float brightness=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float + nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f), + nbrightness = cimg::cut(brightness,0,2); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + offx = _spectrum*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; + float + ntx0 = tx0/z0, nty0 = ty0/z0, + ntx1 = tx1/z1, nty1 = ty1/z1, + ntx2 = tx2/z2, nty2 = ty2/z2, + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2); + if (ny0>=height() || ny2<0) return *this; + float + ptxl = (ntx1 - ntx0)/(ny1 - ny0), + ptxr = (ntx2 - ntx0)/(ny2 - ny0), + ptxn = (ntx2 - ntx1)/(ny2 - ny1), + ptyl = (nty1 - nty0)/(ny1 - ny0), + ptyr = (nty2 - nty0)/(ny2 - ny0), + ptyn = (nty2 - nty1)/(ny2 - ny1), + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))): + (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))): + (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); + _cimg_for_triangle1(*this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) { + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } + int xleft = xleft0, xright = xright0; + float + zleft = zl, zright = zr, + txleft = txl, txright = txr, + tyleft = tyl, tyright = tyr; + if (xright=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)*col; + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else if (nbrightness<1) for (int x=xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(nbrightness**col); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)((2 - nbrightness)**col + (nbrightness - 1)*maxval); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } + } else { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(nopacity**col + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + const T val = (T)((2 - nbrightness)**col + (nbrightness - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } + } + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; + } + return *this; + } + + //! Draw a textured 2d triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const float opacity=1, + const float brightness=1) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,opacity,brightness); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float + nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f), + nbrightness = cimg::cut(brightness,0,2); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + offx = _spectrum*whd; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2; + float + ntx0 = tx0/z0, nty0 = ty0/z0, + ntx1 = tx1/z1, nty1 = ty1/z1, + ntx2 = tx2/z2, nty2 = ty2/z2; + tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2); + if (ny0>=height() || ny2<0) return *this; + float + ptxl = (ntx1 - ntx0)/(ny1 - ny0), + ptxr = (ntx2 - ntx0)/(ny2 - ny0), + ptxn = (ntx2 - ntx1)/(ny2 - ny1), + ptyl = (nty1 - nty0)/(ny1 - ny0), + ptyr = (nty2 - nty0)/(ny2 - ny0), + ptyn = (nty2 - nty1)/(ny2 - ny1), + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))): + (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))): + (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); + tzfloat + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); + _cimg_for_triangle1(*this,xleft0,xright0,y,nx0,ny0,nx1,ny1,nx2,ny2) { + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } + int xleft = xleft0, xright = xright0; + float txleft = txl, txright = txr, tyleft = tyl, tyright = tyr; + tzfloat zleft = zl, zright = zr; + if (xright=width() - 1) xright = width() - 1; + T *ptrd = data(xleft,y,0,0); + tz *ptrz = zbuffer.data(xleft,y); + if (opacity>=1) { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)*col; + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(nbrightness**col); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)((2 - nbrightness)**col + (nbrightness - 1)*maxval); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } + } else { + if (nbrightness==1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(nopacity**col + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else if (nbrightness<1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(nopacity*nbrightness**col + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + const T val = (T)((2 - nbrightness)**col + (nbrightness - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + } + } + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; + } + return *this; + } + + //! Draw a Phong-shaded 2d triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const tc *const color, + const CImg& light, + const int lx0, const int ly0, + const int lx1, const int ly1, + const int lx2, const int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(light)) return draw_triangle(x0,y0,x1,y1,x2,y2,color,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; + const ulongT + whd = (ulongT)_width*_height*_depth, + lwh = (ulongT)light._width*light._height, + offx = _spectrum*whd - 1; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2); + if (ny0>=height() || ny2<0) return *this; + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { + int + xleft = xleft0, xright = xright0, + lxleft = lxleft0, lxright = lxright0, + lyleft = lyleft0, lyright = lyright0; + if (xrightlxleft?lxright - lxleft:lxleft - lxright, + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, + rlx = dx?(lxright - lxleft)/dx:0, + rly = dx?(lyright - lyleft)/dx:0, + slx = lxright>lxleft?1:-1, + sly = lyright>lyleft?1:-1, + ndlx = dlx - (dx?dx*(dlx/dx):0), + ndly = dly - (dx?dx*(dly/dx):0); + int errlx = dx>>1, errly = errlx; + if (xleft<0 && dx) { + lxleft-=xleft*(lxright - lxleft)/dx; + lyleft-=xleft*(lyright - lyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { + const tc *col = color; + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + *ptrd = (T)(l<1?l**(col++):((2 - l)**(col++) + (l - 1)*maxval)); + ptrd+=whd; lig+=lwh; + } + ptrd-=offx; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } else for (int x = xleft; x<=xright; ++x) { + const tc *col = color; + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + const T val = (T)(l<1?l**(col++):((2 - l)**(col++) + (l - 1)*maxval)); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; lig+=lwh; + } + ptrd-=offx; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } + } + return *this; + } + + //! Draw a Phong-shaded 2d triangle, with z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const tc *const color, + const CImg& light, + const int lx0, const int ly0, + const int lx1, const int ly1, + const int lx2, const int ly2, + const float opacity=1) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Specified color is (null).", + cimg_instance); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (is_overlapped(light)) return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + lwh = (ulongT)light._width*light._height, + offx = _spectrum*whd; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; + tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1,nz0,nz1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2,nz0,nz2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2,nz1,nz2); + if (ny0>=height() || ny2<0) return *this; + tzfloat + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { + if (y==ny1) { zl = nz1; pzl = pzn; } + int + xleft = xleft0, xright = xright0, + lxleft = lxleft0, lxright = lxright0, + lyleft = lyleft0, lyright = lyright0; + tzfloat zleft = zl, zright = zr; + if (xrightlxleft?lxright - lxleft:lxleft - lxright, + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, + rlx = dx?(lxright - lxleft)/dx:0, + rly = dx?(lyright - lyleft)/dx:0, + slx = lxright>lxleft?1:-1, + sly = lyright>lyleft?1:-1, + ndlx = dlx - (dx?dx*(dlx/dx):0), + ndly = dly - (dx?dx*(dly/dx):0); + const tzfloat pentez = (zright - zleft)/dx; + int errlx = dx>>1, errly = errlx; + if (xleft<0 && dx) { + zleft-=xleft*(zright - zleft)/dx; + lxleft-=xleft*(lxright - lxleft)/dx; + lyleft-=xleft*(lyright - lyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T *ptrd = data(xleft,y,0,0); + tz *ptrz = xleft<=xright?zbuffer.data(xleft,y):0; + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + const tc cval = *(col++); + *ptrd = (T)(l<1?l*cval:(2 - l)*cval + (l - 1)*maxval); + ptrd+=whd; lig+=lwh; + } + ptrd-=offx; + } + zleft+=pentez; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tc *col = color; + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + const tc cval = *(col++); + const T val = (T)(l<1?l*cval:(2 - l)*cval + (l - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; lig+=lwh; + } + ptrd-=offx; + } + zleft+=pentez; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } + zr+=pzr; zl+=pzl; + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2d triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param brightness0 Brightness factor of the first vertex. + \param brightness1 Brightness factor of the second vertex. + \param brightness2 Brightness factor of the third vertex. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const float brightness0, + const float brightness1, + const float brightness2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + brightness0,brightness1,brightness2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + offx = _spectrum*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2, + nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f), + nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f), + nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f); + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nc0,nc1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nc0,nc2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nc1,nc2); + if (ny0>=height() || ny2<0) return *this; + _cimg_for_triangle4(*this,xleft0,cleft0,txleft0,tyleft0,xright0,cright0,txright0,tyright0,y, + nx0,ny0,nc0,ntx0,nty0,nx1,ny1,nc1,ntx1,nty1,nx2,ny2,nc2,ntx2,nty2) { + int + xleft = xleft0, xright = xright0, + cleft = cleft0, cright = cright0, + txleft = txleft0, txright = txright0, + tyleft = tyleft0, tyright = tyright0; + if (xrightcleft?cright - cleft:cleft - cright, + dtx = txright>txleft?txright - txleft:txleft - txright, + dty = tyright>tyleft?tyright - tyleft:tyleft - tyright, + rc = dx?(cright - cleft)/dx:0, + rtx = dx?(txright - txleft)/dx:0, + rty = dx?(tyright - tyleft)/dx:0, + sc = cright>cleft?1:-1, + stx = txright>txleft?1:-1, + sty = tyright>tyleft?1:-1, + ndc = dc - (dx?dx*(dc/dx):0), + ndtx = dtx - (dx?dx*(dtx/dx):0), + ndty = dty - (dx?dx*(dty/dx):0); + int errc = dx>>1, errtx = errc, errty = errc; + if (xleft<0 && dx) { + cleft-=xleft*(cright - cleft)/dx; + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + *ptrd = (T)(cleft<256?cleft**col/256:((512 - cleft)**col + (cleft - 256)*maxval)/256); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } else for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + cimg_forC(*this,c) { + const T val = (T)(cleft<256?cleft**col/256:((512 - cleft)**col + (cleft - 256)*maxval)/256); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2d triangle, with perspective correction \overloading. + template + CImg& draw_triangle(const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const float brightness0, + const float brightness1, + const float brightness2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + brightness0,brightness1,brightness2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + offx = _spectrum*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f), + nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f), + nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f); + float + ntx0 = tx0/z0, nty0 = ty0/z0, + ntx1 = tx1/z1, nty1 = ty1/z1, + ntx2 = tx2/z2, nty2 = ty2/z2, + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1,nc0,nc1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2,nc0,nc2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2,nc1,nc2); + if (ny0>=height() || ny2<0) return *this; + float + ptxl = (ntx1 - ntx0)/(ny1 - ny0), + ptxr = (ntx2 - ntx0)/(ny2 - ny0), + ptxn = (ntx2 - ntx1)/(ny2 - ny1), + ptyl = (nty1 - nty0)/(ny1 - ny0), + ptyr = (nty2 - nty0)/(ny2 - ny0), + ptyn = (nty2 - nty1)/(ny2 - ny1), + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))): + (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))): + (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } + int + xleft = xleft0, xright = xright0, + cleft = cleft0, cright = cright0; + float + zleft = zl, zright = zr, + txleft = txl, txright = txr, + tyleft = tyl, tyright = tyr; + if (xrightcleft?cright - cleft:cleft - cright, + rc = dx?(cright - cleft)/dx:0, + sc = cright>cleft?1:-1, + ndc = dc - (dx?dx*(dc/dx):0); + const float + pentez = (zright - zleft)/dx, + pentetx = (txright - txleft)/dx, + pentety = (tyright - tyleft)/dx; + int errc = dx>>1; + if (xleft<0 && dx) { + cleft-=xleft*(cright - cleft)/dx; + zleft-=xleft*(zright - zleft)/dx; + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(cleft<256?cleft**col/256:((512 - cleft)**col + (cleft - 256)*maxval)/256); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } else for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + const T val = (T)(cleft<256?cleft**col/256:((512 - cleft)**col + (cleft - 256)*maxval)/256); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; + } + return *this; + } + + //! Draw a textured Gouraud-shaded 2d triangle, with perspective correction and z-buffering \overloading. + template + CImg& draw_triangle(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const float brightness0, + const float brightness1, + const float brightness2, + const float opacity=1) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + brightness0,brightness1,brightness2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + offx = _spectrum*whd; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nc0 = (int)((brightness0<0.0f?0.0f:(brightness0>2.0f?2.0f:brightness0))*256.0f), + nc1 = (int)((brightness1<0.0f?0.0f:(brightness1>2.0f?2.0f:brightness1))*256.0f), + nc2 = (int)((brightness2<0.0f?0.0f:(brightness2>2.0f?2.0f:brightness2))*256.0f); + float + ntx0 = tx0/z0, nty0 = ty0/z0, + ntx1 = tx1/z1, nty1 = ty1/z1, + ntx2 = tx2/z2, nty2 = ty2/z2; + tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nz0,nz1,nc0,nc1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nz0,nz2,nc0,nc2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nz1,nz2,nc1,nc2); + if (ny0>=height() || ny2<0) return *this; + float + ptxl = (ntx1 - ntx0)/(ny1 - ny0), + ptxr = (ntx2 - ntx0)/(ny2 - ny0), + ptxn = (ntx2 - ntx1)/(ny2 - ny1), + ptyl = (nty1 - nty0)/(ny1 - ny0), + ptyr = (nty2 - nty0)/(ny2 - ny0), + ptyn = (nty2 - nty1)/(ny2 - ny1), + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))): + (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))): + (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); + tzfloat + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); + _cimg_for_triangle2(*this,xleft0,cleft0,xright0,cright0,y,nx0,ny0,nc0,nx1,ny1,nc1,nx2,ny2,nc2) { + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } + int xleft = xleft0, xright = xright0, cleft = cleft0, cright = cright0; + float txleft = txl, txright = txr, tyleft = tyl, tyright = tyr; + tzfloat zleft = zl, zright = zr; + if (xrightcleft?cright - cleft:cleft - cright, + rc = dx?(cright - cleft)/dx:0, + sc = cright>cleft?1:-1, + ndc = dc - (dx?dx*(dc/dx):0); + float pentetx = (txright - txleft)/dx, pentety = (tyright - tyleft)/dx; + const tzfloat pentez = (zright - zleft)/dx; + int errc = dx>>1; + if (xleft<0 && dx) { + cleft-=xleft*(cright - cleft)/dx; + zleft-=xleft*(zright - zleft)/dx; + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y); + tz *ptrz = zbuffer.data(xleft,y); + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + *ptrd = (T)(cleft<256?cleft**col/256:((512 - cleft)**col + (cleft - 256)*maxval)/256); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } else for (int x = xleft; x<=xright; ++x, ++ptrd, ++ptrz) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + cimg_forC(*this,c) { + const T val = (T)(cleft<256?cleft**col/256:((512 - cleft)**col + (cleft - 256)*maxval)/256); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + cleft+=rc+((errc-=ndc)<0?errc+=dx,sc:0); + } + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; + } + return *this; + } + + //! Draw a textured Phong-shaded 2d triangle. + /** + \param x0 X-coordinate of the first vertex in the image instance. + \param y0 Y-coordinate of the first vertex in the image instance. + \param x1 X-coordinate of the second vertex in the image instance. + \param y1 Y-coordinate of the second vertex in the image instance. + \param x2 X-coordinate of the third vertex in the image instance. + \param y2 Y-coordinate of the third vertex in the image instance. + \param texture Texture image used to fill the triangle. + \param tx0 X-coordinate of the first vertex in the texture image. + \param ty0 Y-coordinate of the first vertex in the texture image. + \param tx1 X-coordinate of the second vertex in the texture image. + \param ty1 Y-coordinate of the second vertex in the texture image. + \param tx2 X-coordinate of the third vertex in the texture image. + \param ty2 Y-coordinate of the third vertex in the texture image. + \param light Light image. + \param lx0 X-coordinate of the first vertex in the light image. + \param ly0 Y-coordinate of the first vertex in the light image. + \param lx1 X-coordinate of the second vertex in the light image. + \param ly1 Y-coordinate of the second vertex in the light image. + \param lx2 X-coordinate of the third vertex in the light image. + \param ly2 Y-coordinate of the third vertex in the light image. + \param opacity Drawing opacity. + **/ + template + CImg& draw_triangle(const int x0, const int y0, + const int x1, const int y1, + const int x2, const int y2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const CImg& light, + const int lx0, const int ly0, + const int lx1, const int ly1, + const int lx2, const int ly2, + const float opacity=1) { + if (is_empty()) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,x1,y1,x2,y2,+texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,x1,y1,x2,y2,texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + lwh = (ulongT)light._width*light._height, + offx = _spectrum*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + ntx0 = tx0, nty0 = ty0, ntx1 = tx1, nty1 = ty1, ntx2 = tx2, nty2 = ty2, + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2); + if (ny0>=height() || ny2<0) return *this; + _cimg_for_triangle5(*this,xleft0,lxleft0,lyleft0,txleft0,tyleft0,xright0,lxright0,lyright0,txright0,tyright0,y, + nx0,ny0,nlx0,nly0,ntx0,nty0,nx1,ny1,nlx1,nly1,ntx1,nty1,nx2,ny2,nlx2,nly2,ntx2,nty2) { + int + xleft = xleft0, xright = xright0, + lxleft = lxleft0, lxright = lxright0, + lyleft = lyleft0, lyright = lyright0, + txleft = txleft0, txright = txright0, + tyleft = tyleft0, tyright = tyright0; + if (xrightlxleft?lxright - lxleft:lxleft - lxright, + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, + dtx = txright>txleft?txright - txleft:txleft - txright, + dty = tyright>tyleft?tyright - tyleft:tyleft - tyright, + rlx = dx?(lxright - lxleft)/dx:0, + rly = dx?(lyright - lyleft)/dx:0, + rtx = dx?(txright - txleft)/dx:0, + rty = dx?(tyright - tyleft)/dx:0, + slx = lxright>lxleft?1:-1, + sly = lyright>lyleft?1:-1, + stx = txright>txleft?1:-1, + sty = tyright>tyleft?1:-1, + ndlx = dlx - (dx?dx*(dlx/dx):0), + ndly = dly - (dx?dx*(dly/dx):0), + ndtx = dtx - (dx?dx*(dtx/dx):0), + ndty = dty - (dx?dx*(dty/dx):0); + int errlx = dx>>1, errly = errlx, errtx = errlx, errty = errlx; + if (xleft<0 && dx) { + lxleft-=xleft*(lxright - lxleft)/dx; + lyleft-=xleft*(lyright - lyleft)/dx; + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + *ptrd = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval); + ptrd+=whd; col+=twh; lig+=lwh; + } + ptrd-=offx; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } else for (int x = xleft; x<=xright; ++x) { + const tc *col = &texture._atXY(txleft,tyleft); + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + const T val = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; lig+=lwh; + } + ptrd-=offx; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + txleft+=rtx+((errtx-=ndtx)<0?errtx+=dx,stx:0); + tyleft+=rty+((errty-=ndty)<0?errty+=dx,sty:0); + } + } + return *this; + } + + //! Draw a textured Phong-shaded 2d triangle, with perspective correction. + template + CImg& draw_triangle(const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const CImg& light, + const int lx0, const int ly0, + const int lx1, const int ly1, + const int lx2, const int ly2, + const float opacity=1) { + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,+texture,tx0,ty0,tx1,ty1,tx2,ty2, + light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,texture,tx0,ty0,tx1,ty1,tx2,ty2, + +light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + lwh = (ulongT)light._width*light._height, + offx = _spectrum*whd - 1; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; + float + ntx0 = tx0/z0, nty0 = ty0/z0, + ntx1 = tx1/z1, nty1 = ty1/z1, + ntx2 = tx2/z2, nty2 = ty2/z2, + nz0 = 1/z0, nz1 = 1/z1, nz2 = 1/z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2); + if (ny0>=height() || ny2<0) return *this; + float + ptxl = (ntx1 - ntx0)/(ny1 - ny0), + ptxr = (ntx2 - ntx0)/(ny2 - ny0), + ptxn = (ntx2 - ntx1)/(ny2 - ny1), + ptyl = (nty1 - nty0)/(ny1 - ny0), + ptyr = (nty2 - nty0)/(ny2 - ny0), + ptyn = (nty2 - nty1)/(ny2 - ny1), + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))), + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))): + (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))): + (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } + int + xleft = xleft0, xright = xright0, + lxleft = lxleft0, lxright = lxright0, + lyleft = lyleft0, lyright = lyright0; + float + zleft = zl, zright = zr, + txleft = txl, txright = txr, + tyleft = tyl, tyright = tyr; + if (xrightlxleft?lxright - lxleft:lxleft - lxright, + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, + rlx = dx?(lxright - lxleft)/dx:0, + rly = dx?(lyright - lyleft)/dx:0, + slx = lxright>lxleft?1:-1, + sly = lyright>lyleft?1:-1, + ndlx = dlx - (dx?dx*(dlx/dx):0), + ndly = dly - (dx?dx*(dly/dx):0); + const float + pentez = (zright - zleft)/dx, + pentetx = (txright - txleft)/dx, + pentety = (tyright - tyleft)/dx; + int errlx = dx>>1, errly = errlx; + if (xleft<0 && dx) { + zleft-=xleft*(zright - zleft)/dx; + lxleft-=xleft*(lxright - lxleft)/dx; + lyleft-=xleft*(lyright - lyleft)/dx; + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y,0,0); + if (opacity>=1) for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + *ptrd = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval); + ptrd+=whd; col+=twh; lig+=lwh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } else for (int x = xleft; x<=xright; ++x) { + const float invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + const T val = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; lig+=lwh; + } + ptrd-=offx; zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; + } + return *this; + } + + //! Draw a textured Phong-shaded 2d triangle, with perspective correction and z-buffering. + template + CImg& draw_triangle(CImg& zbuffer, + const int x0, const int y0, const float z0, + const int x1, const int y1, const float z1, + const int x2, const int y2, const float z2, + const CImg& texture, + const int tx0, const int ty0, + const int tx1, const int ty1, + const int tx2, const int ty2, + const CImg& light, + const int lx0, const int ly0, + const int lx1, const int ly1, + const int lx2, const int ly2, + const float opacity=1) { + typedef typename cimg::superset::type tzfloat; + if (is_empty() || z0<=0 || z1<=0 || z2<=0) return *this; + if (!is_sameXY(zbuffer)) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have " + "different dimensions.", + cimg_instance, + zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data); + if (texture._depth>1 || texture._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified texture (%u,%u,%u,%u,%p).", + cimg_instance, + texture._width,texture._height,texture._depth,texture._spectrum,texture._data); + if (light._depth>1 || light._spectrum<_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_triangle(): Invalid specified light texture (%u,%u,%u,%u,%p).", + cimg_instance,light._width,light._height,light._depth,light._spectrum,light._data); + if (is_overlapped(texture)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + +texture,tx0,ty0,tx1,ty1,tx2,ty2,light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + if (is_overlapped(light)) + return draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2, + texture,tx0,ty0,tx1,ty1,tx2,ty2,+light,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + static const T maxval = (T)std::min(cimg::type::max(),(T)cimg::type::max()); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT + whd = (ulongT)_width*_height*_depth, + twh = (ulongT)texture._width*texture._height, + lwh = (ulongT)light._width*light._height, + offx = _spectrum*whd; + int nx0 = x0, ny0 = y0, nx1 = x1, ny1 = y1, nx2 = x2, ny2 = y2, + nlx0 = lx0, nly0 = ly0, nlx1 = lx1, nly1 = ly1, nlx2 = lx2, nly2 = ly2; + float + ntx0 = tx0/z0, nty0 = ty0/z0, + ntx1 = tx1/z1, nty1 = ty1/z1, + ntx2 = tx2/z2, nty2 = ty2/z2; + tzfloat nz0 = 1/(tzfloat)z0, nz1 = 1/(tzfloat)z1, nz2 = 1/(tzfloat)z2; + if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1,nz0,nz1); + if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2,nz0,nz2); + if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2,nz1,nz2); + if (ny0>=height() || ny2<0) return *this; + float + ptxl = (ntx1 - ntx0)/(ny1 - ny0), + ptxr = (ntx2 - ntx0)/(ny2 - ny0), + ptxn = (ntx2 - ntx1)/(ny2 - ny1), + ptyl = (nty1 - nty0)/(ny1 - ny0), + ptyr = (nty2 - nty0)/(ny2 - ny0), + ptyn = (nty2 - nty1)/(ny2 - ny1), + txr = ny0>=0?ntx0:(ntx0 - ny0*(ntx2 - ntx0)/(ny2 - ny0)), + tyr = ny0>=0?nty0:(nty0 - ny0*(nty2 - nty0)/(ny2 - ny0)), + txl = ny1>=0?(ny0>=0?ntx0:(ntx0 - ny0*(ntx1 - ntx0)/(ny1 - ny0))): + (ptxl=ptxn,(ntx1 - ny1*(ntx2 - ntx1)/(ny2 - ny1))), + tyl = ny1>=0?(ny0>=0?nty0:(nty0 - ny0*(nty1 - nty0)/(ny1 - ny0))): + (ptyl=ptyn,(nty1 - ny1*(nty2 - nty1)/(ny2 - ny1))); + tzfloat + pzl = (nz1 - nz0)/(ny1 - ny0), + pzr = (nz2 - nz0)/(ny2 - ny0), + pzn = (nz2 - nz1)/(ny2 - ny1), + zr = ny0>=0?nz0:(nz0 - ny0*(nz2 - nz0)/(ny2 - ny0)), + zl = ny1>=0?(ny0>=0?nz0:(nz0 - ny0*(nz1 - nz0)/(ny1 - ny0))):(pzl=pzn,(nz1 - ny1*(nz2 - nz1)/(ny2 - ny1))); + _cimg_for_triangle3(*this,xleft0,lxleft0,lyleft0,xright0,lxright0,lyright0,y, + nx0,ny0,nlx0,nly0,nx1,ny1,nlx1,nly1,nx2,ny2,nlx2,nly2) { + if (y==ny1) { zl = nz1; txl = ntx1; tyl = nty1; pzl = pzn; ptxl = ptxn; ptyl = ptyn; } + int + xleft = xleft0, xright = xright0, + lxleft = lxleft0, lxright = lxright0, + lyleft = lyleft0, lyright = lyright0; + float txleft = txl, txright = txr, tyleft = tyl, tyright = tyr; + tzfloat zleft = zl, zright = zr; + if (xrightlxleft?lxright - lxleft:lxleft - lxright, + dly = lyright>lyleft?lyright - lyleft:lyleft - lyright, + rlx = dx?(lxright - lxleft)/dx:0, + rly = dx?(lyright - lyleft)/dx:0, + slx = lxright>lxleft?1:-1, + sly = lyright>lyleft?1:-1, + ndlx = dlx - (dx?dx*(dlx/dx):0), + ndly = dly - (dx?dx*(dly/dx):0); + float pentetx = (txright - txleft)/dx, pentety = (tyright - tyleft)/dx; + const tzfloat pentez = (zright - zleft)/dx; + int errlx = dx>>1, errly = errlx; + if (xleft<0 && dx) { + zleft-=xleft*(zright - zleft)/dx; + lxleft-=xleft*(lxright - lxleft)/dx; + lyleft-=xleft*(lyright - lyleft)/dx; + txleft-=xleft*(txright - txleft)/dx; + tyleft-=xleft*(tyright - tyleft)/dx; + } + if (xleft<0) xleft = 0; + if (xright>=width() - 1) xright = width() - 1; + T* ptrd = data(xleft,y); + tz *ptrz = zbuffer.data(xleft,y); + if (opacity>=1) for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + *ptrd = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval); + ptrd+=whd; col+=twh; lig+=lwh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } else for (int x = xleft; x<=xright; ++x, ++ptrz, ++ptrd) { + if (zleft>=(tzfloat)*ptrz) { + *ptrz = (tz)zleft; + const tzfloat invz = 1/zleft; + const tc *col = &texture._atXY((int)(txleft*invz),(int)(tyleft*invz)); + const tl *lig = &light._atXY(lxleft,lyleft); + cimg_forC(*this,c) { + const tl l = *lig; + const T val = (T)(l<1?l**col:(2 - l)**col + (l - 1)*maxval); + *ptrd = (T)(nopacity*val + *ptrd*copacity); + ptrd+=whd; col+=twh; lig+=lwh; + } + ptrd-=offx; + } + zleft+=pentez; txleft+=pentetx; tyleft+=pentety; + lxleft+=rlx+((errlx-=ndlx)<0?errlx+=dx,slx:0); + lyleft+=rly+((errly-=ndly)<0?errly+=dx,sly:0); + } + zr+=pzr; txr+=ptxr; tyr+=ptyr; zl+=pzl; txl+=ptxl; tyl+=ptyl; + } + return *this; + } + + //! Draw a filled 4d rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param z0 Z-coordinate of the upper-left rectangle corner. + \param c0 C-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param z1 Z-coordinate of the lower-right rectangle corner. + \param c1 C-coordinate of the lower-right rectangle corner. + \param val Scalar value used to fill the rectangle area. + \param opacity Drawing opacity. + **/ + CImg& draw_rectangle(const int x0, const int y0, const int z0, const int c0, + 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 int + nx0 = x0=width()?width() - 1 - nx1:0) + (nx0<0?nx0:0), + lY = (1 + ny1 - ny0) + (ny1>=height()?height() - 1 - ny1:0) + (ny0<0?ny0:0), + lZ = (1 + nz1 - nz0) + (nz1>=depth()?depth() - 1 - nz1:0) + (nz0<0?nz0:0), + lC = (1 + nc1 - nc0) + (nc1>=spectrum()?spectrum() - 1 - nc1:0) + (nc0<0?nc0:0); + const ulongT + offX = (ulongT)_width - lX, + offY = (ulongT)_width*(_height - lY), + offZ = (ulongT)_width*_height*(_depth - lZ); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + T *ptrd = data(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nc0<0?0:nc0); + if (lX>0 && lY>0 && lZ>0 && lC>0) + for (int v = 0; v=1) { + if (sizeof(T)!=1) { for (int x = 0; x + CImg& draw_rectangle(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_rectangle(): Specified color is (null).", + cimg_instance); + cimg_forC(*this,c) draw_rectangle(x0,y0,z0,c,x1,y1,z1,c,(T)color[c],opacity); + return *this; + } + + //! Draw an outlined 3d rectangle \overloading. + template + CImg& draw_rectangle(const int x0, const int y0, const int z0, + const int x1, const int y1, const int z1, + const tc *const color, const float opacity, + const unsigned int pattern) { + return draw_line(x0,y0,z0,x1,y0,z0,color,opacity,pattern,true). + draw_line(x1,y0,z0,x1,y1,z0,color,opacity,pattern,false). + draw_line(x1,y1,z0,x0,y1,z0,color,opacity,pattern,false). + draw_line(x0,y1,z0,x0,y0,z0,color,opacity,pattern,false). + draw_line(x0,y0,z1,x1,y0,z1,color,opacity,pattern,true). + draw_line(x1,y0,z1,x1,y1,z1,color,opacity,pattern,false). + draw_line(x1,y1,z1,x0,y1,z1,color,opacity,pattern,false). + draw_line(x0,y1,z1,x0,y0,z1,color,opacity,pattern,false). + draw_line(x0,y0,z0,x0,y0,z1,color,opacity,pattern,true). + draw_line(x1,y0,z0,x1,y0,z1,color,opacity,pattern,true). + draw_line(x1,y1,z0,x1,y1,z1,color,opacity,pattern,true). + draw_line(x0,y1,z0,x0,y1,z1,color,opacity,pattern,true); + } + + //! Draw a filled 2d rectangle. + /** + \param x0 X-coordinate of the upper-left rectangle corner. + \param y0 Y-coordinate of the upper-left rectangle corner. + \param x1 X-coordinate of the lower-right rectangle corner. + \param y1 Y-coordinate of the lower-right rectangle corner. + \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity=1) { + return draw_rectangle(x0,y0,0,x1,y1,_depth - 1,color,opacity); + } + + //! Draw a outlined 2d rectangle \overloading. + template + CImg& draw_rectangle(const int x0, const int y0, + const int x1, const int y1, + const tc *const color, const float opacity, + const unsigned int pattern) { + 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 int + nx0 = x0 + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity=1) { + if (is_empty() || !points) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Specified color is (null).", + cimg_instance); + if (points._width==1) return draw_point((int)points(0,0),(int)points(0,1),color,opacity); + if (points._width==2) return draw_line((int)points(0,0),(int)points(0,1), + (int)points(1,0),(int)points(1,1),color,opacity); + if (points._width==3) return draw_triangle((int)points(0,0),(int)points(0,1), + (int)points(1,0),(int)points(1,1), + (int)points(2,0),(int)points(2,1),color,opacity); + cimg_init_scanline(color,opacity); + int + xmin = 0, ymin = 0, + xmax = points.get_shared_row(0).max_min(xmin), + ymax = points.get_shared_row(1).max_min(ymin); + if (xmax<0 || xmin>=width() || ymax<0 || ymin>=height()) return *this; + if (ymin==ymax) return draw_line(xmin,ymin,xmax,ymax,color,opacity); + + ymin = std::max(0,ymin); + ymax = std::min(height() - 1,ymax); + CImg Xs(points._width,ymax - ymin + 1); + CImg count(Xs._height,1,1,1,0); + unsigned int n = 0, nn = 1; + bool go_on = true; + + while (go_on) { + unsigned int an = (nn + 1)%points._width; + const int + x0 = (int)points(n,0), + y0 = (int)points(n,1); + if (points(nn,1)==y0) while (points(an,1)==y0) { nn = an; (an+=1)%=points._width; } + const int + x1 = (int)points(nn,0), + y1 = (int)points(nn,1); + unsigned int tn = an; + while (points(tn,1)==y1) (tn+=1)%=points._width; + + if (y0!=y1) { + const int + y2 = (int)points(tn,1), + x01 = x1 - x0, y01 = y1 - y0, y12 = y2 - y1, + dy = cimg::sign(y01), + tmax = std::max(1,cimg::abs(y01)), + tend = tmax - (dy==cimg::sign(y12)); + unsigned int y = (unsigned int)y0 - ymin; + for (int t = 0; t<=tend; ++t, y+=dy) + if (yn; + n = nn; + nn = an; + } + + cimg_pragma_openmp(parallel for cimg_openmp_if(Xs._height>32)) + cimg_forY(Xs,y) { + const CImg Xsy = Xs.get_shared_points(0,count[y] - 1,y).sort(); + int px = width(); + for (unsigned int n = 0; n + CImg& draw_polygon(const CImg& points, + const tc *const color, const float opacity, const unsigned int pattern) { + if (is_empty() || !points || points._width<3) return *this; + bool ninit_hatch = true; + switch (points._height) { + case 0 : case 1 : + throw CImgArgumentException(_cimg_instance + "draw_polygon(): Invalid specified point set.", + cimg_instance); + case 2 : { // 2d version. + CImg npoints(points._width,2); + int x = npoints(0,0) = (int)points(0,0), y = npoints(0,1) = (int)points(0,1); + unsigned int nb_points = 1; + for (unsigned int p = 1; p npoints(points._width,3); + int + x = npoints(0,0) = (int)points(0,0), + y = npoints(0,1) = (int)points(0,1), + z = npoints(0,2) = (int)points(0,2); + unsigned int nb_points = 1; + for (unsigned int p = 1; p + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity=1) { + return _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,0U); + } + + //! Draw a filled 2d ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity=1) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity); + } + + //! Draw an outlined 2d ellipse. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param r1 First radius of the ellipse. + \param r2 Second radius of the ellipse. + \param angle Angle of the first radius. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity, const unsigned int pattern) { + if (pattern) _draw_ellipse(x0,y0,r1,r2,angle,color,opacity,pattern); + return *this; + } + + //! Draw an outlined 2d ellipse \overloading. + /** + \param x0 X-coordinate of the ellipse center. + \param y0 Y-coordinate of the ellipse center. + \param tensor Diffusion tensor describing the ellipse. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern An integer whose bits describe the outline pattern. + **/ + template + CImg& draw_ellipse(const int x0, const int y0, const CImg &tensor, + const tc *const color, const float opacity, + const unsigned int pattern) { + CImgList eig = tensor.get_symmetric_eigen(); + const CImg &val = eig[0], &vec = eig[1]; + return draw_ellipse(x0,y0,std::sqrt(val(0)),std::sqrt(val(1)), + std::atan2(vec(0,1),vec(0,0))*180/cimg::PI, + color,opacity,pattern); + } + + template + CImg& _draw_ellipse(const int x0, const int y0, const float r1, const float r2, const float angle, + const tc *const color, const float opacity, + const unsigned int pattern) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_ellipse(): Specified color is (null).", + cimg_instance); + if (r1<=0 || r2<=0) return draw_point(x0,y0,color,opacity); + cimg_init_scanline(color,opacity); + const float + nr1 = cimg::abs(r1), nr2 = cimg::abs(r2), + nangle = (float)(angle*cimg::PI/180), + u = (float)std::cos(nangle), + v = (float)std::sin(nangle), + rmax = std::max(nr1,nr2), + l1 = (float)std::pow(rmax/(nr1>0?nr1:1e-6),2), + l2 = (float)std::pow(rmax/(nr2>0?nr2:1e-6),2), + a = l1*u*u + l2*v*v, + b = u*v*(l1 - l2), + c = l1*v*v + l2*u*u; + const int + yb = (int)std::sqrt(a*rmax*rmax/(a*c - b*b)), + tymin = y0 - yb - 1, + tymax = y0 + yb + 1, + ymin = tymin<0?0:tymin, + ymax = tymax>=height()?height() - 1:tymax; + int oxmin = 0, oxmax = 0; + bool first_line = true; + for (int y = ymin; y<=ymax; ++y) { + const float + Y = y - y0 + (y0?(float)std::sqrt(delta)/a:0.0f, + bY = b*Y/a, + fxmin = x0 - 0.5f - bY - sdelta, + fxmax = x0 + 0.5f - bY + sdelta; + const int xmin = (int)fxmin, xmax = (int)fxmax; + if (!pattern) cimg_draw_scanline(xmin,xmax,y,color,opacity,1); + else { + if (first_line) { + if (y0 - yb>=0) cimg_draw_scanline(xmin,xmax,y,color,opacity,1); + else draw_point(xmin,y,color,opacity).draw_point(xmax,y,color,opacity); + first_line = false; + } else { + if (xmin + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + cimg_init_scanline(color,opacity); + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (y0>=0 && y0=0) { + const int x1 = x0 - x, x2 = x0 + x, y1 = y0 - y, y2 = y0 + y; + if (y1>=0 && y1=0 && y2=0 && y1=0 && y2 + CImg& draw_circle(const int x0, const int y0, int radius, + const tc *const color, const float opacity, + const unsigned int pattern) { + cimg::unused(pattern); + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_circle(): Specified color is (null).", + cimg_instance); + if (radius<0 || x0 - radius>=width() || y0 + radius<0 || y0 - radius>=height()) return *this; + if (!radius) return draw_point(x0,y0,color,opacity); + draw_point(x0 - radius,y0,color,opacity).draw_point(x0 + radius,y0,color,opacity). + draw_point(x0,y0 - radius,color,opacity).draw_point(x0,y0 + radius,color,opacity); + if (radius==1) return *this; + for (int f = 1 - radius, ddFx = 0, ddFy = -(radius<<1), x = 0, y = radius; x=0) { f+=(ddFy+=2); --y; } + ++x; ++(f+=(ddFx+=2)); + if (x!=y + 1) { + const int x1 = x0 - y, x2 = x0 + y, y1 = y0 - x, y2 = y0 + x, + x3 = x0 - x, x4 = x0 + x, y3 = y0 - y, y4 = y0 + y; + draw_point(x1,y1,color,opacity).draw_point(x1,y2,color,opacity). + draw_point(x2,y1,color,opacity).draw_point(x2,y2,color,opacity); + if (x!=y) + draw_point(x3,y3,color,opacity).draw_point(x4,y4,color,opacity). + draw_point(x4,y3,color,opacity).draw_point(x3,y4,color,opacity); + } + } + return *this; + } + + //! Draw an image. + /** + \param sprite Sprite image. + \param x0 X-coordinate of the sprite position. + \param y0 Y-coordinate of the sprite position. + \param z0 Z-coordinate of the sprite position. + \param c0 C-coordinate of the sprite position. + \param opacity Drawing opacity. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0); + const int + lX = sprite.width() - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0) + (bx?x0:0), + lY = sprite.height() - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0) + (by?y0:0), + lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), + lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); + const t + *ptrs = sprite._data + + (bx?-x0:0) + + (by?-y0*(ulongT)sprite.width():0) + + (bz?-z0*(ulongT)sprite.width()*sprite.height():0) + + (bc?-c0*(ulongT)sprite.width()*sprite.height()*sprite.depth():0); + const ulongT + offX = (ulongT)_width - lX, + soffX = (ulongT)sprite._width - lX, + offY = (ulongT)_width*(_height - lY), + soffY = (ulongT)sprite._width*(sprite._height - lY), + offZ = (ulongT)_width*_height*(_depth - lZ), + soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (lX>0 && lY>0 && lZ>0 && lC>0) { + T *ptrd = data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0); + for (int v = 0; v=1) for (int x = 0; x& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const float opacity=1) { + if (is_empty() || !sprite) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,opacity); + if (x0==0 && y0==0 && z0==0 && c0==0 && is_sameXYZC(sprite) && opacity>=1 && !is_shared()) + return assign(sprite,false); + const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0); + const int + lX = sprite.width() - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0) + (bx?x0:0), + lY = sprite.height() - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0) + (by?y0:0), + lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), + lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); + const T + *ptrs = sprite._data + + (bx?-x0:0) + + (by?-y0*(ulongT)sprite.width():0) + + (bz?-z0*(ulongT)sprite.width()*sprite.height():0) + + (bc?-c0*(ulongT)sprite.width()*sprite.height()*sprite.depth():0); + const ulongT + offX = (ulongT)_width - lX, + soffX = (ulongT)sprite._width - lX, + offY = (ulongT)_width*(_height - lY), + soffY = (ulongT)sprite._width*(sprite._height - lY), + offZ = (ulongT)_width*_height*(_depth - lZ), + soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ), + slX = lX*sizeof(T); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + if (lX>0 && lY>0 && lZ>0 && lC>0) { + T *ptrd = data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0); + for (int v = 0; v=1) + for (int y = 0; y + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,z0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,y0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const float opacity=1) { + return draw_image(x0,0,sprite,opacity); + } + + //! Draw an image \overloading. + template + CImg& draw_image(const CImg& sprite, const float opacity=1) { + return draw_image(0,sprite,opacity); + } + + //! Draw a masked image. + /** + \param sprite Sprite image. + \param mask Mask image. + \param x0 X-coordinate of the sprite position in the image instance. + \param y0 Y-coordinate of the sprite position in the image instance. + \param z0 Z-coordinate of the sprite position in the image instance. + \param c0 C-coordinate of the sprite position in the image instance. + \param mask_max_value Maximum pixel value of the mask image \c mask. + \param opacity Drawing opacity. + \note + - Pixel values of \c mask set the opacity of the corresponding pixels in \c sprite. + - Dimensions along x,y and z of \p sprite and \p mask must be the same. + **/ + template + CImg& draw_image(const int x0, const int y0, const int z0, const int c0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + if (is_empty() || !sprite || !mask) return *this; + if (is_overlapped(sprite)) return draw_image(x0,y0,z0,c0,+sprite,mask,opacity,mask_max_value); + if (is_overlapped(mask)) return draw_image(x0,y0,z0,c0,sprite,+mask,opacity,mask_max_value); + if (mask._width!=sprite._width || mask._height!=sprite._height || mask._depth!=sprite._depth) + throw CImgArgumentException(_cimg_instance + "draw_image(): Sprite (%u,%u,%u,%u,%p) and mask (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + sprite._width,sprite._height,sprite._depth,sprite._spectrum,sprite._data, + mask._width,mask._height,mask._depth,mask._spectrum,mask._data); + + const bool bx = (x0<0), by = (y0<0), bz = (z0<0), bc = (c0<0); + const int + lX = sprite.width() - (x0 + sprite.width()>width()?x0 + sprite.width() - width():0) + (bx?x0:0), + lY = sprite.height() - (y0 + sprite.height()>height()?y0 + sprite.height() - height():0) + (by?y0:0), + lZ = sprite.depth() - (z0 + sprite.depth()>depth()?z0 + sprite.depth() - depth():0) + (bz?z0:0), + lC = sprite.spectrum() - (c0 + sprite.spectrum()>spectrum()?c0 + sprite.spectrum() - spectrum():0) + (bc?c0:0); + const ulongT + coff = (bx?-x0:0) + + (by?-y0*(ulongT)mask.width():0) + + (bz?-z0*(ulongT)mask.width()*mask.height():0) + + (bc?-c0*(ulongT)mask.width()*mask.height()*mask.depth():0), + ssize = (ulongT)mask.width()*mask.height()*mask.depth()*mask.spectrum(); + const ti *ptrs = sprite._data + coff; + const tm *ptrm = mask._data + coff; + const ulongT + offX = (ulongT)_width - lX, + soffX = (ulongT)sprite._width - lX, + offY = (ulongT)_width*(_height - lY), + soffY = (ulongT)sprite._width*(sprite._height - lY), + offZ = (ulongT)_width*_height*(_depth - lZ), + soffZ = (ulongT)sprite._width*sprite._height*(sprite._depth - lZ); + if (lX>0 && lY>0 && lZ>0 && lC>0) { + T *ptrd = data(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,c0<0?0:c0); + for (int c = 0; c + CImg& draw_image(const int x0, const int y0, const int z0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,z0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, const int y0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,y0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a image \overloading. + template + CImg& draw_image(const int x0, + const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(x0,0,sprite,mask,opacity,mask_max_value); + } + + //! Draw an image. + template + CImg& draw_image(const CImg& sprite, const CImg& mask, const float opacity=1, + const float mask_max_value=1) { + return draw_image(0,sprite,mask,opacity,mask_max_value); + } + + //! Draw a text string. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Pointer to \c spectrum() consecutive values, defining the foreground drawing color. + \param background_color Pointer to \c spectrum() consecutive values, defining the background drawing color. + \param opacity Drawing opacity. + \param font Font used for drawing text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent background is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,foreground_color,(tc*)0,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \note A transparent foreground is used for the text. + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity, const CImgList& font, ...) { + if (!font) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return _draw_text(x0,y0,tmp,(tc*)0,background_color,opacity,font,false); + } + + //! Draw a text string \overloading. + /** + \param x0 X-coordinate of the text in the image instance. + \param y0 Y-coordinate of the text in the image instance. + \param text Format of the text ('printf'-style format string). + \param foreground_color Array of spectrum() values of type \c T, + defining the foreground color (0 means 'transparent'). + \param background_color Array of spectrum() values of type \c T, + defining the background color (0 means 'transparent'). + \param opacity Drawing opacity. + \param font_height Height of the text font (exact match for 13,23,53,103, interpolated otherwise). + **/ + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + const CImgList& font = CImgList::font(font_height,true); + _draw_text(x0,y0,tmp,foreground_color,background_color,opacity,font,true); + return *this; + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const tc *const foreground_color, const int background_color=0, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + cimg::unused(background_color); + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",foreground_color,(const tc*)0,opacity,font_height,tmp._data); + } + + //! Draw a text string \overloading. + template + CImg& draw_text(const int x0, const int y0, + const char *const text, + const int, const tc *const background_color, + const float opacity=1, const unsigned int font_height=13, ...) { + if (!font_height) return *this; + CImg tmp(2048); + std::va_list ap; va_start(ap,font_height); + cimg_vsnprintf(tmp,tmp._width,text,ap); va_end(ap); + return draw_text(x0,y0,"%s",(tc*)0,background_color,opacity,font_height,tmp._data); + } + + template + CImg& _draw_text(const int x0, const int y0, + const char *const text, + const tc1 *const foreground_color, const tc2 *const background_color, + const float opacity, const CImgList& font, + const bool is_native_font) { + if (!text) return *this; + if (!font) + throw CImgArgumentException(_cimg_instance + "draw_text(): Empty specified font.", + cimg_instance); + + const unsigned int text_length = (unsigned int)std::strlen(text); + const bool _is_empty = is_empty(); + if (_is_empty) { + // If needed, pre-compute necessary size of the image + int x = 0, y = 0, w = 0; + unsigned char c = 0; + for (unsigned int i = 0; iw) w = x; x = 0; break; + case '\t' : x+=4*font[' ']._width; break; + default : if (cw) w=x; + y+=font[0]._height; + } + assign(x0 + w,y0 + y,1,is_native_font?1:font[0]._spectrum,(T)0); + } + + int x = x0, y = y0; + for (unsigned int i = 0; i letter = font[c]; + if (letter) { + if (is_native_font && _spectrum>letter._spectrum) letter.resize(-100,-100,1,_spectrum,0,2); + const unsigned int cmin = std::min(_spectrum,letter._spectrum); + if (foreground_color) + for (unsigned int c = 0; c + CImg& draw_quiver(const CImg& flow, + const t2 *const color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + return draw_quiver(flow,CImg(color,_spectrum,1,1,1,true),opacity,sampling,factor,is_arrow,pattern); + } + + //! Draw a 2d vector field, using a field of colors. + /** + \param flow Image of 2d vectors used as input data. + \param color Image of spectrum()-D vectors corresponding to the color of each arrow. + \param opacity Opacity of the drawing. + \param sampling Length (in pixels) between each arrow. + \param factor Length factor of each arrow (if <0, computed as a percentage of the maximum length). + \param is_arrow Tells if arrows must be drawn, instead of oriented segments. + \param pattern Used pattern to draw lines. + \note Clipping is supported. + **/ + template + CImg& draw_quiver(const CImg& flow, + const CImg& color, const float opacity=1, + const unsigned int sampling=25, const float factor=-20, + const bool is_arrow=true, const unsigned int pattern=~0U) { + if (is_empty()) return *this; + if (!flow || flow._spectrum!=2) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid dimensions of specified flow (%u,%u,%u,%u,%p).", + cimg_instance, + flow._width,flow._height,flow._depth,flow._spectrum,flow._data); + if (sampling<=0) + throw CImgArgumentException(_cimg_instance + "draw_quiver(): Invalid sampling value %g " + "(should be >0)", + cimg_instance, + sampling); + const bool colorfield = (color._width==flow._width && color._height==flow._height && + color._depth==1 && color._spectrum==_spectrum); + if (is_overlapped(flow)) return draw_quiver(+flow,color,opacity,sampling,factor,is_arrow,pattern); + float vmax,fact; + if (factor<=0) { + float m, M = (float)flow.get_norm(2).max_min(m); + vmax = (float)std::max(cimg::abs(m),cimg::abs(M)); + if (!vmax) vmax = 1; + fact = -factor; + } else { fact = factor; vmax = 1; } + + for (unsigned int y = sampling/2; y<_height; y+=sampling) + for (unsigned int x = sampling/2; x<_width; x+=sampling) { + const unsigned int X = x*flow._width/_width, Y = y*flow._height/_height; + float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax; + if (is_arrow) { + const int xx = (int)(x + u), yy = (int)(y + v); + if (colorfield) draw_arrow(x,y,xx,yy,color.get_vector_at(X,Y)._data,opacity,45,sampling/5.0f,pattern); + else draw_arrow(x,y,xx,yy,color._data,opacity,45,sampling/5.0f,pattern); + } else { + if (colorfield) + draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color.get_vector_at(X,Y)._data,opacity,pattern); + else draw_line((int)(x - 0.5*u),(int)(y - 0.5*v),(int)(x + 0.5*u),(int)(y + 0.5*v), + color._data,opacity,pattern); + } + } + return *this; + } + + //! Draw a labeled horizontal axis. + /** + \param values_x Values along the horizontal axis. + \param y Y-coordinate of the horizontal axis in the image instance. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const CImg& values_x, const int y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true) { + if (is_empty()) return *this; + const int yt = (y + 3 + font_height)<_height?y + 3:y - 2 - (int)font_height; + const int siz = (int)values_x.size() - 1; + CImg txt(32); + CImg label; + if (siz<=0) { // Degenerated case. + draw_line(0,y,_width - 1,y,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",(double)*values_x); + label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _xt = (width() - label.width())/2, + xt = _xt<3?3:_xt + label.width()>=width() - 2?width() - 3 - label.width():_xt; + draw_point(width()/2,y - 1,color,opacity).draw_point(width()/2,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case. + if (values_x[0]=width() - 2?width() - 3 - label.width():_xt; + draw_point(xi,y - 1,color,opacity).draw_point(xi,y + 1,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw a labeled vertical axis. + /** + \param x X-coordinate of the vertical axis in the image instance. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern Drawing pattern. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axis(const int x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern=~0U, const unsigned int font_height=13, + const bool allow_zero=true) { + if (is_empty()) return *this; + int siz = (int)values_y.size() - 1; + CImg txt(32); + CImg label; + if (siz<=0) { // Degenerated case. + draw_line(x,0,x,_height - 1,color,opacity,pattern); + if (!siz) { + cimg_snprintf(txt,txt._width,"%g",(double)*values_y); + label.assign().draw_text(0,0,txt,color,(tc*)0,opacity,font_height); + const int + _yt = (height() - label.height())/2, + yt = _yt<0?0:_yt + label.height()>=height()?height() - 1-label.height():_yt, + _xt = x - 2 - label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,height()/2,color,opacity).draw_point(x + 1,height()/2,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } else { // Regular case. + if (values_y[0]=height()?height() - 1-label.height():_yt, + _xt = x - 2 - label.width(), + xt = _xt>=0?_xt:x + 3; + draw_point(x - 1,yi,color,opacity).draw_point(x + 1,yi,color,opacity); + if (allow_zero || *txt!='0' || txt[1]!=0) + draw_text(xt,yt,txt,color,(tc*)0,opacity,font_height); + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes. + /** + \param values_x Values along the X-axis. + \param values_y Values along the Y-axis. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for the X-axis. + \param pattern_y Drawing pattern for the Y-axis. + \param font_height Height of the labels (exact match for 13,23,53,103, interpolated otherwise). + \param allow_zero Enable/disable the drawing of label '0' if found. + **/ + template + CImg& draw_axes(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13, const bool allow_zero=true) { + if (is_empty()) return *this; + const CImg nvalues_x(values_x._data,values_x.size(),1,1,1,true); + const int sizx = (int)values_x.size() - 1, wm1 = width() - 1; + if (sizx>=0) { + float ox = (float)*nvalues_x; + for (unsigned int x = sizx?1U:0U; x<_width; ++x) { + const float nx = (float)nvalues_x._linear_atX((float)x*sizx/wm1); + if (nx*ox<=0) { draw_axis(nx==0?x:x - 1,values_y,color,opacity,pattern_y,font_height,allow_zero); break; } + ox = nx; + } + } + const CImg nvalues_y(values_y._data,values_y.size(),1,1,1,true); + const int sizy = (int)values_y.size() - 1, hm1 = height() - 1; + if (sizy>0) { + float oy = (float)nvalues_y[0]; + for (unsigned int y = sizy?1U:0U; y<_height; ++y) { + const float ny = (float)nvalues_y._linear_atX((float)y*sizy/hm1); + if (ny*oy<=0) { draw_axis(values_x,ny==0?y:y - 1,color,opacity,pattern_x,font_height,allow_zero); break; } + oy = ny; + } + } + return *this; + } + + //! Draw labeled horizontal and vertical axes \overloading. + template + CImg& draw_axes(const float x0, const float x1, const float y0, const float y1, + const tc *const color, const float opacity=1, + const int subdivisionx=-60, const int subdivisiony=-60, + const float precisionx=0, const float precisiony=0, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U, + const unsigned int font_height=13) { + if (is_empty()) return *this; + const bool allow_zero = (x0*x1>0) || (y0*y1>0); + const float + dx = cimg::abs(x1-x0), dy = cimg::abs(y1-y0), + px = dx<=0?1:precisionx==0?(float)std::pow(10.0,(int)std::log10(dx) - 2.0):precisionx, + py = dy<=0?1:precisiony==0?(float)std::pow(10.0,(int)std::log10(dy) - 2.0):precisiony; + if (x0!=x1 && y0!=y1) + draw_axes(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1).round(px), + CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1).round(py), + color,opacity,pattern_x,pattern_y,font_height,allow_zero); + else if (x0==x1 && y0!=y1) + draw_axis((int)x0,CImg::sequence(subdivisiony>0?subdivisiony:1-height()/subdivisiony,y0,y1).round(py), + color,opacity,pattern_y,font_height); + else if (x0!=x1 && y0==y1) + draw_axis(CImg::sequence(subdivisionx>0?subdivisionx:1-width()/subdivisionx,x0,x1).round(px),(int)y0, + color,opacity,pattern_x,font_height); + return *this; + } + + //! Draw 2d grid. + /** + \param values_x X-coordinates of the vertical lines. + \param values_y Y-coordinates of the horizontal lines. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + \param pattern_x Drawing pattern for vertical lines. + \param pattern_y Drawing pattern for horizontal lines. + **/ + template + CImg& draw_grid(const CImg& values_x, const CImg& values_y, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + if (values_x) cimg_foroff(values_x,x) { + const int xi = (int)values_x[x]; + if (xi>=0 && xi=0 && yi + CImg& draw_grid(const float delta_x, const float delta_y, + const float offsetx, const float offsety, + const bool invertx, const bool inverty, + const tc *const color, const float opacity=1, + const unsigned int pattern_x=~0U, const unsigned int pattern_y=~0U) { + if (is_empty()) return *this; + CImg seqx, seqy; + if (delta_x!=0) { + const float dx = delta_x>0?delta_x:_width*-delta_x/100; + const unsigned int nx = (unsigned int)(_width/dx); + seqx = CImg::sequence(1 + nx,0,(unsigned int)(dx*nx)); + if (offsetx) cimg_foroff(seqx,x) seqx(x) = (unsigned int)cimg::mod(seqx(x) + offsetx,(float)_width); + if (invertx) cimg_foroff(seqx,x) seqx(x) = _width - 1 - seqx(x); + } + if (delta_y!=0) { + const float dy = delta_y>0?delta_y:_height*-delta_y/100; + const unsigned int ny = (unsigned int)(_height/dy); + seqy = CImg::sequence(1 + ny,0,(unsigned int)(dy*ny)); + if (offsety) cimg_foroff(seqy,y) seqy(y) = (unsigned int)cimg::mod(seqy(y) + offsety,(float)_height); + if (inverty) cimg_foroff(seqy,y) seqy(y) = _height - 1 - seqy(y); + } + return draw_grid(seqx,seqy,color,opacity,pattern_x,pattern_y); + } + + //! Draw 1d graph. + /** + \param data Image containing the graph values I = f(x). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + + \param plot_type Define the type of the plot: + - 0 = No plot. + - 1 = Plot using segments. + - 2 = Plot using cubic splines. + - 3 = Plot with bars. + \param vertex_type Define the type of points: + - 0 = No points. + - 1 = Point. + - 2 = Straight cross. + - 3 = Diagonal cross. + - 4 = Filled circle. + - 5 = Outlined circle. + - 6 = Square. + - 7 = Diamond. + \param ymin Lower bound of the y-range. + \param ymax Upper bound of the y-range. + \param pattern Drawing pattern. + \note + - if \c ymin==ymax==0, the y-range is computed automatically from the input samples. + **/ + template + CImg& draw_graph(const CImg& data, + const tc *const color, const float opacity=1, + const unsigned int plot_type=1, const int vertex_type=1, + const double ymin=0, const double ymax=0, const unsigned int pattern=~0U) { + if (is_empty() || _height<=1) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_graph(): Specified color is (null).", + cimg_instance); + + // Create shaded colors for displaying bar plots. + CImg color1, color2; + if (plot_type==3) { + color1.assign(_spectrum); color2.assign(_spectrum); + cimg_forC(*this,c) { + color1[c] = (tc)std::min((float)cimg::type::max(),color[c]*1.2f); + color2[c] = (tc)(color[c]*0.4f); + } + } + + // Compute min/max and normalization factors. + const ulongT + siz = data.size(), + _siz1 = siz - (plot_type!=3), + siz1 = _siz1?_siz1:1; + const unsigned int + _width1 = _width - (plot_type!=3), + width1 = _width1?_width1:1; + double m = ymin, M = ymax; + if (ymin==ymax) m = (double)data.max_min(M); + if (m==M) { --m; ++M; } + const float ca = (float)(M-m)/(_height - 1); + bool init_hatch = true; + + // Draw graph edges + switch (plot_type%4) { + case 1 : { // Segments + int oX = 0, oY = (int)((data[0] - m)/ca); + if (siz==1) { + const int Y = (int)((*data - m)/ca); + draw_line(0,Y,width() - 1,Y,color,opacity,pattern); + } else { + const float fx = (float)_width/siz1; + for (ulongT off = 1; off ndata(data._data,siz,1,1,1,true); + int oY = (int)((data[0] - m)/ca); + cimg_forX(*this,x) { + const int Y = (int)((ndata._cubic_atX((float)x*siz1/width1)-m)/ca); + if (x>0) draw_line(x,oY,x + 1,Y,color,opacity,pattern,init_hatch); + init_hatch = false; + oY = Y; + } + } break; + case 3 : { // Bars + const int Y0 = (int)(-m/ca); + const float fx = (float)_width/siz1; + int oX = 0; + cimg_foroff(data,off) { + const int + X = (int)((off + 1)*fx) - 1, + Y = (int)((data[off] - m)/ca); + draw_rectangle(oX,Y0,X,Y,color,opacity). + draw_line(oX,Y,oX,Y0,color2.data(),opacity). + draw_line(oX,Y0,X,Y0,Y<=Y0?color2.data():color1.data(),opacity). + draw_line(X,Y,X,Y0,color1.data(),opacity). + draw_line(oX,Y,X,Y,Y<=Y0?color1.data():color2.data(),opacity); + oX = X + 1; + } + } break; + default : break; // No edges + } + + // Draw graph points + const unsigned int wb2 = plot_type==3?_width1/(2*siz):0; + const float fx = (float)_width1/siz1; + switch (vertex_type%8) { + case 1 : { // Point + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_point(X,Y,color,opacity); + } + } break; + case 2 : { // Straight Cross + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_line(X - 3,Y,X + 3,Y,color,opacity).draw_line(X,Y - 3,X,Y + 3,color,opacity); + } + } break; + case 3 : { // Diagonal Cross + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_line(X - 3,Y - 3,X + 3,Y + 3,color,opacity).draw_line(X - 3,Y + 3,X + 3,Y - 3,color,opacity); + } + } break; + case 4 : { // Filled Circle + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity); + } + } break; + case 5 : { // Outlined circle + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_circle(X,Y,3,color,opacity,0U); + } + } break; + case 6 : { // Square + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_rectangle(X - 3,Y - 3,X + 3,Y + 3,color,opacity,~0U); + } + } break; + case 7 : { // Diamond + cimg_foroff(data,off) { + const int + X = (int)(off*fx + wb2), + Y = (int)((data[off]-m)/ca); + draw_line(X,Y - 4,X + 4,Y,color,opacity). + draw_line(X + 4,Y,X,Y + 4,color,opacity). + draw_line(X,Y + 4,X - 4,Y,color,opacity). + draw_line(X - 4,Y,X,Y - 4,color,opacity); + } + } break; + default : break; // No points + } + return *this; + } + + //! Draw filled 3d region with the flood fill algorithm. + /** + \param x X-coordinate of the starting point of the region to fill. + \param y Y-coordinate of the starting point of the region to fill. + \param z Z-coordinate of the starting point of the region to fill. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param[out] region Image that will contain the mask of the filled region mask, as an output. + \param sigma Tolerance concerning neighborhood values. + \param opacity Opacity of the drawing. + \param is_high_connexity Tells if 8-connexity must be used (only for 2d images). + \return \c region is initialized with the binary mask of the filled region. + **/ + template + CImg& draw_fill(const int x, const int y, const int z, + const tc *const color, const float opacity, + CImg& region, const float sigma=0, + const bool is_high_connexity=false) { + +#define _cimg_draw_fill_test(x,y,z,res) if (region(x,y,z)) res = false; else { \ + res = true; \ + const T *reference_col = reference_color._data + _spectrum, *ptrs = data(x,y,z) + siz; \ + for (unsigned int i = _spectrum; res && i; --i) { ptrs-=whd; res = (cimg::abs(*ptrs - *(--reference_col))<=sigma); } \ + region(x,y,z) = (t)(res?1:noregion); \ +} + +#define _cimg_draw_fill_set(x,y,z) { \ + const tc *col = color; \ + T *ptrd = data(x,y,z); \ + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)*(col++); ptrd+=whd; } \ + else cimg_forC(*this,c) { *ptrd = (T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whd; } \ +} + +#define _cimg_draw_fill_insert(x,y,z) { \ + if (posr1>=remaining._height) remaining.resize(3,remaining._height<<1,1,1,0); \ + unsigned int *ptrr = remaining.data(0,posr1); \ + *(ptrr++) = x; *(ptrr++) = y; *(ptrr++) = z; ++posr1; \ +} + +#define _cimg_draw_fill_test_neighbor(x,y,z,cond) if (cond) { \ + const unsigned int tx = x, ty = y, tz = z; \ + _cimg_draw_fill_test(tx,ty,tz,res); if (res) _cimg_draw_fill_insert(tx,ty,tz); \ +} + + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_fill(): Specified color is (null).", + cimg_instance); + + region.assign(_width,_height,_depth,1,(t)0); + if (x>=0 && x=0 && y=0 && z1); + const CImg reference_color = get_vector_at(x,y,z); + CImg remaining(3,512,1,1,0); + remaining(0,0) = (unsigned int)x; + remaining(1,0) = (unsigned int)y; + remaining(2,0) = (unsigned int)z; + unsigned int posr0 = 0, posr1 = 1; + region(x,y,z) = (t)1; + const t noregion = ((t)1==(t)2)?(t)0:(t)-1; + if (is_3d) do { // 3d version of the filling algorithm + const unsigned int *pcurr = remaining.data(0,posr0++), xc = *(pcurr++), yc = *(pcurr++), zc = *(pcurr++); + if (posr0>=512) { remaining.shift(0,-(int)posr0); posr1-=posr0; posr0 = 0; } + bool cont, res; + unsigned int nxc = xc; + do { // X-backward + _cimg_draw_fill_set(nxc,yc,zc); + _cimg_draw_fill_test_neighbor(nxc,yc - 1,zc,yc!=0); + _cimg_draw_fill_test_neighbor(nxc,yc + 1,zc,ycposr0); + else do { // 2d version of the filling algorithm + const unsigned int *pcurr = remaining.data(0,posr0++), xc = *(pcurr++), yc = *(pcurr++); + if (posr0>=512) { remaining.shift(0,-(int)posr0); posr1-=posr0; posr0 = 0; } + bool cont, res; + unsigned int nxc = xc; + do { // X-backward + _cimg_draw_fill_set(nxc,yc,0); + _cimg_draw_fill_test_neighbor(nxc,yc - 1,0,yc!=0); + _cimg_draw_fill_test_neighbor(nxc,yc + 1,0,ycposr0); + if (noregion) cimg_for(region,ptrd,t) if (*ptrd==noregion) *ptrd = (t)0; + } + return *this; + } + + //! Draw filled 3d region with the flood fill algorithm \simplification. + template + CImg& draw_fill(const int x, const int y, const int z, + const tc *const color, const float opacity=1, + const float sigma=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x,y,z,color,opacity,tmp,sigma,is_high_connexity); + } + + //! Draw filled 2d region with the flood fill algorithm \simplification. + template + CImg& draw_fill(const int x, const int y, + const tc *const color, const float opacity=1, + const float sigma=0, const bool is_high_connexity=false) { + CImg tmp; + return draw_fill(x,y,0,color,opacity,tmp,sigma,is_high_connexity); + } + + //! Draw a random plasma texture. + /** + \param alpha Alpha-parameter. + \param beta Beta-parameter. + \param scale Scale-parameter. + \note Use the mid-point algorithm to render. + **/ + CImg& draw_plasma(const float alpha=1, const float beta=0, const unsigned int scale=8) { + if (is_empty()) return *this; + const int w = width(), h = height(); + const Tfloat m = (Tfloat)cimg::type::min(), M = (Tfloat)cimg::type::max(); + cimg_forZC(*this,z,c) { + CImg ref = get_shared_slice(z,c); + for (int delta = 1<1; delta>>=1) { + const int delta2 = delta>>1; + const float r = alpha*delta + beta; + + // Square step. + for (int y0 = 0; y0M?M:val); + } + + // Diamond steps. + for (int y = -delta2; yM?M:val); + } + for (int y0 = 0; y0M?M:val); + } + for (int y = -delta2; yM?M:val); + } + } + } + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2d fractal. + /** + \param x0 X-coordinate of the upper-left pixel. + \param y0 Y-coordinate of the upper-left pixel. + \param x1 X-coordinate of the lower-right pixel. + \param y1 Y-coordinate of the lower-right pixel. + \param colormap Colormap. + \param opacity Drawing opacity. + \param z0r Real part of the upper-left fractal vertex. + \param z0i Imaginary part of the upper-left fractal vertex. + \param z1r Real part of the lower-right fractal vertex. + \param z1i Imaginary part of the lower-right fractal vertex. + \param iteration_max Maximum number of iterations for each estimated point. + \param is_normalized_iteration Tells if iterations are normalized. + \param is_julia_set Tells if the Mandelbrot or Julia set is rendered. + \param param_r Real part of the Julia set parameter. + \param param_i Imaginary part of the Julia set parameter. + \note Fractal rendering is done by the Escape Time Algorithm. + **/ + template + CImg& draw_mandelbrot(const int x0, const int y0, const int x1, const int y1, + const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + if (is_empty()) return *this; + CImg palette; + if (colormap) palette.assign(colormap._data,colormap.size()/colormap._spectrum,1,1,colormap._spectrum,true); + if (palette && palette._spectrum!=_spectrum) + throw CImgArgumentException(_cimg_instance + "draw_mandelbrot(): Instance and specified colormap (%u,%u,%u,%u,%p) have " + "incompatible dimensions.", + cimg_instance, + colormap._width,colormap._height,colormap._depth,colormap._spectrum,colormap._data); + + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f), ln2 = (float)std::log(2.0); + const int + _x0 = cimg::cut(x0,0,width() - 1), + _y0 = cimg::cut(y0,0,height() - 1), + _x1 = cimg::cut(x1,0,width() - 1), + _y1 = cimg::cut(y1,0,height() - 1); + + cimg_pragma_openmp(parallel for collapse(2) cimg_openmp_if((1 + _x1 - _x0)*(1 + _y1 - _y0)>=2048)) + for (int q = _y0; q<=_y1; ++q) + for (int p = _x0; p<=_x1; ++p) { + unsigned int iteration = 0; + const double x = z0r + p*(z1r-z0r)/_width, y = z0i + q*(z1i-z0i)/_height; + double zr, zi, cr, ci; + if (is_julia_set) { zr = x; zi = y; cr = param_r; ci = param_i; } + else { zr = param_r; zi = param_i; cr = x; ci = y; } + for (iteration=1; zr*zr + zi*zi<=4 && iteration<=iteration_max; ++iteration) { + const double temp = zr*zr - zi*zi + cr; + zi = 2*zr*zi + ci; + zr = temp; + } + if (iteration>iteration_max) { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette(0,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(0,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)0; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)((*this)(p,q,0,c)*copacity); + } + } else if (is_normalized_iteration) { + const float + normz = (float)cimg::abs(zr*zr + zi*zi), + niteration = (float)(iteration + 1 - std::log(std::log(normz))/ln2); + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._linear_atX(niteration,c); + else cimg_forC(*this,c) + (*this)(p,q,0,c) = (T)(palette._linear_atX(niteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)niteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(niteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } else { + if (palette) { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)palette._atX(iteration,c); + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(palette(iteration,c)*nopacity + (*this)(p,q,0,c)*copacity); + } else { + if (opacity>=1) cimg_forC(*this,c) (*this)(p,q,0,c) = (T)iteration; + else cimg_forC(*this,c) (*this)(p,q,0,c) = (T)(iteration*nopacity + (*this)(p,q,0,c)*copacity); + } + } + } + return *this; + } + + //! Draw a quadratic Mandelbrot or Julia 2d fractal \overloading. + template + CImg& draw_mandelbrot(const CImg& colormap, const float opacity=1, + const double z0r=-2, const double z0i=-2, const double z1r=2, const double z1i=2, + const unsigned int iteration_max=255, + const bool is_normalized_iteration=false, + const bool is_julia_set=false, + const double param_r=0, const double param_i=0) { + return draw_mandelbrot(0,0,_width - 1,_height - 1,colormap,opacity, + z0r,z0i,z1r,z1i,iteration_max,is_normalized_iteration,is_julia_set,param_r,param_i); + } + + //! Draw a 1d gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param sigma Standard variation of the gaussian distribution. + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float sigma, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + const float sigma2 = 2*sigma*sigma, nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forX(*this,x) { + const float dx = (x - xc), val = (float)std::exp(-dx*dx/sigma2); + T *ptrd = data(x,0,0,0); + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 2d gaussian function. + /** + \param xc X-coordinate of the gaussian center. + \param yc Y-coordinate of the gaussian center. + \param tensor Covariance matrix (must be 2x2). + \param color Pointer to \c spectrum() consecutive values, defining the drawing color. + \param opacity Drawing opacity. + **/ + template + CImg& draw_gaussian(const float xc, const float yc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + if (tensor._width!=2 || tensor._height!=2 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 2x2 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + if (!color) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified color is (null).", + cimg_instance); + typedef typename CImg::Tfloat tfloat; + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0); + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = invT2(1,1); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + float dy = -yc; + cimg_forY(*this,y) { + float dx = -xc; + cimg_forX(*this,x) { + const float val = (float)std::exp(a*dx*dx + b*dx*dy + c*dy*dy); + T *ptrd = data(x,y,0,0); + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + ++dx; + } + ++dy; + } + return *this; + } + + //! Draw a 2d gaussian function \overloading. + template + CImg& draw_gaussian(const int xc, const int yc, const float r1, const float r2, const float ru, const float rv, + const tc *const color, const float opacity=1) { + const double + a = r1*ru*ru + r2*rv*rv, + b = (r1-r2)*ru*rv, + c = r1*rv*rv + r2*ru*ru; + const CImg tensor(2,2,1,1, a,b,b,c); + return draw_gaussian(xc,yc,tensor,color,opacity); + } + + //! Draw a 2d gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,CImg::diagonal(sigma,sigma),color,opacity); + } + + //! Draw a 3d gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const CImg& tensor, + const tc *const color, const float opacity=1) { + if (is_empty()) return *this; + typedef typename CImg::Tfloat tfloat; + if (tensor._width!=3 || tensor._height!=3 || tensor._depth!=1 || tensor._spectrum!=1) + throw CImgArgumentException(_cimg_instance + "draw_gaussian(): Specified tensor (%u,%u,%u,%u,%p) is not a 3x3 matrix.", + cimg_instance, + tensor._width,tensor._height,tensor._depth,tensor._spectrum,tensor._data); + + const CImg invT = tensor.get_invert(), invT2 = (invT*invT)/(-2.0); + const tfloat a = invT2(0,0), b = 2*invT2(1,0), c = 2*invT2(2,0), d = invT2(1,1), e = 2*invT2(2,1), f = invT2(2,2); + const float nopacity = cimg::abs(opacity), copacity = 1 - std::max(opacity,0.0f); + const ulongT whd = (ulongT)_width*_height*_depth; + const tc *col = color; + cimg_forXYZ(*this,x,y,z) { + const float + dx = (x - xc), dy = (y - yc), dz = (z - zc), + val = (float)std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz); + T *ptrd = data(x,y,z,0); + if (opacity>=1) cimg_forC(*this,c) { *ptrd = (T)(val*(*col++)); ptrd+=whd; } + else cimg_forC(*this,c) { *ptrd = (T)(nopacity*val*(*col++) + *ptrd*copacity); ptrd+=whd; } + col-=_spectrum; + } + return *this; + } + + //! Draw a 3d gaussian function \overloading. + template + CImg& draw_gaussian(const float xc, const float yc, const float zc, const float sigma, + const tc *const color, const float opacity=1) { + return draw_gaussian(xc,yc,zc,CImg::diagonal(sigma,sigma,sigma),color,opacity); + } + + //! Draw a 3d object. + /** + \param x0 X-coordinate of the 3d object position + \param y0 Y-coordinate of the 3d object position + \param z0 Z-coordinate of the 3d object position + \param vertices Image Nx3 describing 3d point coordinates + \param primitives List of P primitives + \param colors List of P color (or textures) + \param opacities Image or list of P opacities + \param render_type d Render type (0=Points, 1=Lines, 2=Faces (no light), 3=Faces (flat), 4=Faces(Gouraud) + \param is_double_sided Tells if object faces have two sides or are oriented. + \param focale length of the focale (0 for parallel projection) + \param lightx X-coordinate of the light + \param lighty Y-coordinate of the light + \param lightz Z-coordinate of the light + \param specular_lightness Amount of specular light. + \param specular_shininess Shininess of the object + **/ + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,CImg::empty()); + } + + //! Draw a 3d object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImg& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,1); + } +#endif + + //! Draw a 3d object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,CImg::empty()); + } + + //! Draw a 3d object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + CImg& zbuffer) { + return _draw_object3d(0,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,1); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f) { + return draw_object3d(board,x0,y0,z0,vertices,primitives,colors,opacities,render_type, + is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, const CImgList& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + CImg& zbuffer) { + return _draw_object3d((void*)&board,zbuffer,x0,y0,z0,vertices,primitives,colors,opacities, + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,1); + } +#endif + + //! Draw a 3d object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,CImg::empty()); + } + + //! Draw a 3d object \simplification. + template + CImg& draw_object3d(const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,zbuffer); + } + +#ifdef cimg_use_board + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type=4, + const bool is_double_sided=false, const float focale=700, + const float lightx=0, const float lighty=0, const float lightz=-5e8, + const float specular_lightness=0.2f, const float specular_shininess=0.1f) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,CImg::empty()); + } + + template + CImg& draw_object3d(LibBoard::Board& board, + const float x0, const float y0, const float z0, + const CImg& vertices, const CImgList& primitives, + const CImgList& colors, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + CImg& zbuffer) { + return draw_object3d(x0,y0,z0,vertices,primitives,colors,CImg::const_empty(), + render_type,is_double_sided,focale,lightx,lighty,lightz, + specular_lightness,specular_shininess,zbuffer); + } +#endif + + template + static float __draw_object3d(const CImgList& opacities, const unsigned int n_primitive, CImg& opacity) { + if (n_primitive>=opacities._width || opacities[n_primitive].is_empty()) { opacity.assign(); return 1; } + if (opacities[n_primitive].size()==1) { opacity.assign(); return opacities(n_primitive,0); } + opacity.assign(opacities[n_primitive],true); + return 1.0f; + } + + template + static float __draw_object3d(const CImg& opacities, const unsigned int n_primitive, CImg& opacity) { + opacity.assign(); + return n_primitive>=opacities._width?1.0f:(float)opacities[n_primitive]; + } + + template + static float ___draw_object3d(const CImgList& opacities, const unsigned int n_primitive) { + return n_primitive + static float ___draw_object3d(const CImg& opacities, const unsigned int n_primitive) { + return n_primitive + CImg& _draw_object3d(void *const pboard, CImg& zbuffer, + const float X, const float Y, const float Z, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const unsigned int render_type, + const bool is_double_sided, const float focale, + const float lightx, const float lighty, const float lightz, + const float specular_lightness, const float specular_shininess, + const float sprite_scale) { + typedef typename cimg::superset2::type tpfloat; + typedef typename to::value_type _to; + if (is_empty() || !vertices || !primitives) return *this; + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,false,error_message)) + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid specified 3d object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); +#ifndef cimg_use_board + if (pboard) return *this; +#endif + if (render_type==5) cimg::mutex(10); // Static variable used in this case, breaks thread-safety. + + const float + nspec = 1 - (specular_lightness<0.0f?0.0f:(specular_lightness>1.0f?1.0f:specular_lightness)), + nspec2 = 1 + (specular_shininess<0.0f?0.0f:specular_shininess), + nsl1 = (nspec2 - 1)/cimg::sqr(nspec - 1), + nsl2 = 1 - 2*nsl1*nspec, + nsl3 = nspec2 - nsl1 - nsl2; + + // Create light texture for phong-like rendering. + CImg light_texture; + if (render_type==5) { + if (colors._width>primitives._width) { + static CImg default_light_texture; + static const tc *lptr = 0; + static tc ref_values[64] = { 0 }; + const CImg& img = colors.back(); + bool is_same_texture = (lptr==img._data); + if (is_same_texture) + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + if (ref_values[r++]!=img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum)) { + is_same_texture = false; break; + } + if (!is_same_texture || default_light_texture._spectrum<_spectrum) { + (default_light_texture.assign(img,false)/=255).resize(-100,-100,1,_spectrum); + lptr = colors.back().data(); + for (unsigned int r = 0, j = 0; j<8; ++j) + for (unsigned int i = 0; i<8; ++i) + ref_values[r++] = img(i*img._width/9,j*img._height/9,0,(i + j)%img._spectrum); + } + light_texture.assign(default_light_texture,true); + } else { + static CImg default_light_texture; + static float olightx = 0, olighty = 0, olightz = 0, ospecular_shininess = 0; + if (!default_light_texture || + lightx!=olightx || lighty!=olighty || lightz!=olightz || + specular_shininess!=ospecular_shininess || default_light_texture._spectrum<_spectrum) { + default_light_texture.assign(512,512); + const float + dlx = lightx - X, + dly = lighty - Y, + dlz = lightz - Z, + nl = cimg::hypot(dlx,dly,dlz), + nlx = (default_light_texture._width - 1)/2*(1 + dlx/nl), + nly = (default_light_texture._height - 1)/2*(1 + dly/nl), + white[] = { 1 }; + default_light_texture.draw_gaussian(nlx,nly,default_light_texture._width/3.0f,white); + cimg_forXY(default_light_texture,x,y) { + const float factor = default_light_texture(x,y); + if (factor>nspec) default_light_texture(x,y) = std::min(2.0f,nsl1*factor*factor + nsl2*factor + nsl3); + } + default_light_texture.resize(-100,-100,1,_spectrum); + olightx = lightx; olighty = lighty; olightz = lightz; ospecular_shininess = specular_shininess; + } + light_texture.assign(default_light_texture,true); + } + } + + // Compute 3d to 2d projection. + CImg projections(vertices._width,2); + tpfloat parallzmin = cimg::type::max(); + const float absfocale = focale?cimg::abs(focale):0; + if (absfocale) { + cimg_pragma_openmp(parallel for cimg_openmp_if(projections.size()>4096)) + cimg_forX(projections,l) { // Perspective projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + const tpfloat projectedz = z + Z + absfocale; + projections(l,1) = Y + absfocale*y/projectedz; + projections(l,0) = X + absfocale*x/projectedz; + } + + } else { + cimg_pragma_openmp(parallel for cimg_openmp_if(projections.size()>4096)) + cimg_forX(projections,l) { // Parallel projection + const tpfloat + x = (tpfloat)vertices(l,0), + y = (tpfloat)vertices(l,1), + z = (tpfloat)vertices(l,2); + if (z visibles(primitives._width,1,1,1,~0U); + CImg zrange(primitives._width); + const tpfloat zmin = absfocale?(tpfloat)(1.5f - absfocale):cimg::type::min(); + bool is_forward = zbuffer?true:false; + + cimg_pragma_openmp(parallel for cimg_openmp_if(primitives.size()>4096)) + cimglist_for(primitives,l) { + const CImg& primitive = primitives[l]; + switch (primitive.size()) { + case 1 : { // Point + CImg<_to> _opacity; + __draw_object3d(opacities,l,_opacity); + if (l<=colors.width() && (colors[l].size()!=_spectrum || _opacity)) is_forward = false; + const unsigned int i0 = (unsigned int)primitive(0); + const tpfloat z0 = Z + vertices(i0,2); + if (z0>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = z0; + } + } break; + case 5 : { // Sphere + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + Xc = 0.5f*((float)vertices(i0,0) + (float)vertices(i1,0)), + Yc = 0.5f*((float)vertices(i0,1) + (float)vertices(i1,1)), + Zc = 0.5f*((float)vertices(i0,2) + (float)vertices(i1,2)), + _zc = Z + Zc, + zc = _zc + _focale, + xc = X + Xc*(absfocale?absfocale/zc:1), + yc = Y + Yc*(absfocale?absfocale/zc:1), + radius = 0.5f*cimg::hypot(vertices(i1,0) - vertices(i0,0), + vertices(i1,1) - vertices(i0,1), + vertices(i1,2) - vertices(i0,2))*(absfocale?absfocale/zc:1), + xm = xc - radius, + ym = yc - radius, + xM = xc + radius, + yM = yc + radius; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && _zc>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = _zc; + } + is_forward = false; + } break; + case 2 : // Segment + case 6 : { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2); + tpfloat xm, xM, ym, yM; + if (x0=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1)/2; + } + } break; + case 3 : // Triangle + case 9 : { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (y0yM) yM = y2; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) { + const tpfloat d = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2)/3; + } + } + } break; + case 4 : // Rectangle + case 12 : { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = (unsigned int)primitive(3); + const tpfloat + x0 = projections(i0,0), y0 = projections(i0,1), z0 = Z + vertices(i0,2), + x1 = projections(i1,0), y1 = projections(i1,1), z1 = Z + vertices(i1,2), + x2 = projections(i2,0), y2 = projections(i2,1), z2 = Z + vertices(i2,2), + x3 = projections(i3,0), y3 = projections(i3,1), z3 = Z + vertices(i3,2); + tpfloat xm, xM, ym, yM; + if (x0xM) xM = x2; + if (x3xM) xM = x3; + if (y0yM) yM = y2; + if (y3yM) yM = y3; + if (xM>=0 && xm<_width && yM>=0 && ym<_height && z0>zmin && z1>zmin && z2>zmin) { + const float d = (x1 - x0)*(y2 - y0) - (x2 - x0)*(y1 - y0); + if (is_double_sided || d<0) { + visibles(l) = (unsigned int)l; + zrange(l) = (z0 + z1 + z2 + z3)/4; + } + } + } break; + default : + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Invalid primitive[%u] with size %u " + "(should have size 1,2,3,4,5,6,9 or 12).", + cimg_instance, + l,primitive.size()); + } + } + + // Force transparent primitives to be drawn last when zbuffer is activated + // (and if object contains no spheres or sprites). + if (is_forward) + cimglist_for(primitives,l) + if (___draw_object3d(opacities,l)!=1) zrange(l) = 2*zmax - zrange(l); + + // Sort only visibles primitives. + unsigned int *p_visibles = visibles._data; + tpfloat *p_zrange = zrange._data; + const tpfloat *ptrz = p_zrange; + cimg_for(visibles,ptr,unsigned int) { + if (*ptr!=~0U) { *(p_visibles++) = *ptr; *(p_zrange++) = *ptrz; } + ++ptrz; + } + const unsigned int nb_visibles = (unsigned int)(p_zrange - zrange._data); + if (!nb_visibles) { + if (render_type==5) cimg::mutex(10,0); + return *this; + } + CImg permutations; + CImg(zrange._data,nb_visibles,1,1,1,true).sort(permutations,is_forward); + + // Compute light properties + CImg lightprops; + switch (render_type) { + case 3 : { // Flat Shading + lightprops.assign(nb_visibles); + cimg_pragma_openmp(parallel for cimg_openmp_if(nb_visibles>4096)) + cimg_forX(lightprops,l) { + const CImg& primitive = primitives(visibles(permutations(l))); + const unsigned int psize = (unsigned int)primitive.size(); + if (psize==3 || psize==4 || psize==9 || psize==12) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2); + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nx = dy1*dz2 - dz1*dy2, + ny = dz1*dx2 - dx1*dz2, + nz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + (x0 + x1 + x2)/3 - lightx, + ly = Y + (y0 + y1 + y2)/3 - lighty, + lz = Z + (z0 + z1 + z2)/3 - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max(cimg::abs(-lx*nx - ly*ny - lz*nz)/(norm*nl),0.0f); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } else lightprops[l] = 1; + } + } break; + + case 4 : // Gouraud Shading + case 5 : { // Phong-Shading + CImg vertices_normals(vertices._width,6,1,1,0); + cimg_pragma_openmp(parallel for cimg_openmp_if(nb_visibles>4096)) + for (unsigned int l = 0; l& primitive = primitives[visibles(l)]; + const unsigned int psize = (unsigned int)primitive.size(); + const bool + triangle_flag = (psize==3) || (psize==9), + rectangle_flag = (psize==4) || (psize==12); + if (triangle_flag || rectangle_flag) { + const unsigned int + i0 = (unsigned int)primitive(0), + i1 = (unsigned int)primitive(1), + i2 = (unsigned int)primitive(2), + i3 = rectangle_flag?(unsigned int)primitive(3):0; + const tpfloat + x0 = (tpfloat)vertices(i0,0), y0 = (tpfloat)vertices(i0,1), z0 = (tpfloat)vertices(i0,2), + x1 = (tpfloat)vertices(i1,0), y1 = (tpfloat)vertices(i1,1), z1 = (tpfloat)vertices(i1,2), + x2 = (tpfloat)vertices(i2,0), y2 = (tpfloat)vertices(i2,1), z2 = (tpfloat)vertices(i2,2), + dx1 = x1 - x0, dy1 = y1 - y0, dz1 = z1 - z0, + dx2 = x2 - x0, dy2 = y2 - y0, dz2 = z2 - z0, + nnx = dy1*dz2 - dz1*dy2, + nny = dz1*dx2 - dx1*dz2, + nnz = dx1*dy2 - dy1*dx2, + norm = 1e-5f + cimg::hypot(nnx,nny,nnz), + nx = nnx/norm, + ny = nny/norm, + nz = nnz/norm; + unsigned int ix = 0, iy = 1, iz = 2; + if (is_double_sided && nz>0) { ix = 3; iy = 4; iz = 5; } + vertices_normals(i0,ix)+=nx; vertices_normals(i0,iy)+=ny; vertices_normals(i0,iz)+=nz; + vertices_normals(i1,ix)+=nx; vertices_normals(i1,iy)+=ny; vertices_normals(i1,iz)+=nz; + vertices_normals(i2,ix)+=nx; vertices_normals(i2,iy)+=ny; vertices_normals(i2,iz)+=nz; + if (rectangle_flag) { + vertices_normals(i3,ix)+=nx; vertices_normals(i3,iy)+=ny; vertices_normals(i3,iz)+=nz; + } + } + } + + if (is_double_sided) cimg_forX(vertices_normals,p) { + const float + nx0 = vertices_normals(p,0), ny0 = vertices_normals(p,1), nz0 = vertices_normals(p,2), + nx1 = vertices_normals(p,3), ny1 = vertices_normals(p,4), nz1 = vertices_normals(p,5), + n0 = nx0*nx0 + ny0*ny0 + nz0*nz0, n1 = nx1*nx1 + ny1*ny1 + nz1*nz1; + if (n1>n0) { + vertices_normals(p,0) = -nx1; + vertices_normals(p,1) = -ny1; + vertices_normals(p,2) = -nz1; + } + } + + if (render_type==4) { + lightprops.assign(vertices._width); + cimg_pragma_openmp(parallel for cimg_openmp_if(nb_visibles>4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + lx = X + vertices(l,0) - lightx, + ly = Y + vertices(l,1) - lighty, + lz = Z + vertices(l,2) - lightz, + nl = 1e-5f + cimg::hypot(lx,ly,lz), + factor = std::max((-lx*nx - ly*ny - lz*nz)/(norm*nl),0.0f); + lightprops[l] = factor<=nspec?factor:(nsl1*factor*factor + nsl2*factor + nsl3); + } + } else { + const unsigned int + lw2 = light_texture._width/2 - 1, + lh2 = light_texture._height/2 - 1; + lightprops.assign(vertices._width,2); + cimg_pragma_openmp(parallel for cimg_openmp_if(nb_visibles>4096)) + cimg_forX(lightprops,l) { + const tpfloat + nx = vertices_normals(l,0), + ny = vertices_normals(l,1), + nz = vertices_normals(l,2), + norm = 1e-5f + cimg::hypot(nx,ny,nz), + nnx = nx/norm, + nny = ny/norm; + lightprops(l,0) = lw2*(1 + nnx); + lightprops(l,1) = lh2*(1 + nny); + } + } + } break; + } + + // Draw visible primitives + const CImg default_color(1,_spectrum,1,1,(tc)200); + CImg<_to> _opacity; + + for (unsigned int l = 0; l& primitive = primitives[n_primitive]; + const CImg + &__color = n_primitive(), + _color = (__color && __color.size()!=_spectrum && __color._spectrum<_spectrum)? + __color.get_resize(-100,-100,-100,_spectrum,0):CImg(), + &color = _color?_color:(__color?__color:default_color); + const tc *const pcolor = color._data; + const float opacity = __draw_object3d(opacities,n_primitive,_opacity); + +#ifdef cimg_use_board + LibBoard::Board &board = *(LibBoard::Board*)pboard; +#endif + + switch (primitive.size()) { + case 1 : { // Colored point or sprite + const unsigned int n0 = (unsigned int)primitive[0]; + const int x0 = (int)projections(n0,0), y0 = (int)projections(n0,1); + + if (_opacity.is_empty()) { // Scalar opacity. + + if (color.size()==_spectrum) { // Colored point. + draw_point(x0,y0,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height()-(float)y0); + } +#endif + } else { // Sprite. + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(color._width*factor), + _sh = (unsigned int)(color._height*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + draw_image(nx0,ny0,sprite,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } else { // Opacity mask. + const tpfloat z = Z + vertices(n0,2); + const float factor = focale<0?1:sprite_scale*(absfocale?absfocale/(z + absfocale):1); + const unsigned int + _sw = (unsigned int)(std::max(color._width,_opacity._width)*factor), + _sh = (unsigned int)(std::max(color._height,_opacity._height)*factor), + sw = _sw?_sw:1, sh = _sh?_sh:1; + const int nx0 = x0 - (int)sw/2, ny0 = y0 - (int)sh/2; + if (sw<=3*_width/2 && sh<=3*_height/2 && + (nx0 + (int)sw/2>=0 || nx0 - (int)sw/2=0 || ny0 - (int)sh/2 + _sprite = (sw!=color._width || sh!=color._height)? + color.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg(), + &sprite = _sprite?_sprite:color; + const CImg<_to> + _nopacity = (sw!=_opacity._width || sh!=_opacity._height)? + _opacity.get_resize(sw,sh,1,-100,render_type<=3?1:3):CImg<_to>(), + &nopacity = _nopacity?_nopacity:_opacity; + draw_image(nx0,ny0,sprite,nopacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128); + board.setFillColor(LibBoard::Color::Null); + board.drawRectangle((float)nx0,height() - (float)ny0,sw,sh); + } +#endif + } + } + } break; + case 2 : { // Colored line + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity); + else draw_line(x0,y0,x1,y1,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 5 : { // Colored sphere + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + is_wireframe = (unsigned int)primitive[2]; + const float + Xc = 0.5f*((float)vertices(n0,0) + (float)vertices(n1,0)), + Yc = 0.5f*((float)vertices(n0,1) + (float)vertices(n1,1)), + Zc = 0.5f*((float)vertices(n0,2) + (float)vertices(n1,2)), + zc = Z + Zc + _focale, + xc = X + Xc*(absfocale?absfocale/zc:1), + yc = Y + Yc*(absfocale?absfocale/zc:1), + radius = 0.5f*cimg::hypot(vertices(n1,0) - vertices(n0,0), + vertices(n1,1) - vertices(n0,1), + vertices(n1,2) - vertices(n0,2))*(absfocale?absfocale/zc:1); + switch (render_type) { + case 0 : + draw_point((int)xc,(int)yc,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot(xc,height() - yc); + } +#endif + break; + case 1 : + draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } +#endif + break; + default : + if (is_wireframe) draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity,~0U); + else draw_circle((int)xc,(int)yc,(int)radius,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + if (!is_wireframe) board.fillCircle(xc,height() - yc,radius); + else { + board.setFillColor(LibBoard::Color::Null); + board.drawCircle(xc,height() - yc,radius); + } + } +#endif + break; + } + } break; + case 6 : { // Textured line + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for line primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1]; + const int + tx0 = (int)primitive[2], ty0 = (int)primitive[3], + tx1 = (int)primitive[4], ty1 = (int)primitive[5], + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale; + if (render_type) { + if (zbuffer) draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity); + else draw_line(x0,y0,x1,y1,color,tx0,ty0,tx1,ty1,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + } +#endif + } else { + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + } +#endif + } + } break; + case 3 : { // Colored triangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity).draw_point(x2,y2,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x0,y0,z0,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x0,y0,x2,y2,pcolor,opacity). + draw_line(x1,y1,x2,y2,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)); + else _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)); +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprops(n0),lightprops(n1),lightprops(n2),opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : { + const unsigned int + lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1), + lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1), + lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); + else draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + } break; + } + } break; + case 4 : { // Colored rectangle + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1), + x3 = (int)projections(n3,0), y3 = (int)projections(n3,1); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale; + + switch (render_type) { + case 0 : + draw_point(x0,y0,pcolor,opacity).draw_point(x1,y1,pcolor,opacity). + draw_point(x2,y2,pcolor,opacity).draw_point(x3,y3,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,pcolor,opacity).draw_line(zbuffer,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,pcolor,opacity).draw_line(zbuffer,x3,y3,z3,x0,y0,z0,pcolor,opacity); + else + draw_line(x0,y0,x1,y1,pcolor,opacity).draw_line(x1,y1,x2,y2,pcolor,opacity). + draw_line(x2,y2,x3,y3,pcolor,opacity).draw_line(x3,y3,x0,y0,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity); + else + draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity).draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(color[0],color[1],color[2],(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,opacity,lightprops(l)); + else + _draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,opacity,lightprops(l)). + _draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,opacity,lightprops(l)); +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1); + board.setPenColorRGBi((unsigned char)(color[0]*lp), + (unsigned char)(color[1]*lp), + (unsigned char)(color[2]*lp),(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,lightprop0,lightprop2,lightprop3,opacity); + else + draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,lightprop0,lightprop2,lightprop3,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1), + lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1), + lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1), + lx3 = (unsigned int)lightprops(n3,0), ly3 = (unsigned int)lightprops(n3,1); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,pcolor,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); + else + draw_triangle(x0,y0,x1,y1,x2,y2,pcolor,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(x0,y0,x2,y2,x3,y3,pcolor,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi((unsigned char)(color[0]), + (unsigned char)(color[1]), + (unsigned char)(color[2]), + (unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + case 9 : { // Textured triangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for triangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2]; + const int + tx0 = (int)primitive[3], ty0 = (int)primitive[4], + tx1 = (int)primitive[5], ty1 = (int)primitive[6], + tx2 = (int)primitive[7], ty2 = (int)primitive[8], + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale; + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x0,y0,z0,x2,y2,z2,color,tx0,ty0,tx2,ty2,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x0,height() - (float)y0,(float)x2,height() - (float)y2); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + } +#endif + break; + case 2 : + if (zbuffer) draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); + else draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)); +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + } +#endif + break; + case 4 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprops(n0),lightprops(n1),lightprops(n2),opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprops(n0), + (float)x1,height() - (float)y1,lightprops(n1), + (float)x2,height() - (float)y2,lightprops(n2)); + } +#endif + break; + case 5 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture, + (unsigned int)lightprops(n0,0),(unsigned int)lightprops(n0,1), + (unsigned int)lightprops(n1,0),(unsigned int)lightprops(n1,1), + (unsigned int)lightprops(n2,0),(unsigned int)lightprops(n2,1), + opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n0,0))), + (int)(light_texture.height()/2*(1 + lightprops(n0,1)))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n1,0))), + (int)(light_texture.height()/2*(1 + lightprops(n1,1)))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lightprops(n2,0))), + (int)(light_texture.height()/2*(1 + lightprops(n2,1)))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + } +#endif + break; + } + } break; + case 12 : { // Textured quadrangle + if (!__color) { + if (render_type==5) cimg::mutex(10,0); + throw CImgArgumentException(_cimg_instance + "draw_object3d(): Undefined texture for quadrangle primitive [%u].", + cimg_instance,n_primitive); + } + const unsigned int + n0 = (unsigned int)primitive[0], + n1 = (unsigned int)primitive[1], + n2 = (unsigned int)primitive[2], + n3 = (unsigned int)primitive[3]; + const int + tx0 = (int)primitive[4], ty0 = (int)primitive[5], + tx1 = (int)primitive[6], ty1 = (int)primitive[7], + tx2 = (int)primitive[8], ty2 = (int)primitive[9], + tx3 = (int)primitive[10], ty3 = (int)primitive[11], + x0 = (int)projections(n0,0), y0 = (int)projections(n0,1), + x1 = (int)projections(n1,0), y1 = (int)projections(n1,1), + x2 = (int)projections(n2,0), y2 = (int)projections(n2,1), + x3 = (int)projections(n3,0), y3 = (int)projections(n3,1); + const float + z0 = vertices(n0,2) + Z + _focale, + z1 = vertices(n1,2) + Z + _focale, + z2 = vertices(n2,2) + Z + _focale, + z3 = vertices(n3,2) + Z + _focale; + + switch (render_type) { + case 0 : + draw_point(x0,y0,color.get_vector_at(tx0<=0?0:tx0>=color.width()?color.width() - 1:tx0, + ty0<=0?0:ty0>=color.height()?color.height() - 1:ty0)._data,opacity). + draw_point(x1,y1,color.get_vector_at(tx1<=0?0:tx1>=color.width()?color.width() - 1:tx1, + ty1<=0?0:ty1>=color.height()?color.height() - 1:ty1)._data,opacity). + draw_point(x2,y2,color.get_vector_at(tx2<=0?0:tx2>=color.width()?color.width() - 1:tx2, + ty2<=0?0:ty2>=color.height()?color.height() - 1:ty2)._data,opacity). + draw_point(x3,y3,color.get_vector_at(tx3<=0?0:tx3>=color.width()?color.width() - 1:tx3, + ty3<=0?0:ty3>=color.height()?color.height() - 1:ty3)._data,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawDot((float)x0,height() - (float)y0); + board.drawDot((float)x1,height() - (float)y1); + board.drawDot((float)x2,height() - (float)y2); + board.drawDot((float)x3,height() - (float)y3); + } +#endif + break; + case 1 : + if (zbuffer) + draw_line(zbuffer,x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(zbuffer,x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(zbuffer,x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(zbuffer,x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); + else + draw_line(x0,y0,z0,x1,y1,z1,color,tx0,ty0,tx1,ty1,opacity). + draw_line(x1,y1,z1,x2,y2,z2,color,tx1,ty1,tx2,ty2,opacity). + draw_line(x2,y2,z2,x3,y3,z3,color,tx2,ty2,tx3,ty3,opacity). + draw_line(x3,y3,z3,x0,y0,z0,color,tx3,ty3,tx0,ty0,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.drawLine((float)x0,height() - (float)y0,(float)x1,height() - (float)y1); + board.drawLine((float)x1,height() - (float)y1,(float)x2,height() - (float)y2); + board.drawLine((float)x2,height() - (float)y2,(float)x3,height() - (float)y3); + board.drawLine((float)x3,height() - (float)y3,(float)x0,height() - (float)y0); + } +#endif + break; + case 2 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 3 : + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l)); +#ifdef cimg_use_board + if (pboard) { + const float lp = std::min(lightprops(l),1); + board.setPenColorRGBi((unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(128*lp), + (unsigned char)(opacity*255)); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x1,height() - (float)y1, + (float)x2,height() - (float)y2); + board.fillTriangle((float)x0,height() - (float)y0, + (float)x2,height() - (float)y2, + (float)x3,height() - (float)y3); + } +#endif + break; + case 4 : { + const float + lightprop0 = lightprops(n0), lightprop1 = lightprops(n1), + lightprop2 = lightprops(n2), lightprop3 = lightprops(n3); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + lightprop0,lightprop1,lightprop2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + lightprop0,lightprop2,lightprop3,opacity); +#ifdef cimg_use_board + if (pboard) { + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,lightprop0, + (float)x1,height() - (float)y1,lightprop1, + (float)x2,height() - (float)y2,lightprop2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,lightprop0, + (float)x2,height() - (float)y2,lightprop2, + (float)x3,height() - (float)y3,lightprop3); + } +#endif + } break; + case 5 : { + const unsigned int + lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1), + lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1), + lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1), + lx3 = (unsigned int)lightprops(n3,0), ly3 = (unsigned int)lightprops(n3,1); + if (zbuffer) + draw_triangle(zbuffer,x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(zbuffer,x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); + else + draw_triangle(x0,y0,z0,x1,y1,z1,x2,y2,z2,color,tx0,ty0,tx1,ty1,tx2,ty2, + light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity). + draw_triangle(x0,y0,z0,x2,y2,z2,x3,y3,z3,color,tx0,ty0,tx2,ty2,tx3,ty3, + light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity); +#ifdef cimg_use_board + if (pboard) { + const float + l0 = light_texture((int)(light_texture.width()/2*(1 + lx0)), (int)(light_texture.height()/2*(1 + ly0))), + l1 = light_texture((int)(light_texture.width()/2*(1 + lx1)), (int)(light_texture.height()/2*(1 + ly1))), + l2 = light_texture((int)(light_texture.width()/2*(1 + lx2)), (int)(light_texture.height()/2*(1 + ly2))), + l3 = light_texture((int)(light_texture.width()/2*(1 + lx3)), (int)(light_texture.height()/2*(1 + ly3))); + board.setPenColorRGBi(128,128,128,(unsigned char)(opacity*255)); + board.fillGouraudTriangle((float)x0,height() - (float)y0,l0, + (float)x1,height() - (float)y1,l1, + (float)x2,height() - (float)y2,l2); + board.fillGouraudTriangle((float)x0,height() -(float)y0,l0, + (float)x2,height() - (float)y2,l2, + (float)x3,height() - (float)y3,l3); + } +#endif + } break; + } + } break; + } + } + + if (render_type==5) cimg::mutex(10,0); + return *this; + } + + //@} + //--------------------------- + // + //! \name Data Input + //@{ + //--------------------------- + + //! Launch simple interface to select a shape from an image. + /** + \param disp Display window to use. + \param feature_type Type of feature to select. Can be { 0=point | 1=line | 2=rectangle | 3=ellipse }. + \param XYZ Pointer to 3 values X,Y,Z which tells about the projection point coordinates, for volumetric images. + **/ + CImg& select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) { + return get_select(disp,feature_type,XYZ,exit_on_anykey).move_to(*this); + } + + //! Simple interface to select a shape from an image \overloading. + CImg& select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) { + return get_select(title,feature_type,XYZ,exit_on_anykey).move_to(*this); + } + + //! Simple interface to select a shape from an image \newinstance. + CImg get_select(CImgDisplay &disp, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + 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. + CImg get_select(const char *const title, + const unsigned int feature_type=2, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,XYZ,0,0,0,exit_on_anykey,true,false); + } + + CImg _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(1,feature_type==0?3:6,1,1,-1); + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + } else if (title) disp.set_title("%s",title); + + CImg thumb; + if (width()>disp.screen_width() || height()>disp.screen_height()) + get_resize(cimg_fitscreen(width(),height(),1),1,-100).move_to(thumb); + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0).set_wheel().show_mouse(); + + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + + int area = 0, starting_area = 0, clicked_area = 0, phase = 0, + X0 = (int)((XYZ?XYZ[0]:(_width - 1)/2)%_width), + Y0 = (int)((XYZ?XYZ[1]:(_height - 1)/2)%_height), + Z0 = (int)((XYZ?XYZ[2]:(_depth - 1)/2)%_depth), + X1 =-1, Y1 = -1, Z1 = -1, + X3d = -1, Y3d = -1, + oX3d = X3d, oY3d = -1, + omx = -1, omy = -1; + float X = -1, Y = -1, Z = -1; + unsigned int old_button = 0, key = 0; + + bool shape_selected = false, text_down = false, visible_cursor = true; + static CImg pose3d; + static bool is_view3d = false, is_axes = true; + if (reset_view3d) { pose3d.assign(); is_view3d = false; } + CImg points3d, opacities3d, sel_opacities3d; + CImgList primitives3d, sel_primitives3d; + CImgList colors3d, sel_colors3d; + CImg visu, visu0, view3d; + CImg text(1024); *text = 0; + + while (!key && !disp.is_closed() && !shape_selected) { + + // Handle mouse motion and selection + int + mx = disp.mouse_x(), + my = disp.mouse_y(); + + const float + mX = mx<0?-1.0f:(float)mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my<0?-1.0f:(float)my*(height() + (depth()>1?depth():0))/disp.height(); + + area = 0; + if (mX>=0 && mY>=0 && mX=0 && mX=height()) { area = 2; X = mX; Z = mY - _height; Y = (float)(phase?Y1:Y0); } + if (mY>=0 && mX>=width() && mY=width() && mY>=height()) area = 4; + if (disp.button()) { if (!clicked_area) clicked_area = area; } else clicked_area = 0; + + CImg filename(32); + + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(1); key = 0; } break; + case cimg::keyPAGEDOWN : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { disp.set_wheel(-1); key = 0; } break; + case cimg::keyA : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_axes = !is_axes; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + is_view3d = !is_view3d; disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).draw_text(0,0," Saving snapshot... ",foreground_color,background_color,0.7f,13).display(disp); + visu0.save(filename); + (+visu0).draw_text(0,0," Snapshot '%s' saved. ",foreground_color,background_color,0.7f,13,filename._data). + display(disp); + } + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).draw_text(0,0," Saving instance... ",foreground_color,background_color,0.7f,13).display(disp); + save(filename); + (+visu0).draw_text(0,0," Instance '%s' saved. ",foreground_color,background_color,0.7f,13,filename._data). + display(disp); + disp.set_key(key,false); key = 0; + } break; + } + + switch (area) { + + case 0 : // When mouse is out of image range. + mx = my = -1; X = Y = Z = -1; + break; + + case 1 : case 2 : case 3 : // When mouse is over the XY,XZ or YZ projections. + if (disp.button()&1 && phase<2 && clicked_area==area) { // When selection has been started (1st step). + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } + if (!(disp.button()&1) && phase>=2 && clicked_area!=area) { // When selection is at 2nd step (for volumes). + switch (starting_area) { + case 1 : if (Z1!=(int)Z) visu0.assign(); Z1 = (int)Z; break; + case 2 : if (Y1!=(int)Y) visu0.assign(); Y1 = (int)Y; break; + case 3 : if (X1!=(int)X) visu0.assign(); X1 = (int)X; break; + } + } + if (disp.button()&2 && clicked_area==area) { // When moving through the image/volume. + if (phase) { + if (_depth>1 && (X1!=(int)X || Y1!=(int)Y || Z1!=(int)Z)) visu0.assign(); + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; + } else { + if (_depth>1 && (X0!=(int)X || Y0!=(int)Y || Z0!=(int)Z)) visu0.assign(); + X0 = (int)X; Y0 = (int)Y; Z0 = (int)Z; + } + } + if (disp.button()&4) { + X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = area = clicked_area = starting_area = 0; + visu0.assign(); + } + if (disp.wheel()) { // When moving through the slices of the volume (with mouse wheel). + if (_depth>1 && !disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT() && + !disp.is_keySHIFTLEFT() && !disp.is_keySHIFTRIGHT() && + !disp.is_keyALT() && !disp.is_keyALTGR()) { + switch (area) { + case 1 : + if (phase) Z = (float)(Z1+=disp.wheel()); else Z = (float)(Z0+=disp.wheel()); + visu0.assign(); break; + case 2 : + if (phase) Y = (float)(Y1+=disp.wheel()); else Y = (float)(Y0+=disp.wheel()); + visu0.assign(); break; + case 3 : + if (phase) X = (float)(X1+=disp.wheel()); else X = (float)(X0+=disp.wheel()); + visu0.assign(); break; + } + disp.set_wheel(); + } else key = ~0U; + } + if ((disp.button()&1)!=old_button) { // When left button has just been pressed or released. + switch (phase) { + case 0 : + if (area==clicked_area) { + X0 = X1 = (int)X; Y0 = Y1 = (int)Y; Z0 = Z1 = (int)Z; starting_area = area; ++phase; + } break; + case 1 : + if (area==starting_area) { + X1 = (int)X; Y1 = (int)Y; Z1 = (int)Z; ++phase; + } else if (!(disp.button()&1)) { X = (float)X0; Y = (float)Y0; Z = (float)Z0; phase = 0; visu0.assign(); } + break; + case 2 : ++phase; break; + } + old_button = disp.button()&1; + } + break; + + case 4 : // When mouse is over the 3d view. + if (is_view3d && points3d) { + X3d = mx - width()*disp.width()/(width() + (depth()>1?depth():0)); + Y3d = my - height()*disp.height()/(height() + (depth()>1?depth():0)); + if (oX3d<0) { oX3d = X3d; oY3d = Y3d; } + // Left + right buttons: reset. + if ((disp.button()&3)==3) { pose3d.assign(); view3d.assign(); oX3d = oY3d = X3d = Y3d = -1; } + else if (disp.button()&1 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Left button: rotate. + const float + R = 0.45f*std::min(view3d._width,view3d._height), + R2 = R*R, + u0 = (float)(oX3d - view3d.width()/2), + v0 = (float)(oY3d - view3d.height()/2), + u1 = (float)(X3d - view3d.width()/2), + v1 = (float)(Y3d - view3d.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.0f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.0f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + pose3d.draw_image(CImg::rotation_matrix(u,v,w,-alpha)*pose3d.get_crop(0,0,2,2)); + view3d.assign(); + } else if (disp.button()&2 && pose3d && oY3d!=Y3d) { // Right button: zoom. + pose3d(3,2)-=(oY3d - Y3d)*1.5f; view3d.assign(); + } + if (disp.wheel()) { // Wheel: zoom + pose3d(3,2)-=disp.wheel()*15; view3d.assign(); disp.set_wheel(); + } + if (disp.button()&4 && pose3d && (oX3d!=X3d || oY3d!=Y3d)) { // Middle button: shift. + pose3d(3,0)-=oX3d - X3d; pose3d(3,1)-=oY3d - Y3d; view3d.assign(); + } + oX3d = X3d; oY3d = Y3d; + } + mx = my = -1; X = Y = Z = -1; + break; + } + + if (phase) { + if (!feature_type) shape_selected = phase?true:false; + else { + if (_depth>1) shape_selected = (phase==3)?true:false; + else shape_selected = (phase==2)?true:false; + } + } + + if (X0<0) X0 = 0; + if (X0>=width()) X0 = width() - 1; + if (Y0<0) Y0 = 0; + if (Y0>=height()) Y0 = height() - 1; + if (Z0<0) Z0 = 0; + if (Z0>=depth()) Z0 = depth() - 1; + if (X1<1) X1 = 0; + if (X1>=width()) X1 = width() - 1; + if (Y1<0) Y1 = 0; + if (Y1>=height()) Y1 = height() - 1; + if (Z1<0) Z1 = 0; + if (Z1>=depth()) Z1 = depth() - 1; + + // Draw visualization image on the display + if (mx!=omx || my!=omy || !visu0 || (_depth>1 && !view3d)) { + + if (!visu0) { // Create image of projected planes. + if (thumb) thumb.__get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + else __get_select(disp,old_normalization,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0).move_to(visu0); + visu0.resize(disp); + view3d.assign(); + points3d.assign(); + } + + if (is_view3d && _depth>1 && !view3d) { // Create 3d view for volumetric images. + const unsigned int + _x3d = (unsigned int)cimg::round((float)_width*visu0._width/(_width + _depth),1,1), + _y3d = (unsigned int)cimg::round((float)_height*visu0._height/(_height + _depth),1,1), + x3d = _x3d>=visu0._width?visu0._width - 1:_x3d, + y3d = _y3d>=visu0._height?visu0._height - 1:_y3d; + CImg(1,2,1,1,64,128).resize(visu0._width - x3d,visu0._height - y3d,1,visu0._spectrum,3). + move_to(view3d); + if (!points3d) { + get_projections3d(primitives3d,colors3d,phase?X1:X0,phase?Y1:Y0,phase?Z1:Z0,true).move_to(points3d); + points3d.append(CImg(8,3,1,1, + 0,_width - 1,_width - 1,0,0,_width - 1,_width - 1,0, + 0,0,_height - 1,_height - 1,0,0,_height - 1,_height - 1, + 0,0,0,0,_depth - 1,_depth - 1,_depth - 1,_depth - 1),'x'); + CImg::vector(12,13).move_to(primitives3d); CImg::vector(13,14).move_to(primitives3d); + CImg::vector(14,15).move_to(primitives3d); CImg::vector(15,12).move_to(primitives3d); + CImg::vector(16,17).move_to(primitives3d); CImg::vector(17,18).move_to(primitives3d); + CImg::vector(18,19).move_to(primitives3d); CImg::vector(19,16).move_to(primitives3d); + CImg::vector(12,16).move_to(primitives3d); CImg::vector(13,17).move_to(primitives3d); + CImg::vector(14,18).move_to(primitives3d); CImg::vector(15,19).move_to(primitives3d); + colors3d.insert(12,CImg::vector(255,255,255)); + opacities3d.assign(primitives3d.width(),1,1,1,0.5f); + if (!phase) { + opacities3d[0] = opacities3d[1] = opacities3d[2] = 0.8f; + sel_primitives3d.assign(); + sel_colors3d.assign(); + sel_opacities3d.assign(); + } else { + if (feature_type==2) { + points3d.append(CImg(8,3,1,1, + X0,X1,X1,X0,X0,X1,X1,X0, + Y0,Y0,Y1,Y1,Y0,Y0,Y1,Y1, + Z0,Z0,Z0,Z0,Z1,Z1,Z1,Z1),'x'); + sel_primitives3d.assign(); + CImg::vector(20,21).move_to(sel_primitives3d); + CImg::vector(21,22).move_to(sel_primitives3d); + CImg::vector(22,23).move_to(sel_primitives3d); + CImg::vector(23,20).move_to(sel_primitives3d); + CImg::vector(24,25).move_to(sel_primitives3d); + CImg::vector(25,26).move_to(sel_primitives3d); + CImg::vector(26,27).move_to(sel_primitives3d); + CImg::vector(27,24).move_to(sel_primitives3d); + CImg::vector(20,24).move_to(sel_primitives3d); + CImg::vector(21,25).move_to(sel_primitives3d); + CImg::vector(22,26).move_to(sel_primitives3d); + CImg::vector(23,27).move_to(sel_primitives3d); + } else { + points3d.append(CImg(2,3,1,1, + X0,X1, + Y0,Y1, + Z0,Z1),'x'); + sel_primitives3d.assign(CImg::vector(20,21)); + } + sel_colors3d.assign(sel_primitives3d._width,CImg::vector(255,255,255)); + sel_opacities3d.assign(sel_primitives3d._width,1,1,1,0.8f); + } + points3d.shift_object3d(-0.5f*(_width - 1),-0.5f*(_height - 1),-0.5f*(_depth - 1)).resize_object3d(); + points3d*=0.75f*std::min(view3d._width,view3d._height); + } + + if (!pose3d) CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose3d); + CImg zbuffer3d(view3d._width,view3d._height,1,1,0); + const CImg rotated_points3d = pose3d.get_crop(0,0,2,2)*points3d; + if (sel_primitives3d) + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,sel_primitives3d,sel_colors3d,sel_opacities3d, + 2,true,500,0,0,0,0,0,zbuffer3d); + view3d.draw_object3d(pose3d(3,0) + 0.5f*view3d._width, + pose3d(3,1) + 0.5f*view3d._height, + pose3d(3,2), + rotated_points3d,primitives3d,colors3d,opacities3d, + 2,true,500,0,0,0,0,0,zbuffer3d); + visu0.draw_image(x3d,y3d,view3d); + } + visu = visu0; + + if (X<0 || Y<0 || Z<0) { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + else { + if (is_axes) { if (visible_cursor) { disp.hide_mouse(); visible_cursor = false; }} + else { if (!visible_cursor) { disp.show_mouse(); visible_cursor = true; }} + const int d = (depth()>1)?depth():0; + int + _X = (int)X, _Y = (int)Y, _Z = (int)Z, + w = disp.width(), W = width() + d, + h = disp.height(), H = height() + d, + _xp = (int)(_X*(float)w/W), xp = _xp + ((int)(_xp*(float)W/w)!=_X), + _yp = (int)(_Y*(float)h/H), yp = _yp + ((int)(_yp*(float)H/h)!=_Y), + _xn = (int)((_X + 1.0f)*w/W - 1), xn = _xn + ((int)((_xn + 1.0f)*W/w)!=_X + 1), + _yn = (int)((_Y + 1.0f)*h/H - 1), yn = _yn + ((int)((_yn + 1.0f)*H/h)!=_Y + 1), + _zxp = (int)((_Z + width())*(float)w/W), zxp = _zxp + ((int)(_zxp*(float)W/w)!=_Z + width()), + _zyp = (int)((_Z + height())*(float)h/H), zyp = _zyp + ((int)(_zyp*(float)H/h)!=_Z + height()), + _zxn = (int)((_Z + width() + 1.0f)*w/W - 1), + zxn = _zxn + ((int)((_zxn + 1.0f)*W/w)!=_Z + width() + 1), + _zyn = (int)((_Z + height() + 1.0f)*h/H - 1), + zyn = _zyn + ((int)((_zyn + 1.0f)*H/h)!=_Z + height() + 1), + _xM = (int)(width()*(float)w/W - 1), xM = _xM + ((int)((_xM + 1.0f)*W/w)!=width()), + _yM = (int)(height()*(float)h/H - 1), yM = _yM + ((int)((_yM + 1.0f)*H/h)!=height()), + xc = (xp + xn)/2, + yc = (yp + yn)/2, + zxc = (zxp + zxn)/2, + zyc = (zyp + zyn)/2, + xf = (int)(X*w/W), + yf = (int)(Y*h/H), + zxf = (int)((Z + width())*w/W), + zyf = (int)((Z + height())*h/H); + + if (is_axes) { // Draw axes. + visu.draw_line(0,yf,visu.width() - 1,yf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,yf,visu.width() - 1,yf,background_color,0.7f,0x00FF00FF). + draw_line(xf,0,xf,visu.height() - 1,foreground_color,0.7f,0xFF00FF00). + draw_line(xf,0,xf,visu.height() - 1,background_color,0.7f,0x00FF00FF); + if (_depth>1) + visu.draw_line(zxf,0,zxf,yM,foreground_color,0.7f,0xFF00FF00). + draw_line(zxf,0,zxf,yM,background_color,0.7f,0x00FF00FF). + draw_line(0,zyf,xM,zyf,foreground_color,0.7f,0xFF00FF00). + draw_line(0,zyf,xM,zyf,background_color,0.7f,0x00FF00FF); + } + + // Draw box cursor. + if (xn - xp>=4 && yn - yp>=4) visu.draw_rectangle(xp,yp,xn,yn,foreground_color,0.2f). + draw_rectangle(xp,yp,xn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,yp,xn,yn,background_color,1,0x55555555); + if (_depth>1) { + if (yn - yp>=4 && zxn - zxp>=4) visu.draw_rectangle(zxp,yp,zxn,yn,background_color,0.2f). + draw_rectangle(zxp,yp,zxn,yn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(zxp,yp,zxn,yn,background_color,1,0x55555555); + if (xn - xp>=4 && zyn - zyp>=4) visu.draw_rectangle(xp,zyp,xn,zyn,background_color,0.2f). + draw_rectangle(xp,zyp,xn,zyn,foreground_color,1,0xAAAAAAAA). + draw_rectangle(xp,zyp,xn,zyn,background_color,1,0x55555555); + } + + // Draw selection. + if (phase) { + const int + _xp0 = (int)(X0*(float)w/W), xp0 = _xp0 + ((int)(_xp0*(float)W/w)!=X0), + _yp0 = (int)(Y0*(float)h/H), yp0 = _yp0 + ((int)(_yp0*(float)H/h)!=Y0), + _xn0 = (int)((X0 + 1.0f)*w/W - 1), xn0 = _xn0 + ((int)((_xn0 + 1.0f)*W/w)!=X0 + 1), + _yn0 = (int)((Y0 + 1.0f)*h/H - 1), yn0 = _yn0 + ((int)((_yn0 + 1.0f)*H/h)!=Y0 + 1), + _zxp0 = (int)((Z0 + width())*(float)w/W), zxp0 = _zxp0 + ((int)(_zxp0*(float)W/w)!=Z0 + width()), + _zyp0 = (int)((Z0 + height())*(float)h/H), zyp0 = _zyp0 + ((int)(_zyp0*(float)H/h)!=Z0 + height()), + _zxn0 = (int)((Z0 + width() + 1.0f)*w/W - 1), + zxn0 = _zxn0 + ((int)((_zxn0 + 1.0f)*W/w)!=Z0 + width() + 1), + _zyn0 = (int)((Z0 + height() + 1.0f)*h/H - 1), + zyn0 = _zyn0 + ((int)((_zyn0 + 1.0f)*H/h)!=Z0 + height() + 1), + xc0 = (xp0 + xn0)/2, + yc0 = (yp0 + yn0)/2, + zxc0 = (zxp0 + zxn0)/2, + zyc0 = (zyp0 + zyn0)/2; + + switch (feature_type) { + case 1 : { + visu.draw_arrow(xc0,yc0,xc,yc,background_color,0.9f,30,5,0x55555555). + draw_arrow(xc0,yc0,xc,yc,foreground_color,0.9f,30,5,0xAAAAAAAA); + if (d) { + visu.draw_arrow(zxc0,yc0,zxc,yc,background_color,0.9f,30,5,0x55555555). + draw_arrow(zxc0,yc0,zxc,yc,foreground_color,0.9f,30,5,0xAAAAAAAA). + draw_arrow(xc0,zyc0,xc,zyc,background_color,0.9f,30,5,0x55555555). + draw_arrow(xc0,zyc0,xc,zyc,foreground_color,0.9f,30,5,0xAAAAAAAA); + } + } break; + case 2 : { + visu.draw_rectangle(X0=0 && my<13) text_down = true; else if (my>=visu.height() - 13) text_down = false; + if (!feature_type || !phase) { + if (X>=0 && Y>=0 && Z>=0 && X1 || force_display_z_coord) + cimg_snprintf(text,text._width," Point (%d,%d,%d) = [ ",origX + (int)X,origY + (int)Y,origZ + (int)Z); + 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::format_s(), + cimg::type::format((*this)((int)X,(int)Y,(int)Z,c))); + ctext = text._data + std::strlen(text); + *(ctext++) = ' '; *ctext = 0; + } + std::strcpy(text._data + std::strlen(text),"] "); + } + } else switch (feature_type) { + case 1 : { + const double dX = (double)(X0 - X1), dY = (double)(Y0 - Y1), dZ = (double)(Z0 - Z1), + norm = cimg::hypot(dX,dY,dZ); + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width," Vect (%d,%d,%d)-(%d,%d,%d), Norm = %g ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1,norm); + else cimg_snprintf(text,text._width," Vect (%d,%d)-(%d,%d), Norm = %g ", + origX + X0,origY + Y0,origX + X1,origY + Y1,norm); + } break; + case 2 : + if (_depth>1 || force_display_z_coord) + cimg_snprintf(text,text._width," Box (%d,%d,%d)-(%d,%d,%d), Size = (%d,%d,%d) ", + origX + (X01 || force_display_z_coord) + cimg_snprintf(text,text._width," Ellipse (%d,%d,%d)-(%d,%d,%d), Radii = (%d,%d,%d) ", + origX + X0,origY + Y0,origZ + Z0,origX + X1,origY + Y1,origZ + Z1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1),1 + cimg::abs(Z0 - Z1)); + else cimg_snprintf(text,text._width," Ellipse (%d,%d)-(%d,%d), Radii = (%d,%d) ", + origX + X0,origY + Y0,origX + X1,origY + Y1, + 1 + cimg::abs(X0 - X1),1 + cimg::abs(Y0 - Y1)); + } + if (phase || (mx>=0 && my>=0)) + visu.draw_text(0,text_down?visu.height() - 13:0,text,foreground_color,background_color,0.7f,13); + } + + disp.display(visu).wait(); + } else if (!shape_selected) disp.wait(); + if (disp.is_resized()) { disp.resize(false)._is_resized = false; old_is_resized = true; visu0.assign(); } + omx = mx; omy = my; + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + + // Return result. + CImg res(1,feature_type==0?3:6,1,1,-1); + if (XYZ) { XYZ[0] = (unsigned int)X0; XYZ[1] = (unsigned int)Y0; XYZ[2] = (unsigned int)Z0; } + if (shape_selected) { + if (feature_type==2) { + if (X0>X1) cimg::swap(X0,X1); + if (Y0>Y1) cimg::swap(Y0,Y1); + if (Z0>Z1) cimg::swap(Z0,Z1); + } + if (X1<0 || Y1<0 || Z1<0) X0 = Y0 = Z0 = X1 = Y1 = Z1 = -1; + switch (feature_type) { + case 1 : case 2 : res[0] = X0; res[1] = Y0; res[2] = Z0; res[3] = X1; res[4] = Y1; res[5] = Z1; break; + case 3 : + res[3] = cimg::abs(X1 - X0); res[4] = cimg::abs(Y1 - Y0); res[5] = cimg::abs(Z1 - Z0); // keep no break here! + default : res[0] = X0; res[1] = Y0; res[2] = Z0; + } + } + if (!exit_on_anykey || !(disp.button()&4)) disp.set_button(); + if (!visible_cursor) disp.show_mouse(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + if (key!=~0U) disp.set_key(key); + return res; + } + + // Return a visualizable uchar8 image for display routines. + CImg __get_select(const CImgDisplay& disp, const int normalization, + const int x, const int y, const int z) const { + if (is_empty()) return CImg(1,1,1,1,0); + const CImg crop = get_shared_channels(0,std::min(2,spectrum() - 1)); + CImg img2d; + if (_depth>1) { + const int mdisp = std::min(disp.screen_width(),disp.screen_height()); + if (depth()>mdisp) { + crop.get_resize(-100,-100,mdisp,-100,0).move_to(img2d); + img2d.projections2d(x,y,z*img2d._depth/_depth); + } else crop.get_projections2d(x,y,z).move_to(img2d); + } else CImg(crop,false).move_to(img2d); + + // Check for inf and NaN values. + if (cimg::type::is_float() && normalization) { + bool is_inf = false, is_nan = false; + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) { is_inf = true; break; } + else if (cimg::type::is_nan(*ptr)) { is_nan = true; break; } + if (is_inf || is_nan) { + Tint m0 = (Tint)cimg::type::max(), M0 = (Tint)cimg::type::min(); + if (!normalization) { m0 = 0; M0 = 255; } + else if (normalization==2) { m0 = (Tint)disp._min; M0 = (Tint)disp._max; } + else + cimg_for(img2d,ptr,Tuchar) + if (!cimg::type::is_inf(*ptr) && !cimg::type::is_nan(*ptr)) { + if (*ptr<(Tuchar)m0) m0 = *ptr; + if (*ptr>(Tuchar)M0) M0 = *ptr; + } + const T + val_minf = (T)(normalization==1 || normalization==3?m0 - (M0 - m0)*20 - 1:m0), + val_pinf = (T)(normalization==1 || normalization==3?M0 + (M0 - m0)*20 + 1:M0); + if (is_nan) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_nan(*ptr)) *ptr = val_minf; // Replace NaN values. + if (is_inf) + cimg_for(img2d,ptr,Tuchar) + if (cimg::type::is_inf(*ptr)) *ptr = (float)*ptr<0?val_minf:val_pinf; // Replace +-inf values. + } + } + + switch (normalization) { + case 1 : img2d.normalize((T)0,(T)255); break; + case 2 : { + const float m = disp._min, M = disp._max; + (img2d-=m)*=255.0f/(M - m>0?M - m:1); + } break; + case 3 : + if (cimg::type::is_float()) img2d.normalize((T)0,(T)255); + else { + const float m = (float)cimg::type::min(), M = (float)cimg::type::max(); + (img2d-=m)*=255.0f/(M - m>0?M - m:1); + } break; + } + + if (img2d.spectrum()==2) img2d.channels(0,2); + return img2d; + } + + //! Select sub-graph in a graph. + CImg get_select_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "select_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title("CImg<%s>",pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth; + const unsigned int old_normalization = disp.normalization(); + disp.show().set_button().set_wheel()._normalization = 0; + + double nymin = ymin, nymax = ymax, nxmin = xmin, nxmax = xmax; + if (nymin==nymax) { nymin = (Tfloat)min_max(nymax); const double dy = nymax - nymin; nymin-=dy/20; nymax+=dy/20; } + if (nymin==nymax) { --nymin; ++nymax; } + if (nxmin==nxmax && nxmin==0) { nxmin = 0; nxmax = siz - 1.0; } + + static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 }, gray[] = { 220, 220, 220 }; + static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 }; + static unsigned int odimv = 0; + static CImg colormap; + if (odimv!=_spectrum) { + odimv = _spectrum; + colormap = CImg(3,_spectrum,1,1,120).noise(70,1); + if (_spectrum==1) { colormap[0] = colormap[1] = 120; colormap[2] = 200; } + else { + colormap(0,0) = 220; colormap(1,0) = 10; colormap(2,0) = 10; + if (_spectrum>1) { colormap(0,1) = 10; colormap(1,1) = 220; colormap(2,1) = 10; } + if (_spectrum>2) { colormap(0,2) = 10; colormap(1,2) = 10; colormap(2,2) = 220; } + } + } + + CImg visu0, visu, graph, text, axes; + int x0 = -1, x1 = -1, y0 = -1, y1 = -1, omouse_x = -2, omouse_y = -2; + const unsigned int one = plot_type==3?0U:1U; + unsigned int okey = 0, obutton = 0; + CImg message(1024); + CImg_3x3(I,unsigned char); + + for (bool selected = false; !selected && !disp.is_closed() && !okey && !disp.wheel(); ) { + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + const unsigned int key = disp.key(), button = disp.button(); + + // Generate graph representation. + if (!visu0) { + visu0.assign(disp.width(),disp.height(),1,3,220); + const int gdimx = disp.width() - 32, gdimy = disp.height() - 32; + if (gdimx>0 && gdimy>0) { + graph.assign(gdimx,gdimy,1,3,255); + if (siz<32) { + if (siz>1) graph.draw_grid(gdimx/(float)(siz - one),gdimy/(float)(siz - one),0,0, + false,true,black,0.2f,0x33333333,0x33333333); + } else graph.draw_grid(-10,-10,0,0,false,true,black,0.2f,0x33333333,0x33333333); + cimg_forC(*this,c) + graph.draw_graph(get_shared_channel(c),&colormap(0,c),(plot_type!=3 || _spectrum==1)?1:0.6f, + plot_type,vertex_type,nymax,nymin); + + axes.assign(gdimx,gdimy,1,1,0); + const float + dx = (float)cimg::abs(nxmax - nxmin), dy = (float)cimg::abs(nymax - nymin), + px = (float)std::pow(10.0,(int)std::log10(dx?dx:1) - 2.0), + py = (float)std::pow(10.0,(int)std::log10(dy?dy:1) - 2.0); + const CImg + seqx = dx<=0?CImg::vector(nxmin): + CImg::sequence(1 + gdimx/60,nxmin,one?nxmax:nxmin + (nxmax - nxmin)*(siz + 1)/siz).round(px), + seqy = CImg::sequence(1 + gdimy/60,nymax,nymin).round(py); + + const bool allow_zero = (nxmin*nxmax>0) || (nymin*nymax>0); + axes.draw_axes(seqx,seqy,white,1,~0U,~0U,13,allow_zero); + if (nymin>0) axes.draw_axis(seqx,gdimy - 1,gray,1,~0U,13,allow_zero); + if (nymax<0) axes.draw_axis(seqx,0,gray,1,~0U,13,allow_zero); + if (nxmin>0) axes.draw_axis(0,seqy,gray,1,~0U,13,allow_zero); + if (nxmax<0) axes.draw_axis(gdimx - 1,seqy,gray,1,~0U,13,allow_zero); + + cimg_for3x3(axes,x,y,0,0,I,unsigned char) + if (Icc) { + if (Icc==255) cimg_forC(graph,c) graph(x,y,c) = 0; + else cimg_forC(graph,c) graph(x,y,c) = (unsigned char)(2*graph(x,y,c)/3); + } + else if (Ipc || Inc || Icp || Icn || Ipp || Inn || Ipn || Inp) + cimg_forC(graph,c) graph(x,y,c) = (unsigned char)((graph(x,y,c) + 511)/3); + + visu0.draw_image(16,16,graph); + visu0.draw_line(15,15,16 + gdimx,15,gray2).draw_line(16 + gdimx,15,16 + gdimx,16 + gdimy,gray2). + draw_line(16 + gdimx,16 + gdimy,15,16 + gdimy,white).draw_line(15,16 + gdimy,15,15,white); + } else graph.assign(); + text.assign().draw_text(0,0,labelx?labelx:"X-axis",white,ngray,1,13).resize(-100,-100,1,3); + visu0.draw_image((visu0.width() - text.width())/2,visu0.height() - 14,~text); + text.assign().draw_text(0,0,labely?labely:"Y-axis",white,ngray,1,13).rotate(-90).resize(-100,-100,1,3); + visu0.draw_image(1,(visu0.height() - text.height())/2,~text); + visu.assign(); + } + + // Generate and display current view. + if (!visu) { + visu.assign(visu0); + if (graph && x0>=0 && x1>=0) { + const int + nx0 = x0<=x1?x0:x1, + nx1 = x0<=x1?x1:x0, + ny0 = y0<=y1?y0:y1, + ny1 = y0<=y1?y1:y0, + sx0 = (int)(16 + nx0*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sx1 = (int)(15 + (nx1 + 1)*(visu.width() - 32)/std::max((ulongT)1,siz - one)), + sy0 = 16 + ny0, + sy1 = 16 + ny1; + if (y0>=0 && y1>=0) + visu.draw_rectangle(sx0,sy0,sx1,sy1,gray,0.5f).draw_rectangle(sx0,sy0,sx1,sy1,black,0.5f,0xCCCCCCCCU); + else visu.draw_rectangle(sx0,0,sx1,visu.height() - 17,gray,0.5f). + draw_line(sx0,16,sx0,visu.height() - 17,black,0.5f,0xCCCCCCCCU). + draw_line(sx1,16,sx1,visu.height() - 17,black,0.5f,0xCCCCCCCCU); + } + if (mouse_x>=16 && mouse_y>=16 && mouse_x=7) + cimg_snprintf(message,message._width,"Value[%u:%g] = ( %g %g %g ... %g %g %g )",x,cx, + (double)(*this)(x,0,0,0),(double)(*this)(x,0,0,1),(double)(*this)(x,0,0,2), + (double)(*this)(x,0,0,_spectrum - 4),(double)(*this)(x,0,0,_spectrum - 3), + (double)(*this)(x,0,0,_spectrum - 1)); + else { + cimg_snprintf(message,message._width,"Value[%u:%g] = ( ",x,cx); + cimg_forC(*this,c) cimg_sprintf(message._data + std::strlen(message),"%g ",(double)(*this)(x,0,0,c)); + cimg_sprintf(message._data + std::strlen(message),")"); + } + if (x0>=0 && x1>=0) { + const unsigned int + nx0 = (unsigned int)(x0<=x1?x0:x1), + nx1 = (unsigned int)(x0<=x1?x1:x0), + ny0 = (unsigned int)(y0<=y1?y0:y1), + ny1 = (unsigned int)(y0<=y1?y1:y0); + const double + cx0 = nxmin + nx0*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cx1 = nxmin + (nx1 + one)*(nxmax - nxmin)/std::max((ulongT)1,siz - 1), + cy0 = nymax - ny0*(nymax - nymin)/(visu._height - 32), + cy1 = nymax - ny1*(nymax - nymin)/(visu._height - 32); + if (y0>=0 && y1>=0) + cimg_sprintf(message._data + std::strlen(message)," - Range ( %u:%g, %g ) - ( %u:%g, %g )", + x0,cx0,cy0,x1 + one,cx1,cy1); + else + cimg_sprintf(message._data + std::strlen(message)," - Range [ %u:%g - %u:%g ]", + x0,cx0,x1 + one,cx1); + } + text.assign().draw_text(0,0,message,white,ngray,1,13).resize(-100,-100,1,3); + visu.draw_image((visu.width() - text.width())/2,1,~text); + } + visu.display(disp); + } + + // Test keys. + CImg filename(32); + switch (okey = key) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case cimg::keyCTRLLEFT : case cimg::keySHIFTLEFT : okey = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1),false)._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).draw_text(0,0," Saving snapshot... ",black,gray,1,13).display(disp); + screen.save(filename); + (+screen).draw_text(0,0," Snapshot '%s' saved. ",black,gray,1,13,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + if (visu || visu0) { + CImg &screen = visu?visu:visu0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+screen).draw_text(0,0," Saving instance... ",black,gray,1,13).display(disp); + save(filename); + (+screen).draw_text(0,0," Instance '%s' saved. ",black,gray,1,13,filename._data).display(disp); + } + disp.set_key(key,false); okey = 0; + } break; + } + + // Handle mouse motion and mouse buttons + if (obutton!=button || omouse_x!=mouse_x || omouse_y!=mouse_y) { + visu.assign(); + if (disp.mouse_x()>=0 && disp.mouse_y()>=0) { + const int + mx = (mouse_x - 16)*(int)(siz - one)/(disp.width() - 32), + cx = cimg::cut(mx,0,(int)(siz - 1 - one)), + my = mouse_y - 16, + cy = cimg::cut(my,0,disp.height() - 32); + if (button&1) { + if (!obutton) { x0 = cx; y0 = -1; } else { x1 = cx; y1 = -1; } + } + else if (button&2) { + if (!obutton) { x0 = cx; y0 = cy; } else { x1 = cx; y1 = cy; } + } + else if (obutton) { x1 = x1>=0?cx:-1; y1 = y1>=0?cy:-1; selected = true; } + } else if (!button && obutton) selected = true; + obutton = button; omouse_x = mouse_x; omouse_y = mouse_y; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (visu && visu0) disp.wait(); + if (!exit_on_anykey && okey && okey!=cimg::keyESC && + (okey!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + okey = 0; + } + } + + disp._normalization = old_normalization; + if (x1>=0 && x1(4,1,1,1,x0,y0,x1>=0?x1 + (int)one:-1,y1); + } + + //! Load image from a file. + /** + \param filename Filename, as a C-string. + \note The extension of \c filename defines the file format. If no filename + extension is provided, CImg::get_load() will try to load the file as a .cimg or .cimgz file. + **/ + CImg& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load(): Specified filename is (null).", + cimg_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimg_load_plugin + cimg_load_plugin(filename); +#endif +#ifdef cimg_load_plugin1 + cimg_load_plugin1(filename); +#endif +#ifdef cimg_load_plugin2 + cimg_load_plugin2(filename); +#endif +#ifdef cimg_load_plugin3 + cimg_load_plugin3(filename); +#endif +#ifdef cimg_load_plugin4 + cimg_load_plugin4(filename); +#endif +#ifdef cimg_load_plugin5 + cimg_load_plugin5(filename); +#endif +#ifdef cimg_load_plugin6 + cimg_load_plugin6(filename); +#endif +#ifdef cimg_load_plugin7 + cimg_load_plugin7(filename); +#endif +#ifdef cimg_load_plugin8 + cimg_load_plugin8(filename); +#endif + // Ascii formats + if (!cimg::strcasecmp(ext,"asc")) load_ascii(filename); + else if (!cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) load_dlm(filename); + + // 2d binary formats + else if (!cimg::strcasecmp(ext,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) load_jpeg(filename); + else if (!cimg::strcasecmp(ext,"png")) load_png(filename); + else if (!cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"pnm") || + !cimg::strcasecmp(ext,"pbm") || + !cimg::strcasecmp(ext,"pnk")) load_pnm(filename); + else if (!cimg::strcasecmp(ext,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"exr")) load_exr(filename); + else if (!cimg::strcasecmp(ext,"cr2") || + !cimg::strcasecmp(ext,"crw") || + !cimg::strcasecmp(ext,"dcr") || + !cimg::strcasecmp(ext,"mrw") || + !cimg::strcasecmp(ext,"nef") || + !cimg::strcasecmp(ext,"orf") || + !cimg::strcasecmp(ext,"pix") || + !cimg::strcasecmp(ext,"ptx") || + !cimg::strcasecmp(ext,"raf") || + !cimg::strcasecmp(ext,"srf")) load_dcraw_external(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + + // 3d binary formats + else if (!cimg::strcasecmp(ext,"dcm") || + !cimg::strcasecmp(ext,"dicom")) load_medcon_external(filename); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) load_analyze(filename); + else if (!cimg::strcasecmp(ext,"par") || + !cimg::strcasecmp(ext,"rec")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"mnc")) load_minc2(filename); + else if (!cimg::strcasecmp(ext,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(ext,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) return load_cimg(filename); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + + // Image sequences + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded) { + std::FILE *file = std::fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to open file '%s'.", + cimg_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + std::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"pnm")) load_pnm(filename); + else if (!cimg::strcasecmp(f_type,"pfm")) load_pfm(filename); + else if (!cimg::strcasecmp(f_type,"bmp")) load_bmp(filename); + else if (!cimg::strcasecmp(f_type,"inr")) load_inr(filename); + else if (!cimg::strcasecmp(f_type,"jpg")) load_jpeg(filename); + else if (!cimg::strcasecmp(f_type,"pan")) load_pandore(filename); + else if (!cimg::strcasecmp(f_type,"png")) load_png(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"dcm")) load_medcon_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file with other means. + if (!is_loaded) { + try { + load_other(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image from a file \newinstance. + static CImg get_load(const char *const filename) { + return CImg().load(filename); + } + + //! Load image from an ascii file. + /** + \param filename Filename, as a C -string. + **/ + CImg& load_ascii(const char *const filename) { + return _load_ascii(0,filename); + } + + //! Load image from an ascii file \inplace. + static CImg get_load_ascii(const char *const filename) { + return CImg().load_ascii(filename); + } + + //! Load image from an ascii file \overloading. + CImg& load_ascii(std::FILE *const file) { + return _load_ascii(file,0); + } + + //! Loadimage from an ascii file \newinstance. + static CImg get_load_ascii(std::FILE *const file) { + return CImg().load_ascii(file); + } + + CImg& _load_ascii(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_ascii(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg line(256); *line = 0; + int err = std::fscanf(nfile,"%255[^\n]",line._data); + unsigned int dx = 0, dy = 1, dz = 1, dc = 1; + cimg_sscanf(line,"%u%*c%u%*c%u%*c%u",&dx,&dy,&dz,&dc); + err = std::fscanf(nfile,"%*[^0-9.eEinfa+-]"); + if (!dx || !dy || !dz || !dc) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_ascii(): Invalid ascii header in file '%s', image dimensions are set " + "to (%u,%u,%u,%u).", + cimg_instance, + filename?filename:"(FILE*)",dx,dy,dz,dc); + } + assign(dx,dy,dz,dc); + const ulongT siz = size(); + ulongT off = 0; + double val; + T *ptr = _data; + for (err = 1, off = 0; off& load_dlm(const char *const filename) { + return _load_dlm(0,filename); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(const char *const filename) { + return CImg().load_dlm(filename); + } + + //! Load image from a DLM file \overloading. + CImg& load_dlm(std::FILE *const file) { + return _load_dlm(file,0); + } + + //! Load image from a DLM file \newinstance. + static CImg get_load_dlm(std::FILE *const file) { + return CImg().load_dlm(file); + } + + CImg& _load_dlm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_dlm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + CImg delimiter(256), tmp(256); *delimiter = *tmp = 0; + unsigned int cdx = 0, dx = 0, dy = 0; + int err = 0; + double val; + assign(256,256,1,1,(T)0); + while ((err = std::fscanf(nfile,"%lf%255[^0-9eEinfa.+-]",&val,delimiter._data))>0) { + if (err>0) (*this)(cdx++,dy) = (T)val; + if (cdx>=_width) resize(3*_width/2,_height,1,1,0); + char c = 0; + if (!cimg_sscanf(delimiter,"%255[^\n]%c",tmp._data,&c) || c=='\n') { + dx = std::max(cdx,dx); + if (++dy>=_height) resize(_width,3*_height/2,1,1,0); + cdx = 0; + } + } + if (cdx && err==1) { dx = cdx; ++dy; } + if (!dx || !dy) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_dlm(): Invalid DLM file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + resize(dx,dy,1,1,0); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a BMP file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_bmp(const char *const filename) { + return _load_bmp(0,filename); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(const char *const filename) { + return CImg().load_bmp(filename); + } + + //! Load image from a BMP file \overloading. + CImg& load_bmp(std::FILE *const file) { + return _load_bmp(file,0); + } + + //! Load image from a BMP file \newinstance. + static CImg get_load_bmp(std::FILE *const file) { + return CImg().load_bmp(file); + } + + CImg& _load_bmp(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_bmp(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(54); + cimg::fread(header._data,54,nfile); + if (*header!='B' || header[1]!='M') { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_bmp(): Invalid BMP file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read header and pixel buffer + int + file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24), + offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24), + header_size = header[0x0E] + (header[0x0F]<<8) + (header[0x10]<<16) + (header[0x11]<<24), + dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24), + dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24), + compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24), + nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24), + bpp = header[0x1C] + (header[0x1D]<<8); + + if (!file_size || file_size==offset) { + cimg::fseek(nfile,0,SEEK_END); + file_size = (int)cimg::ftell(nfile); + cimg::fseek(nfile,54,SEEK_SET); + } + 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)):(dx*bpp/8)), + align_bytes = (4 - dx_bytes%4)%4; + const longT + cimg_iobuffer = (longT)24*1024*1024, + buf_size = std::min((longT)cimg::abs(dy)*(dx_bytes + align_bytes),(longT)file_size - offset); + + CImg colormap; + if (bpp<16) { if (!nb_colors) nb_colors = 1<0) cimg::fseek(nfile,xoffset,SEEK_CUR); + + CImg buffer; + if (buf_size=0; --y) { + if (buf_size>=cimg_iobuffer) { + cimg::fread(ptrs=buffer._data,dx_bytes,nfile); + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0x80, val = 0; + cimg_forX(*this,x) { + if (mask==0x80) val = *(ptrs++); + const unsigned char *col = (unsigned char*)(colormap._data + (val&mask?1:0)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask); + } + ptrs+=align_bytes; + } + } break; + case 4 : { // 16 colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + cimg::fread(ptrs=buffer._data,dx_bytes,nfile); + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + unsigned char mask = 0xF0, val = 0; + cimg_forX(*this,x) { + if (mask==0xF0) val = *(ptrs++); + const unsigned char color = (unsigned char)((mask<16)?(val&mask):((val&mask)>>4)); + const unsigned char *col = (unsigned char*)(colormap._data + color); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + mask = cimg::ror(mask,4); + } + ptrs+=align_bytes; + } + } break; + case 8 : { // 256 colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + cimg::fread(ptrs=buffer._data,dx_bytes,nfile); + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char *col = (unsigned char*)(colormap._data + *(ptrs++)); + (*this)(x,y,2) = (T)*(col++); + (*this)(x,y,1) = (T)*(col++); + (*this)(x,y,0) = (T)*(col++); + } + ptrs+=align_bytes; + } + } break; + case 16 : { // 16 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + cimg::fread(ptrs=buffer._data,dx_bytes,nfile); + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + const unsigned char c1 = *(ptrs++), c2 = *(ptrs++); + const unsigned short col = (unsigned short)(c1|(c2<<8)); + (*this)(x,y,2) = (T)(col&0x1F); + (*this)(x,y,1) = (T)((col>>5)&0x1F); + (*this)(x,y,0) = (T)((col>>10)&0x1F); + } + ptrs+=align_bytes; + } + } break; + case 24 : { // 24 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + cimg::fread(ptrs=buffer._data,dx_bytes,nfile); + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + } + ptrs+=align_bytes; + } + } break; + case 32 : { // 32 bits colors + for (int y = height() - 1; y>=0; --y) { + if (buf_size>=cimg_iobuffer) { + cimg::fread(ptrs=buffer._data,dx_bytes,nfile); + cimg::fseek(nfile,align_bytes,SEEK_CUR); + } + cimg_forX(*this,x) { + (*this)(x,y,2) = (T)*(ptrs++); + (*this)(x,y,1) = (T)*(ptrs++); + (*this)(x,y,0) = (T)*(ptrs++); + ++ptrs; + } + ptrs+=align_bytes; + } + } break; + } + if (dy<0) mirror('y'); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a JPEG file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_jpeg(const char *const filename) { + return _load_jpeg(0,filename); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(const char *const filename) { + return CImg().load_jpeg(filename); + } + + //! Load image from a JPEG file \overloading. + CImg& load_jpeg(std::FILE *const file) { + return _load_jpeg(file,0); + } + + //! Load image from a JPEG file \newinstance. + static CImg get_load_jpeg(std::FILE *const file) { + return CImg().load_jpeg(file); + } + + // Custom error handler for libjpeg. +#ifdef cimg_use_jpeg + struct _cimg_error_mgr { + struct jpeg_error_mgr original; + jmp_buf setjmp_buffer; + char message[JMSG_LENGTH_MAX]; + }; + + typedef struct _cimg_error_mgr *_cimg_error_ptr; + + METHODDEF(void) _cimg_jpeg_error_exit(j_common_ptr cinfo) { + _cimg_error_ptr c_err = (_cimg_error_ptr) cinfo->err; // Return control to the setjmp point + (*cinfo->err->format_message)(cinfo,c_err->message); + jpeg_destroy(cinfo); // Clean memory and temp files. + longjmp(c_err->setjmp_buffer,1); + } +#endif + + CImg& _load_jpeg(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_jpeg(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_jpeg + if (file) + throw CImgIOException(_cimg_instance + "load_jpeg(): Unable to load data from '(FILE*)' unless libjpeg is enabled.", + cimg_instance); + else return load_other(filename); +#else + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + struct jpeg_decompress_struct cinfo; + struct _cimg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.original); + jerr.original.error_exit = _cimg_jpeg_error_exit; + if (setjmp(jerr.setjmp_buffer)) { // JPEG error + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_jpeg(): Error message returned by libjpeg: %s.", + cimg_instance,jerr.message); + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo,nfile); + jpeg_read_header(&cinfo,TRUE); + jpeg_start_decompress(&cinfo); + + if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) { + if (!file) { + cimg::fclose(nfile); + return load_other(filename); + } else + throw CImgIOException(_cimg_instance + "load_jpeg(): Failed to load JPEG data from file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + } + CImg buffer(cinfo.output_width*cinfo.output_components); + JSAMPROW row_pointer[1]; + try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); } + catch (...) { if (!file) cimg::fclose(nfile); throw; } + T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height, + *ptr_a = _data + 3UL*_width*_height; + while (cinfo.output_scanline + // This is experimental code, not much tested, use with care. + CImg& load_magick(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_magick(): Specified filename is (null).", + cimg_instance); +#ifdef cimg_use_magick + Magick::Image image(filename); + const unsigned int W = image.size().width(), H = image.size().height(); + switch (image.type()) { + case Magick::PaletteMatteType : + case Magick::TrueColorMatteType : + case Magick::ColorSeparationType : { + assign(W,H,1,4); + 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); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + case Magick::PaletteType : + case Magick::TrueColorType : { + assign(W,H,1,3); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_g++) = (T)(pixels->green); + *(ptr_b++) = (T)(pixels->blue); + ++pixels; + } + } break; + case Magick::GrayscaleMatteType : { + assign(W,H,1,2); + T *ptr_r = data(0,0,0,0), *ptr_a = data(0,0,0,1); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + *(ptr_a++) = (T)(pixels->opacity); + ++pixels; + } + } break; + default : { + assign(W,H,1,1); + T *ptr_r = data(0,0,0,0); + Magick::PixelPacket *pixels = image.getPixels(0,0,W,H); + for (ulongT off = (ulongT)W*H; off; --off) { + *(ptr_r++) = (T)(pixels->red); + ++pixels; + } + } + } + return *this; +#else + throw CImgIOException(_cimg_instance + "load_magick(): Unable to load file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Load image from a file, using Magick++ library \newinstance. + static CImg get_load_magick(const char *const filename) { + return CImg().load_magick(filename); + } + + //! Load image from a PNG file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_png(const char *const filename, unsigned int *const bits_per_pixel=0) { + return _load_png(0,filename,bits_per_pixel); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(const char *const filename, unsigned int *const bits_per_pixel=0) { + return CImg().load_png(filename,bits_per_pixel); + } + + //! Load image from a PNG file \overloading. + CImg& load_png(std::FILE *const file, unsigned int *const bits_per_pixel=0) { + return _load_png(file,0,bits_per_pixel); + } + + //! Load image from a PNG file \newinstance. + static CImg get_load_png(std::FILE *const file, unsigned int *const bits_per_pixel=0) { + return CImg().load_png(file,bits_per_pixel); + } + + // (Note: Most of this function has been written by Eric Fausett) + CImg& _load_png(std::FILE *const file, const char *const filename, unsigned int *const bits_per_pixel) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_png(): Specified filename is (null).", + cimg_instance); + +#ifndef cimg_use_png + cimg::unused(bits_per_pixel); + if (file) + throw CImgIOException(_cimg_instance + "load_png(): Unable to load data from '(FILE*)' unless libpng is enabled.", + cimg_instance); + + else return load_other(filename); +#else + // Open file and check for PNG validity + const char *volatile nfilename = filename; // two 'volatile' here to remove a g++ warning due to 'setjmp'. + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb"); + + unsigned char pngCheck[8] = { 0 }; + cimg::fread(pngCheck,8,(std::FILE*)nfile); + if (png_sig_cmp(pngCheck,0,8)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Invalid PNG file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Setup PNG structures for read + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn); + if (!png_ptr) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'png_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,(png_infopp)0,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'info_ptr' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Failed to initialize 'end_info' structure for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + + // Error handling callback for png file reading + if (setjmp(png_jmpbuf(png_ptr))) { + if (!file) cimg::fclose((std::FILE*)nfile); + png_destroy_read_struct(&png_ptr, &end_info, (png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Encountered unknown fatal error in libpng for file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + png_set_sig_bytes(png_ptr, 8); + + // Get PNG Header Info up to data block + png_read_info(png_ptr,info_ptr); + png_uint_32 W, H; + int bit_depth, color_type, interlace_type; + bool is_gray = false; + png_get_IHDR(png_ptr,info_ptr,&W,&H,&bit_depth,&color_type,&interlace_type,(int*)0,(int*)0); + if (bits_per_pixel) *bits_per_pixel = (unsigned int)bit_depth; + + // Transforms to unify image data + if (color_type==PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + color_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + } + if (color_type==PNG_COLOR_TYPE_GRAY && bit_depth<8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + is_gray = true; + bit_depth = 8; + } + if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) { + png_set_tRNS_to_alpha(png_ptr); + color_type |= PNG_COLOR_MASK_ALPHA; + } + if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA) { + png_set_gray_to_rgb(png_ptr); + color_type |= PNG_COLOR_MASK_COLOR; + is_gray = true; + } + if (color_type==PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr,0xffffU,PNG_FILLER_AFTER); + + png_read_update_info(png_ptr,info_ptr); + if (bit_depth!=8 && bit_depth!=16) { + if (!file) cimg::fclose(nfile); + png_destroy_read_struct(&png_ptr,&end_info,(png_infopp)0); + throw CImgIOException(_cimg_instance + "load_png(): Invalid bit depth %u in file '%s'.", + cimg_instance, + bit_depth,nfilename?nfilename:"(FILE*)"); + } + const int byte_depth = bit_depth>>3; + + // Allocate Memory for Image Read + png_bytep *const imgData = new png_bytep[H]; + for (unsigned int row = 0; row& load_pnm(const char *const filename) { + return _load_pnm(0,filename); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(const char *const filename) { + return CImg().load_pnm(filename); + } + + //! Load image from a PNM file \overloading. + CImg& load_pnm(std::FILE *const file) { + return _load_pnm(file,0); + } + + //! Load image from a PNM file \newinstance. + static CImg get_load_pnm(std::FILE *const file) { + return CImg().load_pnm(file); + } + + CImg& _load_pnm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pnm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + unsigned int ppm_type, W, H, D = 1, colormax = 255; + CImg item(16384,1,1,1,0); + int err, rval, gval, bval; + const longT cimg_iobuffer = (longT)24*1024*1024; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%u",&ppm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %u %u %u %u",&W,&H,&D,&colormax))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): WIDTH and HEIGHT fields undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (ppm_type!=1 && ppm_type!=4) { + if (err==2 || (err==3 && (ppm_type==5 || ppm_type==7 || ppm_type==8 || ppm_type==9))) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%u",&colormax)!=1) + cimg::warn(_cimg_instance + "load_pnm(): COLORMAX field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } else { colormax = D; D = 1; } + } + std::fgetc(nfile); + + switch (ppm_type) { + case 1 : { // 2d b&w ascii. + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)(rval?0:255); else break; } + } break; + case 2 : { // 2d grey ascii. + assign(W,H,1,1); + T* ptrd = _data; + cimg_foroff(*this,off) { if (std::fscanf(nfile,"%d",&rval)>0) *(ptrd++) = (T)rval; else break; } + } break; + case 3 : { // 2d color ascii. + assign(W,H,1,3); + T *ptrd = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forXY(*this,x,y) { + if (std::fscanf(nfile,"%d %d %d",&rval,&gval,&bval)==3) { + *(ptrd++) = (T)rval; *(ptr_g++) = (T)gval; *(ptr_b++) = (T)bval; + } else break; + } + } break; + case 4 : { // 2d b&w binary (support 3D PINK extension). + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + unsigned int w = 0, h = 0, d = 0; + for (longT to_read = (longT)((W/8 + (W%8?1:0))*H*D); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + unsigned char mask = 0, val = 0; + for (ulongT off = (ulongT)raw._width; off || mask; mask>>=1) { + if (!mask) { if (off--) val = *(ptrs++); mask = 128; } + *(ptrd++) = (T)((val&mask)?0:255); + if (++w==W) { w = 0; mask = 0; if (++h==H) { h = 0; if (++d==D) break; }} + } + } + } break; + case 5 : case 7 : { // 2d/3d grey binary (support 3D PINK extension). + if (colormax<256) { // 8 bits. + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } else { // 16 bits. + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } + } break; + case 6 : { // 2d color binary. + if (colormax<256) { // 8 bits. + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { // 16 bits. + CImg raw; + assign(W,H,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer/2)); + cimg::fread(raw._data,raw._width,nfile); + if (!cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); + to_read-=raw._width; + const unsigned short *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width/3; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } + } break; + case 8 : { // 2d/3d grey binary with int32 integers (PINK extension). + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const int *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + case 9 : { // 2d/3d grey binary with float values (PINK extension). + CImg raw; + assign(W,H,D,1); + T *ptrd = data(0,0,0,0); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const float *ptrs = raw._data; + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); + } + } break; + default : + assign(); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pnm(): PNM type 'P%d' found, but type is not supported.", + cimg_instance, + filename?filename:"(FILE*)",ppm_type); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PFM file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pfm(const char *const filename) { + return _load_pfm(0,filename); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(const char *const filename) { + return CImg().load_pfm(filename); + } + + //! Load image from a PFM file \overloading. + CImg& load_pfm(std::FILE *const file) { + return _load_pfm(file,0); + } + + //! Load image from a PFM file \newinstance. + static CImg get_load_pfm(std::FILE *const file) { + return CImg().load_pfm(file); + } + + CImg& _load_pfm(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pfm(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + char pfm_type; + CImg item(16384,1,1,1,0); + int W = 0, H = 0, err = 0; + double scale = 0; + while ((err=std::fscanf(nfile,"%16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item," P%c",&pfm_type)!=1) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): PFM header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if ((err=cimg_sscanf(item," %d %d",&W,&H))<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pfm(): WIDTH and HEIGHT fields are undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (err==2) { + while ((err=std::fscanf(nfile," %16383[^\n]",item.data()))!=EOF && (*item=='#' || !err)) std::fgetc(nfile); + if (cimg_sscanf(item,"%lf",&scale)!=1) + cimg::warn(_cimg_instance + "load_pfm(): SCALE field is undefined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + std::fgetc(nfile); + const bool is_color = (pfm_type=='F'), is_inverted = (scale>0)!=cimg::endianness(); + if (is_color) { + assign(W,H,1,3,(T)0); + CImg buf(3*W); + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + cimg_forY(*this,y) { + cimg::fread(buf._data,3*W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,3*W); + const float *ptrs = buf._data; + cimg_forX(*this,x) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + } else { + assign(W,H,1,1,(T)0); + CImg buf(W); + T *ptrd = data(0,0,0,0); + cimg_forY(*this,y) { + cimg::fread(buf._data,W,nfile); + if (is_inverted) cimg::invert_endianness(buf._data,W); + const float *ptrs = buf._data; + cimg_forX(*this,x) *(ptrd++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return mirror('y'); // Most of the .pfm files are flipped along the y-axis. + } + + //! Load image from a RGB file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(0,filename,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(filename,dimw,dimh); + } + + //! Load image from a RGB file \overloading. + CImg& load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgb(file,0,dimw,dimh); + } + + //! Load image from a RGB file \newinstance. + static CImg get_load_rgb(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgb(file,dimw,dimh); + } + + CImg& _load_rgb(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgb(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,3); + T + *ptr_r = data(0,0,0,0), + *ptr_g = data(0,0,0,1), + *ptr_b = data(0,0,0,2); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/3UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a RGBA file. + /** + \param filename Filename, as a C-string. + \param dimw Width of the image buffer. + \param dimh Height of the image buffer. + **/ + CImg& load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(0,filename,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(const char *const filename, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(filename,dimw,dimh); + } + + //! Load image from a RGBA file \overloading. + CImg& load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return _load_rgba(file,0,dimw,dimh); + } + + //! Load image from a RGBA file \newinstance. + static CImg get_load_rgba(std::FILE *const file, const unsigned int dimw, const unsigned int dimh=1) { + return CImg().load_rgba(file,dimw,dimh); + } + + CImg& _load_rgba(std::FILE *const file, const char *const filename, + const unsigned int dimw, const unsigned int dimh) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_rgba(): Specified filename is (null).", + cimg_instance); + + if (!dimw || !dimh) return assign(); + const longT cimg_iobuffer = (longT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg raw; + assign(dimw,dimh,1,4); + 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); + for (longT to_read = (longT)size(); to_read>0; ) { + raw.assign(std::min(to_read,cimg_iobuffer)); + cimg::fread(raw._data,raw._width,nfile); + to_read-=raw._width; + const unsigned char *ptrs = raw._data; + for (ulongT off = raw._width/4UL; off; --off) { + *(ptr_r++) = (T)*(ptrs++); + *(ptr_g++) = (T)*(ptrs++); + *(ptr_b++) = (T)*(ptrs++); + *(ptr_a++) = (T)*(ptrs++); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a TIFF file. + /** + \param filename Filename, as a C-string. + \param first_frame First frame to read (for multi-pages tiff). + \param last_frame Last frame to read (for multi-pages tiff). + \param step_frame Step value of frame reading. + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tif is not defined at compile time the + function uses CImg& load_other(const char*). + **/ + CImg& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + float *const voxel_size=0, + CImg *const description=0) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Specified filename is (null).", + cimg_instance); + + const unsigned int + nfirst_frame = first_frame1) + throw CImgArgumentException(_cimg_instance + "load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.", + cimg_instance, + filename); + return load_other(filename); +#else + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimg_instance + "load_tiff(): File '%s' contains %u image(s) while specified frame range is [%u,%u] (step %u).", + cimg_instance, + filename,nb_images,nfirst_frame,nlast_frame,nstep_frame); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + TIFFSetDirectory(tif,0); + CImg frame; + for (unsigned int l = nfirst_frame; l<=nlast_frame; l+=nstep_frame) { + frame._load_tiff(tif,l,voxel_size,description); + if (l==nfirst_frame) + assign(frame._width,frame._height,1 + (nlast_frame - nfirst_frame)/nstep_frame,frame._spectrum); + if (frame._width>_width || frame._height>_height || frame._spectrum>_spectrum) + resize(std::max(frame._width,_width), + std::max(frame._height,_height),-100, + std::max(frame._spectrum,_spectrum),0); + draw_image(0,0,(l - nfirst_frame)/nstep_frame,frame); + } + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "load_tiff(): Failed to open file '%s'.", + cimg_instance, + filename); + return *this; +#endif + } + + //! Load image from a TIFF file \newinstance. + static CImg get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + float *const voxel_size=0, + CImg *const description=0) { + return CImg().load_tiff(filename,first_frame,last_frame,step_frame,voxel_size,description); + } + + // (Original contribution by Jerome Boulanger). +#ifdef cimg_use_tiff + template + void _load_tiff_tiled_contig(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int row = 0; row + void _load_tiff_tiled_separate(TIFF *const tif, const uint16 samplesperpixel, + const uint32 nx, const uint32 ny, const uint32 tw, const uint32 th) { + t *const buf = (t*)_TIFFmalloc(TIFFTileSize(tif)); + if (buf) { + for (unsigned int vv = 0; vv + void _load_tiff_contig(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (row = 0; rowny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, 0); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0; rr + void _load_tiff_separate(TIFF *const tif, const uint16 samplesperpixel, const uint32 nx, const uint32 ny) { + t *buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + uint32 row, rowsperstrip = (uint32)-1; + TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rowsperstrip); + for (unsigned int vv = 0; vvny?ny - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif, row, vv); + if ((TIFFReadEncodedStrip(tif,strip,buf,-1))<0) { + _TIFFfree(buf); TIFFClose(tif); + throw CImgIOException(_cimg_instance + "load_tiff(): Invalid strip in file '%s'.", + cimg_instance, + TIFFFileName(tif)); + } + const t *ptr = buf; + for (unsigned int rr = 0;rr& _load_tiff(TIFF *const tif, const unsigned int directory, + float *const voxel_size, CImg *const description) { + if (!TIFFSetDirectory(tif,directory)) return assign(); + uint16 samplesperpixel = 1, bitspersample = 8, photo = 0; + uint16 sampleformat = 1; + uint32 nx = 1, ny = 1; + const char *const filename = TIFFFileName(tif); + const bool is_spp = (bool)TIFFGetField(tif,TIFFTAG_SAMPLESPERPIXEL,&samplesperpixel); + TIFFGetField(tif,TIFFTAG_IMAGEWIDTH,&nx); + TIFFGetField(tif,TIFFTAG_IMAGELENGTH,&ny); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &sampleformat); + TIFFGetFieldDefaulted(tif,TIFFTAG_BITSPERSAMPLE,&bitspersample); + TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photo); + if (voxel_size) { + const char *s_description = 0; + float vx = 0, vy = 0, vz = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) { + const char *s_desc = std::strstr(s_description,"VX="); + if (s_desc && cimg_sscanf(s_desc,"VX=%f VY=%f VZ=%f",&vx,&vy,&vz)==3) { // CImg format. + voxel_size[0] = vx; voxel_size[1] = vy; voxel_size[2] = vz; + } + s_desc = std::strstr(s_description,"spacing="); + if (s_desc && cimg_sscanf(s_desc,"spacing=%f",&vz)==1) { // fiji format. + voxel_size[2] = vz; + } + } + TIFFGetField(tif,TIFFTAG_XRESOLUTION,voxel_size); + TIFFGetField(tif,TIFFTAG_YRESOLUTION,voxel_size + 1); + voxel_size[0] = 1.0f/voxel_size[0]; + voxel_size[1] = 1.0f/voxel_size[1]; + } + if (description) { + const char *s_description = 0; + if (TIFFGetField(tif,TIFFTAG_IMAGEDESCRIPTION,&s_description) && s_description) + CImg::string(s_description).move_to(*description); + } + const unsigned int spectrum = !is_spp || photo>=3?(photo>1?3:1):samplesperpixel; + assign(nx,ny,1,spectrum); + + if ((photo>=3 && sampleformat==1 && + (bitspersample==4 || bitspersample==8) && + (samplesperpixel==1 || samplesperpixel==3 || samplesperpixel==4)) || + (bitspersample==1 && samplesperpixel==1)) { + // Special case for unsigned color images. + uint32 *const raster = (uint32*)_TIFFmalloc(nx*ny*sizeof(uint32)); + if (!raster) { + _TIFFfree(raster); TIFFClose(tif); + throw CImgException(_cimg_instance + "load_tiff(): Failed to allocate memory (%s) for file '%s'.", + cimg_instance, + cimg::strbuffersize(nx*ny*sizeof(uint32)),filename); + } + TIFFReadRGBAImage(tif,nx,ny,raster,0); + switch (spectrum) { + case 1 : + cimg_forXY(*this,x,y) + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]); + break; + case 3 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 -y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 -y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 -y) + x]); + } + break; + case 4 : + cimg_forXY(*this,x,y) { + (*this)(x,y,0) = (T)(float)TIFFGetR(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,1) = (T)(float)TIFFGetG(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,2) = (T)(float)TIFFGetB(raster[nx*(ny - 1 - y) + x]); + (*this)(x,y,3) = (T)(float)TIFFGetA(raster[nx*(ny - 1 - y) + x]); + } + break; + } + _TIFFfree(raster); + } else { // Other cases. + uint16 config; + TIFFGetField(tif,TIFFTAG_PLANARCONFIG,&config); + if (TIFFIsTiled(tif)) { + uint32 tw = 1, th = 1; + TIFFGetField(tif,TIFFTAG_TILEWIDTH,&tw); + TIFFGetField(tif,TIFFTAG_TILELENGTH,&th); + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : { + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + } break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_contig(tif,samplesperpixel,nx,ny,tw,th); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else if (sampleformat==SAMPLEFORMAT_INT) + _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + else _load_tiff_tiled_separate(tif,samplesperpixel,nx,ny,tw,th); + break; + } + } else { + if (config==PLANARCONFIG_CONTIG) switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) + _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_contig(tif,samplesperpixel,nx,ny); + else _load_tiff_contig(tif,samplesperpixel,nx,ny); + break; + } else switch (bitspersample) { + case 8 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 16 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + case 32 : + if (sampleformat==SAMPLEFORMAT_UINT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else if (sampleformat==SAMPLEFORMAT_INT) _load_tiff_separate(tif,samplesperpixel,nx,ny); + else _load_tiff_separate(tif,samplesperpixel,nx,ny); + break; + } + } + } + return *this; + } +#endif + + //! Load image from a MINC2 file. + /** + \param filename Filename, as a C-string. + **/ + // (Original code by Haz-Edine Assemlal). + CImg& load_minc2(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_minc2(): Specified filename is (null).", + cimg_instance); +#ifndef cimg_use_minc2 + return load_other(filename); +#else + minc::minc_1_reader rdr; + rdr.open(filename); + assign(rdr.ndim(1)?rdr.ndim(1):1, + rdr.ndim(2)?rdr.ndim(2):1, + rdr.ndim(3)?rdr.ndim(3):1, + rdr.ndim(4)?rdr.ndim(4):1); + if(typeid(T)==typeid(unsigned char)) + rdr.setup_read_byte(); + else if(typeid(T)==typeid(int)) + rdr.setup_read_int(); + else if(typeid(T)==typeid(double)) + rdr.setup_read_double(); + else + rdr.setup_read_float(); + minc::load_standard_volume(rdr, this->_data); + return *this; +#endif + } + + //! Load image from a MINC2 file \newinstance. + static CImg get_load_minc2(const char *const filename) { + return CImg().load_analyze(filename); + } + + //! Load image from an ANALYZE7.5/NIFTI file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_analyze(const char *const filename, float *const voxel_size=0) { + return _load_analyze(0,filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(const char *const filename, float *const voxel_size=0) { + return CImg().load_analyze(filename,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \overloading. + CImg& load_analyze(std::FILE *const file, float *const voxel_size=0) { + return _load_analyze(file,0,voxel_size); + } + + //! Load image from an ANALYZE7.5/NIFTI file \newinstance. + static CImg get_load_analyze(std::FILE *const file, float *const voxel_size=0) { + return CImg().load_analyze(file,voxel_size); + } + + CImg& _load_analyze(std::FILE *const file, const char *const filename, float *const voxel_size=0) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_analyze(): Specified filename is (null).", + cimg_instance); + + std::FILE *nfile_header = 0, *nfile = 0; + if (!file) { + CImg body(1024); + const char *const ext = cimg::split_filename(filename,body); + if (!cimg::strcasecmp(ext,"hdr")) { // File is an Analyze header file. + nfile_header = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".img"); + nfile = cimg::fopen(body,"rb"); + } else if (!cimg::strcasecmp(ext,"img")) { // File is an Analyze data file. + nfile = cimg::fopen(filename,"rb"); + cimg_sprintf(body._data + std::strlen(body),".hdr"); + nfile_header = cimg::fopen(body,"rb"); + } else nfile_header = nfile = cimg::fopen(filename,"rb"); // File is a Niftii file. + } else nfile_header = nfile = file; // File is a Niftii file. + if (!nfile || !nfile_header) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid Analyze7.5 or NIFTI header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + // Read header. + bool endian = false; + unsigned int header_size; + cimg::fread(&header_size,1,nfile_header); + if (!header_size) + throw CImgIOException(_cimg_instance + "load_analyze(): Invalid zero-size header in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (header_size>=4096) { endian = true; cimg::invert_endianness(header_size); } + + unsigned char *const header = new unsigned char[header_size]; + cimg::fread(header + 4,header_size - 4,nfile_header); + if (!file && nfile_header!=nfile) cimg::fclose(nfile_header); + if (endian) { + cimg::invert_endianness((short*)(header + 40),5); + cimg::invert_endianness((short*)(header + 70),1); + cimg::invert_endianness((short*)(header + 72),1); + cimg::invert_endianness((float*)(header + 76),4); + cimg::invert_endianness((float*)(header + 108),1); + cimg::invert_endianness((float*)(header + 112),1); + } + + if (nfile_header==nfile) { + const unsigned int vox_offset = (unsigned int)*(float*)(header + 108); + std::fseek(nfile,vox_offset,SEEK_SET); + } + + unsigned short *dim = (unsigned short*)(header + 40), dimx = 1, dimy = 1, dimz = 1, dimv = 1; + if (!dim[0]) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with zero dimensions.", + cimg_instance, + filename?filename:"(FILE*)"); + + if (dim[0]>4) + cimg::warn(_cimg_instance + "load_analyze(): File '%s' defines an image with %u dimensions, reading only the 4 first.", + cimg_instance, + filename?filename:"(FILE*)",dim[0]); + + if (dim[0]>=1) dimx = dim[1]; + if (dim[0]>=2) dimy = dim[2]; + if (dim[0]>=3) dimz = dim[3]; + if (dim[0]>=4) dimv = dim[4]; + float scalefactor = *(float*)(header + 112); if (scalefactor==0) scalefactor = 1; + const unsigned short datatype = *(unsigned short*)(header + 70); + if (voxel_size) { + const float *vsize = (float*)(header + 76); + voxel_size[0] = vsize[1]; voxel_size[1] = vsize[2]; voxel_size[2] = vsize[3]; + } + delete[] header; + + // Read pixel data. + assign(dimx,dimy,dimz,dimv); + const size_t pdim = (size_t)dimx*dimy*dimz*dimv; + switch (datatype) { + case 2 : { + unsigned char *const buffer = new unsigned char[pdim]; + cimg::fread(buffer,pdim,nfile); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 4 : { + short *const buffer = new short[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 8 : { + int *const buffer = new int[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 16 : { + float *const buffer = new float[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + case 64 : { + double *const buffer = new double[pdim]; + cimg::fread(buffer,pdim,nfile); + if (endian) cimg::invert_endianness(buffer,pdim); + cimg_foroff(*this,off) _data[off] = (T)(buffer[off]*scalefactor); + delete[] buffer; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_analyze(): Unable to load datatype %d in file '%s'", + cimg_instance, + datatype,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a .cimg[z] file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(const char *const filename, const char axis='z', const float align=0) { + return CImg().load_cimg(filename,axis,align); + } + + //! Load image from a .cimg[z] file \overloading. + CImg& load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a .cimg[z] file \newinstance + static CImg get_load_cimg(std::FILE *const file, const char axis='z', const float align=0) { + return CImg().load_cimg(file,axis,align); + } + + //! Load sub-images of a .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Starting frame. + \param n1 Ending frame (~0U for max). + \param x0 X-coordinate of the starting sub-image vertex. + \param y0 Y-coordinate of the starting sub-image vertex. + \param z0 Z-coordinate of the starting sub-image vertex. + \param c0 C-coordinate of the starting sub-image vertex. + \param x1 X-coordinate of the ending sub-image vertex (~0U for max). + \param y1 Y-coordinate of the ending sub-image vertex (~0U for max). + \param z1 Z-coordinate of the ending sub-image vertex (~0U for max). + \param c1 C-coordinate of the ending sub-image vertex (~0U for max). + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load sub-images of a .cimg file \overloading. + CImg& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + CImgList list; + list.load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load sub-images of a .cimg file \newinstance. + static CImg get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1, + const char axis='z', const float align=0) { + return CImg().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1,axis,align); + } + + //! Load image from an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param[out] voxel_size Pointer to the three voxel sizes read from the file. + **/ + CImg& load_inr(const char *const filename, float *const voxel_size=0) { + return _load_inr(0,filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(const char *const filename, float *const voxel_size=0) { + return CImg().load_inr(filename,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \overloading. + CImg& load_inr(std::FILE *const file, float *const voxel_size=0) { + return _load_inr(file,0,voxel_size); + } + + //! Load image from an INRIMAGE-4 file \newinstance. + static CImg get_load_inr(std::FILE *const file, float *voxel_size=0) { + return CImg().load_inr(file,voxel_size); + } + + static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) { + CImg item(1024), tmp1(64), tmp2(64); + *item = *tmp1 = *tmp2 = 0; + out[0] = std::fscanf(file,"%63s",item._data); + out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1; + if(cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0) + throw CImgIOException("CImg<%s>::load_inr(): INRIMAGE-4 header not found.", + pixel_type()); + + while (std::fscanf(file," %63[^\n]%*c",item._data)!=EOF && std::strncmp(item,"##}",3)) { + cimg_sscanf(item," XDIM%*[^0-9]%d",out); + cimg_sscanf(item," YDIM%*[^0-9]%d",out + 1); + cimg_sscanf(item," ZDIM%*[^0-9]%d",out + 2); + cimg_sscanf(item," VDIM%*[^0-9]%d",out + 3); + cimg_sscanf(item," PIXSIZE%*[^0-9]%d",out + 6); + if (voxel_size) { + cimg_sscanf(item," VX%*[^0-9.+-]%f",voxel_size); + cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1); + cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2); + } + if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1; + switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) { + case 0 : break; + case 2 : out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; std::strncpy(tmp1,tmp2,tmp1._width - 1); + case 1 : + if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5)) out[4] = 0; + if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4] = 1; + if (!cimg::strncasecmp(tmp1,"packed",6)) out[4] = 2; + if (out[4]>=0) break; + default : + throw CImgIOException("CImg<%s>::load_inr(): Invalid pixel type '%s' defined in header.", + pixel_type(), + tmp2._data); + } + } + if(out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0) + throw CImgIOException("CImg<%s>::load_inr(): Invalid dimensions (%d,%d,%d,%d) defined in header.", + pixel_type(), + out[0],out[1],out[2],out[3]); + if(out[4]<0 || out[5]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete pixel type defined in header.", + pixel_type()); + if(out[6]<0) + throw CImgIOException("CImg<%s>::load_inr(): Incomplete PIXSIZE field defined in header.", + pixel_type()); + if(out[7]<0) + throw CImgIOException("CImg<%s>::load_inr(): Big/Little Endian coding type undefined in header.", + pixel_type()); + } + + CImg& _load_inr(std::FILE *const file, const char *const filename, float *const voxel_size) { +#define _cimg_load_inr_case(Tf,sign,pixsize,Ts) \ + if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \ + Ts *xval, *const val = new Ts[(size_t)fopt[0]*fopt[3]]; \ + cimg_forYZ(*this,y,z) { \ + cimg::fread(val,fopt[0]*fopt[3],nfile); \ + if (fopt[7]!=endian) cimg::invert_endianness(val,fopt[0]*fopt[3]); \ + xval = val; cimg_forX(*this,x) cimg_forC(*this,c) (*this)(x,y,z,c) = (T)*(xval++); \ + } \ + delete[] val; \ + loaded = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_inr(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + int fopt[8], endian = cimg::endianness()?1:0; + bool loaded = false; + if (voxel_size) voxel_size[0] = voxel_size[1] = voxel_size[2] = 1; + _load_inr_header(nfile,fopt,voxel_size); + assign(fopt[0],fopt[1],fopt[2],fopt[3]); + _cimg_load_inr_case(0,0,8,unsigned char); + _cimg_load_inr_case(0,1,8,char); + _cimg_load_inr_case(0,0,16,unsigned short); + _cimg_load_inr_case(0,1,16,short); + _cimg_load_inr_case(0,0,32,unsigned int); + _cimg_load_inr_case(0,1,32,int); + _cimg_load_inr_case(1,0,32,float); + _cimg_load_inr_case(1,1,32,float); + _cimg_load_inr_case(1,0,64,double); + _cimg_load_inr_case(1,1,64,double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_inr(): Unknown pixel type defined in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a EXR file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_exr(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_exr(): Specified filename is (null).", + cimg_instance); +#if defined(cimg_use_openexr) + Imf::RgbaInputFile file(filename); + Imath::Box2i dw = file.dataWindow(); + const int + inwidth = dw.max.x - dw.min.x + 1, + inheight = dw.max.y - dw.min.y + 1; + Imf::Array2D pixels; + pixels.resizeErase(inheight,inwidth); + file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y*inwidth, 1, inwidth); + file.readPixels(dw.min.y, dw.max.y); + assign(inwidth,inheight,1,4); + 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); + cimg_forXY(*this,x,y) { + *(ptr_r++) = (T)pixels[y][x].r; + *(ptr_g++) = (T)pixels[y][x].g; + *(ptr_b++) = (T)pixels[y][x].b; + *(ptr_a++) = (T)pixels[y][x].a; + } +#elif defined(cimg_use_tinexr) + float *res; + const char *err = 0; + int width = 0, height = 0; + const int ret = LoadEXR(&res,&width,&height,filename,&err); + if (ret) throw CImgIOException(_cimg_instance + "load_exr(): Unable to load EXR file '%s'.", + cimg_instance,filename); + CImg(out,4,width,height,1,true).get_permute_axes("yzcx").move_to(*this); + std::free(res); +#else + return load_other(filename); +#endif + return *this; + } + + //! Load image from a EXR file \newinstance. + static CImg get_load_exr(const char *const filename) { + return CImg().load_exr(filename); + } + + //! Load image from a PANDORE-5 file. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_pandore(const char *const filename) { + return _load_pandore(0,filename); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(const char *const filename) { + return CImg().load_pandore(filename); + } + + //! Load image from a PANDORE-5 file \overloading. + CImg& load_pandore(std::FILE *const file) { + return _load_pandore(file,0); + } + + //! Load image from a PANDORE-5 file \newinstance. + static CImg get_load_pandore(std::FILE *const file) { + return CImg().load_pandore(file); + } + + CImg& _load_pandore(std::FILE *const file, const char *const filename) { +#define __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,ndim,stype) \ + cimg::fread(dims,nbdim,nfile); \ + if (endian) cimg::invert_endianness(dims,nbdim); \ + assign(nwidth,nheight,ndepth,ndim); \ + const size_t siz = size(); \ + stype *buffer = new stype[siz]; \ + cimg::fread(buffer,siz,nfile); \ + if (endian) cimg::invert_endianness(buffer,siz); \ + T *ptrd = _data; \ + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); \ + buffer-=siz; \ + delete[] buffer + +#define _cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1,stype2,stype3,ltype) { \ + if (sizeof(stype1)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype1); } \ + else if (sizeof(stype2)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype2); } \ + else if (sizeof(stype3)==ltype) { __cimg_load_pandore_case(nbdim,nwidth,nheight,ndepth,dim,stype3); } \ + else throw CImgIOException(_cimg_instance \ + "load_pandore(): Unknown pixel datatype in file '%s'.", \ + cimg_instance, \ + filename?filename:"(FILE*)"); } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_pandore(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + CImg header(32); + cimg::fread(header._data,12,nfile); + if (cimg::strncasecmp("PANDORE",header,7)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): PANDORE header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + unsigned int imageid, dims[8] = { 0 }; + int ptbuf[4] = { 0 }; + cimg::fread(&imageid,1,nfile); + const bool endian = imageid>255; + if (endian) cimg::invert_endianness(imageid); + cimg::fread(header._data,20,nfile); + + switch (imageid) { + case 2 : _cimg_load_pandore_case(2,dims[1],1,1,1,unsigned char,unsigned char,unsigned char,1); break; + case 3 : _cimg_load_pandore_case(2,dims[1],1,1,1,long,int,short,4); break; + case 4 : _cimg_load_pandore_case(2,dims[1],1,1,1,double,float,float,4); break; + case 5 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,unsigned char,unsigned char,unsigned char,1); break; + case 6 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,long,int,short,4); break; + case 7 : _cimg_load_pandore_case(3,dims[2],dims[1],1,1,double,float,float,4); break; + case 8 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,unsigned char,unsigned char,unsigned char,1); break; + case 9 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,long,int,short,4); break; + case 10 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],1,double,float,float,4); break; + case 11 : { // Region 1d + cimg::fread(dims,3,nfile); + if (endian) cimg::invert_endianness(dims,3); + assign(dims[1],1,1,1); + const unsigned siz = size(); + if (dims[2]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[2]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 12 : { // Region 2d + cimg::fread(dims,4,nfile); + if (endian) cimg::invert_endianness(dims,4); + assign(dims[2],dims[1],1,1); + const size_t siz = size(); + if (dims[3]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[3]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 13 : { // Region 3d + cimg::fread(dims,5,nfile); + if (endian) cimg::invert_endianness(dims,5); + assign(dims[3],dims[2],dims[1],1); + const size_t siz = size(); + if (dims[4]<256) { + unsigned char *buffer = new unsigned char[siz]; + cimg::fread(buffer,siz,nfile); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + if (dims[4]<65536) { + unsigned short *buffer = new unsigned short[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } else { + unsigned int *buffer = new unsigned int[siz]; + cimg::fread(buffer,siz,nfile); + if (endian) cimg::invert_endianness(buffer,siz); + T *ptrd = _data; + cimg_foroff(*this,off) *(ptrd++) = (T)*(buffer++); + buffer-=siz; + delete[] buffer; + } + } + } + break; + case 16 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,unsigned char,unsigned char,unsigned char,1); break; + case 17 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,long,int,short,4); break; + case 18 : _cimg_load_pandore_case(4,dims[2],dims[1],1,3,double,float,float,4); break; + case 19 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,unsigned char,unsigned char,unsigned char,1); break; + case 20 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,long,int,short,4); break; + case 21 : _cimg_load_pandore_case(5,dims[3],dims[2],dims[1],3,double,float,float,4); break; + case 22 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 23 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],long,int,short,4); + case 24 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 25 : _cimg_load_pandore_case(2,dims[1],1,1,dims[0],double,float,float,4); break; + case 26 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned char,unsigned char,unsigned char,1); break; + case 27 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],long,int,short,4); break; + case 28 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],unsigned long,unsigned int,unsigned short,4); break; + case 29 : _cimg_load_pandore_case(3,dims[2],dims[1],1,dims[0],double,float,float,4); break; + case 30 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned char,unsigned char,unsigned char,1); + break; + case 31 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],long,int,short,4); break; + case 32 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],unsigned long,unsigned int,unsigned short,4); + break; + case 33 : _cimg_load_pandore_case(4,dims[3],dims[2],dims[1],dims[0],double,float,float,4); break; + case 34 : { // Points 1d + cimg::fread(ptbuf,1,nfile); + if (endian) cimg::invert_endianness(ptbuf,1); + assign(1); (*this)(0) = (T)ptbuf[0]; + } break; + case 35 : { // Points 2d + cimg::fread(ptbuf,2,nfile); + if (endian) cimg::invert_endianness(ptbuf,2); + assign(2); (*this)(0) = (T)ptbuf[1]; (*this)(1) = (T)ptbuf[0]; + } break; + case 36 : { // Points 3d + cimg::fread(ptbuf,3,nfile); + if (endian) cimg::invert_endianness(ptbuf,3); + assign(3); (*this)(0) = (T)ptbuf[2]; (*this)(1) = (T)ptbuf[1]; (*this)(2) = (T)ptbuf[0]; + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_pandore(): Unable to load data with ID_type %u in file '%s'.", + cimg_instance, + imageid,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image from a PAR-REC (Philips) file. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_parrec(const char *const filename, const char axis='c', const float align=0) { + CImgList list; + list.load_parrec(filename); + if (list._width==1) return list[0].move_to(*this); + return assign(list.get_append(axis,align)); + } + + //! Load image from a PAR-REC (Philips) file \newinstance. + static CImg get_load_parrec(const char *const filename, const char axis='c', const float align=0) { + return CImg().load_parrec(filename,axis,align); + } + + //! Load image from a raw binary file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the image buffer. + \param size_y Height of the image buffer. + \param size_z Depth of the image buffer. + \param size_c Spectrum of the image buffer. + \param is_multiplexed Tells if the image values are multiplexed along the C-axis. + \param invert_endianness Tells if the endianness of the image buffer must be inverted. + \param offset Starting offset of the read in the specified file. + **/ + CImg& load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(0,filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(const char *const filename, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(filename,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \overloading. + CImg& load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return _load_raw(file,0,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + //! Load image from a raw binary file \newinstance. + static CImg get_load_raw(std::FILE *const file, + const unsigned int size_x=0, const unsigned int size_y=1, + const unsigned int size_z=1, const unsigned int size_c=1, + const bool is_multiplexed=false, const bool invert_endianness=false, + const ulongT offset=0) { + return CImg().load_raw(file,size_x,size_y,size_z,size_c,is_multiplexed,invert_endianness,offset); + } + + CImg& _load_raw(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int size_z, const unsigned int size_c, + const bool is_multiplexed, const bool invert_endianness, + const ulongT offset) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename is (null).", + cimg_instance); + if (cimg::is_directory(filename)) + throw CImgArgumentException(_cimg_instance + "load_raw(): Specified filename '%s' is a directory.", + cimg_instance,filename); + + ulongT siz = (ulongT)size_x*size_y*size_z*size_c; + unsigned int + _size_x = size_x, + _size_y = size_y, + _size_z = size_z, + _size_c = size_c; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + if (!siz) { // Retrieve file size. + const longT fpos = cimg::ftell(nfile); + if (fpos<0) throw CImgArgumentException(_cimg_instance + "load_raw(): Cannot determine size of input file '%s'.", + cimg_instance,filename?filename:"(FILE*)"); + cimg::fseek(nfile,0,SEEK_END); + siz = cimg::ftell(nfile)/sizeof(T); + _size_y = (unsigned int)siz; + _size_x = _size_z = _size_c = 1; + cimg::fseek(nfile,fpos,SEEK_SET); + } + cimg::fseek(nfile,offset,SEEK_SET); + assign(_size_x,_size_y,_size_z,_size_c,0); + if (siz && (!is_multiplexed || size_c==1)) { + cimg::fread(_data,siz,nfile); + if (invert_endianness) cimg::invert_endianness(_data,siz); + } else if (siz) { + CImg buf(1,1,1,_size_c); + cimg_forXYZ(*this,x,y,z) { + cimg::fread(buf._data,_size_c,nfile); + if (invert_endianness) cimg::invert_endianness(buf._data,_size_c); + set_vector_at(buf,x,y,z); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load image sequence from a YUV file. + /** + \param filename Filename, as a C-string. + \param size_x Width of the frames. + \param size_y Height of the frames. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \param yuv2rgb Tells if the YUV to RGB transform must be applied. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + **/ + CImg& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load image sequence from a YUV file \overloading. + CImg& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return get_load_yuv(file,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb,axis).move_to(*this); + } + + //! Load image sequence from a YUV file \newinstance. + static CImg get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true, const char axis='z') { + return CImgList().load_yuv(file,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb).get_append(axis); + } + + //! Load 3d object from a .OFF file. + /** + \param[out] primitives Primitives data of the 3d object. + \param[out] colors Colors data of the 3d object. + \param filename Filename, as a C-string. + **/ + template + CImg& load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return _load_off(primitives,colors,0,filename); + } + + //! Load 3d object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, const char *const filename) { + return CImg().load_off(primitives,colors,filename); + } + + //! Load 3d object from a .OFF file \overloading. + template + CImg& load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return _load_off(primitives,colors,file,0); + } + + //! Load 3d object from a .OFF file \newinstance. + template + static CImg get_load_off(CImgList& primitives, CImgList& colors, std::FILE *const file) { + return CImg().load_off(primitives,colors,file); + } + + template + CImg& _load_off(CImgList& primitives, CImgList& colors, + std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "load_off(): Specified filename is (null).", + cimg_instance); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"r"); + unsigned int nb_points = 0, nb_primitives = 0, nb_read = 0; + CImg line(256); *line = 0; + int err; + + // Skip comments, and read magic string OFF + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if (cimg::strncasecmp(line,"OFF",3) && cimg::strncasecmp(line,"COFF",4)) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): OFF header not found in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%u%u%*[^\n] ",&nb_points,&nb_primitives))!=2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Invalid number of vertices or primitives specified in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + } + + // Read points data + assign(nb_points,3); + float X = 0, Y = 0, Z = 0; + cimg_forX(*this,l) { + do { err = std::fscanf(nfile,"%255[^\n] ",line._data); } while (!err || (err==1 && *line=='#')); + if ((err = cimg_sscanf(line,"%f%f%f%*[^\n] ",&X,&Y,&Z))!=3) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "load_off(): Failed to read vertex %u/%u in file '%s'.", + cimg_instance, + l + 1,nb_points,filename?filename:"(FILE*)"); + } + (*this)(l,0) = (T)X; (*this)(l,1) = (T)Y; (*this)(l,2) = (T)Z; + } + + // Read primitive data + primitives.assign(); + colors.assign(); + bool stop_flag = false; + while (!stop_flag) { + float c0 = 0.7f, c1 = 0.7f, c2 = 0.7f; + unsigned int prim = 0, i0 = 0, i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, i7 = 0; + *line = 0; + if ((err = std::fscanf(nfile,"%u",&prim))!=1) stop_flag = true; + else { + ++nb_read; + switch (prim) { + case 1 : { + if ((err = std::fscanf(nfile,"%u%255[^\n] ",&i0,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 2 : { + if ((err = std::fscanf(nfile,"%u%u%255[^\n] ",&i0,&i1,line._data))<2) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 3 : { + if ((err = std::fscanf(nfile,"%u%u%u%255[^\n] ",&i0,&i1,&i2,line._data))<3) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 4 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,line._data))<4) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)).move_to(colors); + } + } break; + case 5 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,line._data))<5) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 6 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,line._data))<6) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + colors.insert(2,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++nb_primitives; + } + } break; + case 7 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i4,i3,i1).move_to(primitives); + CImg::vector(i0,i6,i5,i4).move_to(primitives); + CImg::vector(i3,i2,i1).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + case 8 : { + if ((err = std::fscanf(nfile,"%u%u%u%u%u%u%u%u%255[^\n] ",&i0,&i1,&i2,&i3,&i4,&i5,&i6,&i7,line._data))<7) { + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u from file '%s'.", + cimg_instance, + nb_read,nb_primitives,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } else { + err = cimg_sscanf(line,"%f%f%f",&c0,&c1,&c2); + CImg::vector(i0,i3,i2,i1).move_to(primitives); + CImg::vector(i0,i5,i4,i3).move_to(primitives); + CImg::vector(i0,i7,i6,i5).move_to(primitives); + colors.insert(3,CImg::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255))); + ++(++nb_primitives); + } + } break; + default : + cimg::warn(_cimg_instance + "load_off(): Failed to read primitive %u/%u (%u vertices) from file '%s'.", + cimg_instance, + nb_read,nb_primitives,prim,filename?filename:"(FILE*)"); + + err = std::fscanf(nfile,"%*[^\n] "); + } + } + } + if (!file) cimg::fclose(nfile); + if (primitives._width!=nb_primitives) + cimg::warn(_cimg_instance + "load_off(): Only %u/%u primitives read from file '%s'.", + cimg_instance, + primitives._width,nb_primitives,filename?filename:"(FILE*)"); + return *this; + } + + //! Load image sequence from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + **/ + CImg& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return get_load_video(filename,first_frame,last_frame,step_frame,axis,align).move_to(*this); + } + + //! Load image sequence from a video file, using OpenCV library \newinstance. + static CImg get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + const char axis='z', const float align=0) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame).get_append(axis,align); + } + + //! Load image sequence using FFMPEG's external tool 'ffmpeg'. + /** + \param filename Filename, as a C-string. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_ffmpeg_external(const char *const filename, const char axis='z', const float align=0) { + return get_load_ffmpeg_external(filename,axis,align).move_to(*this); + } + + //! Load image sequence using FFMPEG's external tool 'ffmpeg' \newinstance. + static CImg get_load_ffmpeg_external(const char *const filename, const char axis='z', const float align=0) { + return CImgList().load_ffmpeg_external(filename).get_append(axis,align); + } + + //! Load gif file, using Imagemagick or GraphicsMagicks's external tools. + /** + \param filename Filename, as a C-string. + \param use_graphicsmagick Tells if GraphicsMagick's tool 'gm' is used instead of ImageMagick's tool 'convert'. + \param axis Appending axis, if file contains multiple images. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg& load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return get_load_gif_external(filename,axis,align).move_to(*this); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tool 'convert' \newinstance. + static CImg get_load_gif_external(const char *const filename, + const char axis='z', const float align=0) { + return CImgList().load_gif_external(filename).get_append(axis,align); + } + + //! Load image using GraphicsMagick's external tool 'gm'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_graphicsmagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"%s convert \"%s\" pnm:-", + cimg::graphicsmagick_path(),s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.pnm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"%s convert \"%s\" \"%s\"", + cimg::graphicsmagick_path(),s_filename.data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::graphicsmagick_path()); + if (!(file = std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_graphicsmagick_external(): Failed to load file '%s' with external command 'gm'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image using GraphicsMagick's external tool 'gm' \newinstance. + static CImg get_load_graphicsmagick_external(const char *const filename) { + return CImg().load_graphicsmagick_external(filename); + } + + //! Load gzipped image file, using external tool 'gunzip'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimg_instance + "load_gzip_external(): Specified filename is (null).", + cimg_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256), body(256); + const char + *const ext = cimg::split_filename(filename,body), + *const ext2 = cimg::split_filename(body,0); + + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"%s -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command); + if (!(file = std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_gzip_external(): Failed to load file '%s' with external command 'gunzip'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load gzipped image file, using external tool 'gunzip' \newinstance. + static CImg get_load_gzip_external(const char *const filename) { + return CImg().load_gzip_external(filename); + } + + //! Load image using ImageMagick's external tool 'convert'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_imagemagick_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_imagemagick_external(): Specified filename is (null).", + cimg_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"%s%s \"%s\" pnm:-", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with " + "external command 'convert'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.pnm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"%s%s \"%s\" \"%s\"", + cimg::imagemagick_path(), + !cimg::strcasecmp(cimg::split_filename(filename),"pdf")?" -density 400x400":"", + s_filename.data(),CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::imagemagick_path()); + if (!(file = std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_imagemagick_external(): Failed to load file '%s' with external command 'convert'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image using ImageMagick's external tool 'convert' \newinstance. + static CImg get_load_imagemagick_external(const char *const filename) { + return CImg().load_imagemagick_external(filename); + } + + //! Load image from a DICOM file, using XMedcon's external tool 'medcon'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_medcon_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_medcon_external(): Specified filename is (null).", + cimg_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256), body(256); + cimg::fclose(cimg::fopen(filename,"r")); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"%s -w -c anlz -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command); + cimg::split_filename(filename_tmp,body); + + cimg_snprintf(command,command._width,"%s.hdr",body._data); + file = std_fopen(command,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s.hdr",body._data); + file = std_fopen(command,"rb"); + if (!file) { + throw CImgIOException(_cimg_instance + "load_medcon_external(): Failed to load file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + load_analyze(command); + std::remove(command); + cimg::split_filename(command,body); + cimg_snprintf(command,command._width,"%s.img",body._data); + std::remove(command); + return *this; + } + + //! Load image from a DICOM file, using XMedcon's external tool 'medcon' \newinstance. + static CImg get_load_medcon_external(const char *const filename) { + return CImg().load_medcon_external(filename); + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw'. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_dcraw_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_dcraw_external(): Specified filename is (null).", + cimg_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256); + std::FILE *file = 0; + const CImg s_filename = CImg::string(filename)._system_strescape(); +#if cimg_OS==1 + cimg_snprintf(command,command._width,"%s -w -4 -c \"%s\"", + cimg::dcraw_path(),s_filename.data()); + file = popen(command,"r"); + if (file) { + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_pnm(file); } catch (...) { + pclose(file); + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + } + pclose(file); + return *this; + } +#endif + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.ppm", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"%s -w -4 -c \"%s\" > \"%s\"", + cimg::dcraw_path(),s_filename.data(),CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command,cimg::dcraw_path()); + if (!(file = std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "load_dcraw_external(): Failed to load file '%s' with external command 'dcraw'.", + cimg_instance, + filename); + + } else cimg::fclose(file); + load_pnm(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load image from a RAW Color Camera file, using external tool 'dcraw' \newinstance. + static CImg get_load_dcraw_external(const char *const filename) { + return CImg().load_dcraw_external(filename); + } + + //! Load image from a camera stream, using OpenCV. + /** + \param camera_index Index of the camera to capture images from. + \param skip_frames Number of frames to skip before the capture. + \param release_camera Tells if the camera ressource must be released at the end of the method. + **/ + CImg& load_camera(const unsigned int camera_index=0, const unsigned int skip_frames=0, + const bool release_camera=true, const unsigned int capture_width=0, + const unsigned int capture_height=0) { +#ifdef cimg_use_opencv + if (camera_index>99) + throw CImgArgumentException(_cimg_instance + "load_camera(): Invalid request for camera #%u " + "(no more than 100 cameras can be managed simultaneously).", + cimg_instance, + camera_index); + static CvCapture *capture[100] = { 0 }; + static unsigned int capture_w[100], capture_h[100]; + if (release_camera) { + cimg::mutex(9); + if (capture[camera_index]) cvReleaseCapture(&(capture[camera_index])); + capture[camera_index] = 0; + capture_w[camera_index] = capture_h[camera_index] = 0; + cimg::mutex(9,0); + return *this; + } + if (!capture[camera_index]) { + cimg::mutex(9); + capture[camera_index] = cvCreateCameraCapture(camera_index); + capture_w[camera_index] = 0; + capture_h[camera_index] = 0; + cimg::mutex(9,0); + if (!capture[camera_index]) { + throw CImgIOException(_cimg_instance + "load_camera(): Failed to initialize camera #%u.", + cimg_instance, + camera_index); + } + } + cimg::mutex(9); + if (capture_width!=capture_w[camera_index]) { + cvSetCaptureProperty(capture[camera_index],CV_CAP_PROP_FRAME_WIDTH,capture_width); + capture_w[camera_index] = capture_width; + } + if (capture_height!=capture_h[camera_index]) { + cvSetCaptureProperty(capture[camera_index],CV_CAP_PROP_FRAME_HEIGHT,capture_height); + capture_h[camera_index] = capture_height; + } + const IplImage *img = 0; + for (unsigned int i = 0; iwidthStep - 3*img->width); + assign(img->width,img->height,1,3); + const unsigned char* ptrs = (unsigned char*)img->imageData; + T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2); + if (step>0) cimg_forY(*this,y) { + cimg_forX(*this,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); } + ptrs+=step; + } else for (ulongT siz = (ulongT)img->width*img->height; siz; --siz) { + *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); + } + } + cimg::mutex(9,0); + return *this; +#else + cimg::unused(camera_index,skip_frames,release_camera,capture_width,capture_height); + throw CImgIOException(_cimg_instance + "load_camera(): This function requires the OpenCV library to run " + "(macro 'cimg_use_opencv' must be defined).", + cimg_instance); +#endif + } + + //! Load image from a camera stream, using OpenCV \newinstance. + static CImg get_load_camera(const unsigned int camera_index=0, const unsigned int skip_frames=0, + const bool release_camera=true, + const unsigned int capture_width=0, const unsigned int capture_height=0) { + return CImg().load_camera(camera_index,skip_frames,release_camera,capture_width,capture_height); + } + + //! Load image using various non-native ways. + /** + \param filename Filename, as a C-string. + **/ + CImg& load_other(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimg_instance + "load_other(): Specified filename is (null).", + cimg_instance); + + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { load_magick(filename); } + catch (CImgException&) { + try { load_imagemagick_external(filename); } + catch (CImgException&) { + try { load_graphicsmagick_external(filename); } + catch (CImgException&) { + try { load_cimg(filename); } + catch (CImgException&) { + try { + std::fclose(cimg::fopen(filename,"rb")); + } catch (CImgException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to open file '%s'.", + cimg_instance, + filename); + } + cimg::exception_mode(omode); + throw CImgIOException(_cimg_instance + "load_other(): Failed to recognize format of file '%s'.", + cimg_instance, + filename); + } + } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load image using various non-native ways \newinstance. + static CImg get_load_other(const char *const filename) { + return CImg().load_other(filename); + } + + //@} + //--------------------------- + // + //! \name Data Output + //@{ + //--------------------------- + + //! Display information about the image data. + /** + \param title Name for the considered image. + \param display_stats Tells to compute and display image statistics. + **/ + const CImg& 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 st; + if (!is_empty() && display_stats) { + st = get_stats(); + 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; + + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImg<%s>",pixel_type()); + + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = (%u,%u,%u,%u) [%lu %s], %sdata%s = (%s*)%p", + 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, + (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) + std::fprintf(cimg::output(),"..%p (%s) = [ ",(void*)((char*)end() - 1),_is_shared?"shared":"non-shared"); + else std::fprintf(cimg::output()," (%s) = [ ",_is_shared?"shared":"non-shared"); + + if (!is_empty()) cimg_foroff(*this,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(),"... "); } + } + if (!is_empty() && display_stats) + std::fprintf(cimg::output(), + " ], %smin%s = %g, %smax%s = %g, %smean%s = %g, %sstd%s = %g, %scoords_min%s = (%u,%u,%u,%u), " + "%scoords_max%s = (%u,%u,%u,%u).\n", + cimg::t_bold,cimg::t_normal,st[0], + cimg::t_bold,cimg::t_normal,st[1], + cimg::t_bold,cimg::t_normal,st[2], + cimg::t_bold,cimg::t_normal,std::sqrt(st[3]), + cimg::t_bold,cimg::t_normal,xm,ym,zm,vm, + cimg::t_bold,cimg::t_normal,xM,yM,zM,vM); + else std::fprintf(cimg::output(),"%s].\n",is_empty()?"":" "); + std::fflush(cimg::output()); + return *this; + } + + //! Display image into a CImgDisplay window. + /** + \param disp Display window. + **/ + const CImg& display(CImgDisplay& disp) const { + disp.display(*this); + return *this; + } + + //! Display image into a CImgDisplay window, in an interactive way. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + **/ + const CImg& display(CImgDisplay &disp, const bool display_info, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + return _display(disp,0,display_info,XYZ,exit_on_anykey,false); + } + + //! Display image into an interactive window. + /** + \param title Window title + \param display_info Tells if image information are displayed on the standard output. + **/ + const CImg& display(const char *const title=0, const bool display_info=true, unsigned int *const XYZ=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display(disp,title,display_info,XYZ,exit_on_anykey,false); + } + + const CImg& _display(CImgDisplay &disp, const char *const title, const bool display_info, + unsigned int *const XYZ, const bool exit_on_anykey, + const bool exit_on_simpleclick) const { + unsigned int oldw = 0, oldh = 0, _XYZ[3] = { 0 }, key = 0; + int x0 = 0, y0 = 0, z0 = 0, x1 = width() - 1, y1 = height() - 1, z1 = depth() - 1, + old_mouse_x = -1, old_mouse_y = -1; + + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,1); + if (!title) disp.set_title("CImg<%s> (%ux%ux%ux%u)",pixel_type(),_width,_height,_depth,_spectrum); + else disp.set_title("%s",title); + } else if (title) disp.set_title("%s",title); + disp.show().flush(); + + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(dtitle); + + CImg zoom; + for (bool reset_view = true, resize_disp = false, is_first_select = true; !key && !disp.is_closed(); ) { + if (reset_view) { + if (XYZ) { _XYZ[0] = XYZ[0]; _XYZ[1] = XYZ[1]; _XYZ[2] = XYZ[2]; } + else { + _XYZ[0] = (unsigned int)(x0 + x1)/2; + _XYZ[1] = (unsigned int)(y0 + y1)/2; + _XYZ[2] = (unsigned int)(z0 + z1)/2; + } + x0 = 0; y0 = 0; z0 = 0; x1 = width() - 1; y1 = height() - 1; z1 = depth() - 1; + oldw = disp._width; oldh = disp._height; + reset_view = false; + } + if (!x0 && !y0 && !z0 && x1==width() - 1 && y1==height() - 1 && z1==depth() - 1) { + if (is_empty()) zoom.assign(1,1,1,1,(T)0); else zoom.assign(); + } else zoom = get_crop(x0,y0,z0,x1,y1,z1); + + const CImg& 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); + if (!is_empty() && !disp.is_fullscreen() && resize_disp) { + const unsigned int + ttw = tw*disp.width()/oldw, tth = th*disp.height()/oldh, + dM = std::max(ttw,tth), diM = (unsigned int)std::max(disp.width(),disp.height()), + imgw = std::max(16U,ttw*diM/dM), imgh = std::max(16U,tth*diM/dM); + disp.set_fullscreen(false).resize(cimg_fitscreen(imgw,imgh,1),false); + resize_disp = false; + } + oldw = tw; oldh = th; + + bool + go_up = false, go_down = false, go_left = false, go_right = false, + go_inc = false, go_dec = false, go_in = false, go_out = false, + go_in_center = false; + + disp.set_title("%s",dtitle._data); + if (_width>1 && visu._width==1) disp.set_title("%s | x=%u",disp._title,x0); + if (_height>1 && visu._height==1) disp.set_title("%s | y=%u",disp._title,y0); + if (_depth>1 && visu._depth==1) disp.set_title("%s | z=%u",disp._title,z0); + + if (!is_first_select) { + _XYZ[0] = (unsigned int)(x1 - x0)/2; + _XYZ[1] = (unsigned int)(y1 - y0)/2; + _XYZ[2] = (unsigned int)(z1 - z0)/2; + } + + disp._mouse_x = old_mouse_x; disp._mouse_y = old_mouse_y; + const CImg 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; + + if (disp.wheel()) { + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + go_down = !(go_up = disp.wheel()>0); + } else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) { + go_left = !(go_right = disp.wheel()>0); + } + else if (disp.is_keyALT() || disp.is_keyALTGR() || _depth==1) { + go_out = !(go_in = disp.wheel()>0); go_in_center = false; + } + disp.set_wheel(); + } + + const int + sx0 = selection(0), sy0 = selection(1), sz0 = selection(2), + sx1 = selection(3), sy1 = selection(4), sz1 = selection(5); + if (sx0>=0 && sy0>=0 && sz0>=0 && sx1>=0 && sy1>=0 && sz1>=0) { + x1 = x0 + sx1; y1 = y0 + sy1; z1 = z0 + sz1; + x0+=sx0; y0+=sy0; z0+=sz0; + if (sx0==sx1 && sy0==sy1 && sz0==sz1) { + if (exit_on_simpleclick && (!zoom || is_empty())) break; else reset_view = true; + } + resize_disp = true; + } else switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : case cimg::keySHIFTRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : case cimg::keyPAD5 : case cimg::keySHIFTLEFT : +#if cimg_OS!=2 + case cimg::keyALTGR : +#endif + case cimg::keyALT : key = 0; break; + case cimg::keyP : if (visu._depth>1 && (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT())) { + // Special mode: play stack of frames + const unsigned int + w1 = visu._width*disp.width()/(visu._width + (visu._depth>1?visu._depth:0)), + h1 = visu._height*disp.height()/(visu._height + (visu._depth>1?visu._depth:0)); + float frame_timing = 5; + bool is_stopped = false; + disp.set_key(key,false).set_wheel().resize(cimg_fitscreen(w1,h1,1),false); key = 0; + for (unsigned int timer = 0; !key && !disp.is_closed() && !disp.button(); ) { + if (disp.is_resized()) disp.resize(false); + if (!timer) { + visu.get_slice((int)_XYZ[2]).display(disp.set_title("%s | z=%d",dtitle.data(),_XYZ[2])); + (++_XYZ[2])%=visu._depth; + } + if (!is_stopped) { if (++timer>(unsigned int)frame_timing) timer = 0; } else timer = ~0U; + if (disp.wheel()) { frame_timing-=disp.wheel()/3.0f; disp.set_wheel(); } + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyPAGEUP : frame_timing-=0.3f; key = 0; break; + case cimg::keyPAGEDOWN : frame_timing+=0.3f; key = 0; break; + case cimg::keySPACE : is_stopped = !is_stopped; disp.set_key(key,false); key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyARROWUP : is_stopped = true; timer = 0; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyARROWDOWN : is_stopped = true; + (_XYZ[2]+=visu._depth - 2)%=visu._depth; timer = 0; key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false).set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(_width,_height,_depth),false).set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false). + toggle_fullscreen().set_key(key,false); key = 0; + } break; + } + frame_timing = frame_timing<1?1:(frame_timing>39?39:frame_timing); + disp.wait(20); + } + const unsigned int + w2 = (visu._width + (visu._depth>1?visu._depth:0))*disp.width()/visu._width, + h2 = (visu._height + (visu._depth>1?visu._depth:0))*disp.height()/visu._height; + disp.resize(cimg_fitscreen(w2,h2,1),false).set_title(dtitle.data()).set_key().set_button().set_wheel(); + key = 0; + } break; + case cimg::keyHOME : reset_view = resize_disp = true; key = 0; break; + case cimg::keyPADADD : go_in = true; go_in_center = true; key = 0; break; + case cimg::keyPADSUB : go_out = true; key = 0; break; + case cimg::keyARROWLEFT : case cimg::keyPAD4: go_left = true; key = 0; break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6: go_right = true; key = 0; break; + case cimg::keyARROWUP : case cimg::keyPAD8: go_up = true; key = 0; break; + case cimg::keyARROWDOWN : case cimg::keyPAD2: go_down = true; key = 0; break; + case cimg::keyPAD7 : go_up = go_left = true; key = 0; break; + case cimg::keyPAD9 : go_up = go_right = true; key = 0; break; + case cimg::keyPAD1 : go_down = go_left = true; key = 0; break; + case cimg::keyPAD3 : go_down = go_right = true; key = 0; break; + case cimg::keyPAGEUP : go_inc = true; key = 0; break; + case cimg::keyPAGEDOWN : go_dec = true; key = 0; break; + } + if (go_in) { + const int + mx = go_in_center?disp.width()/2:disp.mouse_x(), + my = go_in_center?disp.height()/2:disp.mouse_y(), + mX = mx*(width() + (depth()>1?depth():0))/disp.width(), + mY = my*(height() + (depth()>1?depth():0))/disp.height(); + int X = (int)_XYZ[0], Y = (int)_XYZ[1], Z = (int)_XYZ[2]; + if (mX=height()) { + X = x0 + mX*(1 + x1 - x0)/width(); Z = z0 + (mY - height())*(1 + z1 - z0)/depth(); Y = (int)_XYZ[1]; + } + if (mX>=width() && mY4) { x0 = X - 3*(X - x0)/4; x1 = X + 3*(x1 - X)/4; } + if (y1 - y0>4) { y0 = Y - 3*(Y - y0)/4; y1 = Y + 3*(y1 - Y)/4; } + if (z1 - z0>4) { z0 = Z - 3*(Z - z0)/4; z1 = Z + 3*(z1 - Z)/4; } + } + if (go_out) { + const int + delta_x = (x1 - x0)/8, delta_y = (y1 - y0)/8, delta_z = (z1 - z0)/8, + ndelta_x = delta_x?delta_x:(_width>1), + ndelta_y = delta_y?delta_y:(_height>1), + ndelta_z = delta_z?delta_z:(_depth>1); + x0-=ndelta_x; y0-=ndelta_y; z0-=ndelta_z; + x1+=ndelta_x; y1+=ndelta_y; z1+=ndelta_z; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=width()) x1 = width() - 1; } + if (y0<0) { y1-=y0; y0 = 0; if (y1>=height()) y1 = height() - 1; } + if (z0<0) { z1-=z0; z0 = 0; if (z1>=depth()) z1 = depth() - 1; } + if (x1>=width()) { x0-=(x1 - width() + 1); x1 = width() - 1; if (x0<0) x0 = 0; } + if (y1>=height()) { y0-=(y1 - height() + 1); y1 = height() - 1; if (y0<0) y0 = 0; } + if (z1>=depth()) { z0-=(z1 - depth() + 1); z1 = depth() - 1; if (z0<0) z0 = 0; } + const float + ratio = (float)(x1-x0)/(y1-y0), + ratiow = (float)disp._width/disp._height, + sub = std::min(cimg::abs(ratio - ratiow),cimg::abs(1/ratio-1/ratiow)); + if (sub>0.01) resize_disp = true; + } + if (go_left) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + } + if (go_right) { + const int delta = (x1 - x0)/4, ndelta = delta?delta:(_width>1); + if (x1+ndelta1); + if (y0 - ndelta>=0) { y0-=ndelta; y1-=ndelta; } + else { y1-=y0; y0 = 0; } + } + if (go_down) { + const int delta = (y1 - y0)/4, ndelta = delta?delta:(_height>1); + if (y1+ndelta1); + if (z0 - ndelta>=0) { z0-=ndelta; z1-=ndelta; } + else { z1-=z0; z0 = 0; } + } + if (go_dec) { + const int delta = (z1 - z0)/4, ndelta = delta?delta:(_depth>1); + if (z1+ndelta + const CImg& display_object3d(CImgDisplay& disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return _display_object3d(disp,0,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_object3d(disp,title,vertices,primitives,colors,opacities,centering,render_static, + render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,colors,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const CImgList& primitives, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,primitives,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(CImgDisplay &disp, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(disp,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + //! Display object 3d in an interactive window \simplification. + template + const CImg& display_object3d(const char *const title, + const CImg& vertices, + const bool centering=true, + const int render_static=4, const int render_motion=1, + const bool is_double_sided=true, const float focale=700, + const float light_x=0, const float light_y=0, const float light_z=-5e8f, + const float specular_lightness=0.2f, const float specular_shininess=0.1f, + const bool display_axes=true, float *const pose_matrix=0, + const bool exit_on_anykey=false) const { + return display_object3d(title,vertices,CImgList(),centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + + template + const CImg& _display_object3d(CImgDisplay& disp, const char *const title, + const CImg& vertices, + const CImgList& primitives, + const CImgList& colors, + const to& opacities, + const bool centering, + const int render_static, const int render_motion, + const bool is_double_sided, const float focale, + const float light_x, const float light_y, const float light_z, + const float specular_lightness, const float specular_shininess, + const bool display_axes, float *const pose_matrix, + const bool exit_on_anykey) const { + typedef typename cimg::superset::type tpfloat; + + // Check input arguments + if (is_empty()) { + if (disp) return CImg(disp.width(),disp.height(),1,(colors && colors[0].size()==1)?1:3,0). + _display_object3d(disp,title,vertices,primitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + else return CImg(1,2,1,1,64,128).resize(cimg_fitscreen(CImgDisplay::screen_width()/2, + CImgDisplay::screen_height()/2,1), + 1,(colors && colors[0].size()==1)?1:3,3). + _display_object3d(disp,title,vertices,primitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } else { if (disp) disp.resize(*this,false); } + CImg error_message(1024); + if (!vertices.is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgArgumentException(_cimg_instance + "display_object3d(): Invalid specified 3d object (%u,%u) (%s).", + cimg_instance,vertices._width,primitives._width,error_message.data()); + if (vertices._width && !primitives) { + CImgList nprimitives(vertices._width,1,1,1,1); + cimglist_for(nprimitives,l) nprimitives(l,0) = (tf)l; + return _display_object3d(disp,title,vertices,nprimitives,colors,opacities,centering, + render_static,render_motion,is_double_sided,focale, + light_x,light_y,light_z,specular_lightness,specular_shininess, + display_axes,pose_matrix,exit_on_anykey); + } + if (!disp) { + disp.assign(cimg_fitscreen(_width,_height,_depth),title?title:0,3); + if (!title) disp.set_title("CImg<%s> (%u vertices, %u primitives)", + pixel_type(),vertices._width,primitives._width); + } else if (title) disp.set_title("%s",title); + + // Init 3d objects and compute object statistics + CImg + pose, + rotated_vertices(vertices._width,3), + bbox_vertices, rotated_bbox_vertices, + axes_vertices, rotated_axes_vertices, + bbox_opacities, axes_opacities; + CImgList bbox_primitives, axes_primitives; + CImgList reverse_primitives; + CImgList bbox_colors, bbox_colors2, axes_colors; + unsigned int ns_width = 0, ns_height = 0; + int _is_double_sided = (int)is_double_sided; + bool ndisplay_axes = display_axes; + const CImg + background_color(1,1,1,_spectrum,0), + foreground_color(1,1,1,_spectrum,255); + float + Xoff = 0, Yoff = 0, Zoff = 0, sprite_scale = 1, + xm = 0, xM = vertices?vertices.get_shared_row(0).max_min(xm):0, + ym = 0, yM = vertices?vertices.get_shared_row(1).max_min(ym):0, + zm = 0, zM = vertices?vertices.get_shared_row(2).max_min(zm):0; + const float delta = cimg::max(xM - xm,yM - ym,zM - zm); + + rotated_bbox_vertices = bbox_vertices.assign(8,3,1,1, + xm,xM,xM,xm,xm,xM,xM,xm, + ym,ym,yM,yM,ym,ym,yM,yM, + zm,zm,zm,zm,zM,zM,zM,zM); + bbox_primitives.assign(6,1,4,1,1, 0,3,2,1, 4,5,6,7, 1,2,6,5, 0,4,7,3, 0,1,5,4, 2,3,7,6); + bbox_colors.assign(6,_spectrum,1,1,1,background_color[0]); + bbox_colors2.assign(6,_spectrum,1,1,1,foreground_color[0]); + bbox_opacities.assign(bbox_colors._width,1,1,1,0.3f); + + rotated_axes_vertices = axes_vertices.assign(7,3,1,1, + 0,20,0,0,22,-6,-6, + 0,0,20,0,-6,22,-6, + 0,0,0,20,0,0,22); + axes_opacities.assign(3,1,1,1,1); + axes_colors.assign(3,_spectrum,1,1,1,foreground_color[0]); + axes_primitives.assign(3,1,2,1,1, 0,1, 0,2, 0,3); + + // Begin user interaction loop + CImg visu0(*this), visu; + CImg zbuffer(visu0.width(),visu0.height(),1,1,0); + bool init_pose = true, clicked = false, redraw = true; + unsigned int key = 0; + int + x0 = 0, y0 = 0, x1 = 0, y1 = 0, + nrender_static = render_static, + nrender_motion = render_motion; + disp.show().flush(); + + while (!disp.is_closed() && !key) { + + // Init object pose + if (init_pose) { + const float + ratio = delta>0?(2.0f*std::min(disp.width(),disp.height())/(3.0f*delta)):1, + dx = (xM + xm)/2, dy = (yM + ym)/2, dz = (zM + zm)/2; + if (centering) + CImg(4,3,1,1, ratio,0.,0.,-ratio*dx, 0.,ratio,0.,-ratio*dy, 0.,0.,ratio,-ratio*dz).move_to(pose); + else CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0).move_to(pose); + if (pose_matrix) { + CImg pose0(pose_matrix,4,3,1,1,false); + pose0.resize(4,4,1,1,0); pose.resize(4,4,1,1,0); + pose0(3,3) = pose(3,3) = 1; + (pose0*pose).get_crop(0,0,3,2).move_to(pose); + Xoff = pose_matrix[12]; Yoff = pose_matrix[13]; Zoff = pose_matrix[14]; sprite_scale = pose_matrix[15]; + } else { Xoff = Yoff = Zoff = 0; sprite_scale = 1; } + init_pose = false; + redraw = true; + } + + // Rotate and draw 3d object + if (redraw) { + const float + r00 = pose(0,0), r10 = pose(1,0), r20 = pose(2,0), r30 = pose(3,0), + r01 = pose(0,1), r11 = pose(1,1), r21 = pose(2,1), r31 = pose(3,1), + r02 = pose(0,2), r12 = pose(1,2), r22 = pose(2,2), r32 = pose(3,2); + if ((clicked && nrender_motion>=0) || (!clicked && nrender_static>=0)) + cimg_forX(vertices,l) { + const float x = (float)vertices(l,0), y = (float)vertices(l,1), z = (float)vertices(l,2); + rotated_vertices(l,0) = r00*x + r10*y + r20*z + r30; + rotated_vertices(l,1) = r01*x + r11*y + r21*z + r31; + rotated_vertices(l,2) = r02*x + r12*y + r22*z + r32; + } + else cimg_forX(bbox_vertices,l) { + const float x = bbox_vertices(l,0), y = bbox_vertices(l,1), z = bbox_vertices(l,2); + rotated_bbox_vertices(l,0) = r00*x + r10*y + r20*z + r30; + rotated_bbox_vertices(l,1) = r01*x + r11*y + r21*z + r31; + rotated_bbox_vertices(l,2) = r02*x + r12*y + r22*z + r32; + } + + // Draw objects + const bool render_with_zbuffer = !clicked && nrender_static>0; + visu = visu0; + if ((clicked && nrender_motion<0) || (!clicked && nrender_static<0)) + visu.draw_object3d(Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors,bbox_opacities,2,false,focale). + draw_object3d(Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff, + rotated_bbox_vertices,bbox_primitives,bbox_colors2,1,false,focale); + else visu._draw_object3d((void*)0,render_with_zbuffer?zbuffer.fill(0):CImg::empty(), + Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static,_is_double_sided==1,focale, + width()/2.0f + light_x,height()/2.0f + light_y,light_z + Zoff, + specular_lightness,specular_shininess,sprite_scale); + // Draw axes + if (ndisplay_axes) { + const float + n = 1e-8f + cimg::hypot(r00,r01,r02), + _r00 = r00/n, _r10 = r10/n, _r20 = r20/n, + _r01 = r01/n, _r11 = r11/n, _r21 = r21/n, + _r02 = r01/n, _r12 = r12/n, _r22 = r22/n, + Xaxes = 25, Yaxes = visu._height - 38.0f; + cimg_forX(axes_vertices,l) { + const float + x = axes_vertices(l,0), + y = axes_vertices(l,1), + z = axes_vertices(l,2); + rotated_axes_vertices(l,0) = _r00*x + _r10*y + _r20*z; + rotated_axes_vertices(l,1) = _r01*x + _r11*y + _r21*z; + rotated_axes_vertices(l,2) = _r02*x + _r12*y + _r22*z; + } + axes_opacities(0,0) = (rotated_axes_vertices(1,2)>0)?0.5f:1.0f; + axes_opacities(1,0) = (rotated_axes_vertices(2,2)>0)?0.5f:1.0f; + axes_opacities(2,0) = (rotated_axes_vertices(3,2)>0)?0.5f:1.0f; + visu.draw_object3d(Xaxes,Yaxes,0,rotated_axes_vertices,axes_primitives, + axes_colors,axes_opacities,1,false,focale). + draw_text((int)(Xaxes + rotated_axes_vertices(4,0)), + (int)(Yaxes + rotated_axes_vertices(4,1)), + "X",axes_colors[0]._data,0,axes_opacities(0,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(5,0)), + (int)(Yaxes + rotated_axes_vertices(5,1)), + "Y",axes_colors[1]._data,0,axes_opacities(1,0),13). + draw_text((int)(Xaxes + rotated_axes_vertices(6,0)), + (int)(Yaxes + rotated_axes_vertices(6,1)), + "Z",axes_colors[2]._data,0,axes_opacities(2,0),13); + } + visu.display(disp); + if (!clicked || nrender_motion==nrender_static) redraw = false; + } + + // Handle user interaction + disp.wait(); + if ((disp.button() || disp.wheel()) && disp.mouse_x()>=0 && disp.mouse_y()>=0) { + redraw = true; + if (!clicked) { x0 = x1 = disp.mouse_x(); y0 = y1 = disp.mouse_y(); if (!disp.wheel()) clicked = true; } + else { x1 = disp.mouse_x(); y1 = disp.mouse_y(); } + if (disp.button()&1) { + const float + R = 0.45f*std::min(disp.width(),disp.height()), + R2 = R*R, + u0 = (float)(x0 - disp.width()/2), + v0 = (float)(y0 - disp.height()/2), + u1 = (float)(x1 - disp.width()/2), + v1 = (float)(y1 - disp.height()/2), + n0 = cimg::hypot(u0,v0), + n1 = cimg::hypot(u1,v1), + nu0 = n0>R?(u0*R/n0):u0, + nv0 = n0>R?(v0*R/n0):v0, + nw0 = (float)std::sqrt(std::max(0.0f,R2 - nu0*nu0 - nv0*nv0)), + nu1 = n1>R?(u1*R/n1):u1, + nv1 = n1>R?(v1*R/n1):v1, + nw1 = (float)std::sqrt(std::max(0.0f,R2 - nu1*nu1 - nv1*nv1)), + u = nv0*nw1 - nw0*nv1, + v = nw0*nu1 - nu0*nw1, + w = nv0*nu1 - nu0*nv1, + n = cimg::hypot(u,v,w), + alpha = (float)std::asin(n/R2)*180/cimg::PI; + (CImg::rotation_matrix(u,v,w,-alpha)*pose).move_to(pose); + x0 = x1; y0 = y1; + } + if (disp.button()&2) { + if (focale>0) Zoff-=(y0 - y1)*focale/400; + else { const float s = std::exp((y0 - y1)/400.0f); pose*=s; sprite_scale*=s; } + x0 = x1; y0 = y1; + } + if (disp.wheel()) { + if (focale>0) Zoff-=disp.wheel()*focale/20; + else { const float s = std::exp(disp.wheel()/20.0f); pose*=s; sprite_scale*=s; } + disp.set_wheel(); + } + if (disp.button()&4) { Xoff+=(x1 - x0); Yoff+=(y1 - y0); x0 = x1; y0 = y1; } + if ((disp.button()&1) && (disp.button()&2)) { + init_pose = true; disp.set_button(); x0 = x1; y0 = y1; + pose = CImg(4,3,1,1, 1,0,0,0, 0,1,0,0, 0,0,1,0); + } + } else if (clicked) { x0 = x1; y0 = y1; clicked = false; redraw = true; } + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD: if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false).resize(cimg_fitscreen(_width,_height,_depth),false)._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + if (!ns_width || !ns_height || + ns_width>(unsigned int)disp.screen_width() || ns_height>(unsigned int)disp.screen_height()) { + ns_width = disp.screen_width()*3U/4; + ns_height = disp.screen_height()*3U/4; + } + if (disp.is_fullscreen()) disp.resize(ns_width,ns_height,false); + else { + ns_width = disp._width; ns_height = disp._height; + disp.resize(disp.screen_width(),disp.screen_height(),false); + } + disp.toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; + } break; + case cimg::keyT : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Switch single/double-sided primitives. + if (--_is_double_sided==-2) _is_double_sided = 1; + if (_is_double_sided>=0) reverse_primitives.assign(); + else primitives.get_reverse_object3d().move_to(reverse_primitives); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyZ : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Enable/disable Z-buffer + if (zbuffer) zbuffer.assign(); + else zbuffer.assign(visu0.width(),visu0.height(),1,1,0); + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyA : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Show/hide 3d axes. + ndisplay_axes = !ndisplay_axes; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF1 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to points. + nrender_motion = (nrender_static==0 && nrender_motion!=0)?0:-1; nrender_static = 0; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF2 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to lines. + nrender_motion = (nrender_static==1 && nrender_motion!=1)?1:-1; nrender_static = 1; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF3 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat. + nrender_motion = (nrender_static==2 && nrender_motion!=2)?2:-1; nrender_static = 2; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF4 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to flat-shaded. + nrender_motion = (nrender_static==3 && nrender_motion!=3)?3:-1; nrender_static = 3; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF5 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + // Set rendering mode to gouraud-shaded. + nrender_motion = (nrender_static==4 && nrender_motion!=4)?4:-1; nrender_static = 4; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyF6 : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Set rendering mode to phong-shaded. + nrender_motion = (nrender_static==5 && nrender_motion!=5)?5:-1; nrender_static = 5; + disp.set_key(key,false); key = 0; redraw = true; + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save snapshot + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).draw_text(0,0," Saving snapshot... ", + foreground_color._data,background_color._data,0.7f,13).display(disp); + visu.save(filename); + (+visu).draw_text(0,0," Snapshot '%s' saved. ", + foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyG : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .off file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.off",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).draw_text(0,0," Saving object... ", + foreground_color._data,background_color._data,0.7f,13).display(disp); + vertices.save_off(reverse_primitives?reverse_primitives:primitives,colors,filename); + (+visu).draw_text(0,0," Object '%s' saved. ", + foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyO : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .cimg file + static unsigned int snap_number = 0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).draw_text(0,0," Saving object... ", + foreground_color._data,background_color._data,0.7f,13).display(disp); + vertices.get_object3dtoCImg3d(reverse_primitives?reverse_primitives:primitives,colors,opacities). + save(filename); + (+visu).draw_text(0,0," Object '%s' saved. ", + foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; +#ifdef cimg_use_board + case cimg::keyP : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .EPS file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.eps",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).draw_text(0,0," Saving EPS snapshot... ", + foreground_color._data,background_color._data,0.7f,13).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.0f + light_x,visu.height()/2.0f + light_y,light_z + Zoff, + specular_lightness,specular_shininess, + sprite_scale); + board.saveEPS(filename); + (+visu).draw_text(0,0," Object '%s' saved. ", + foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; + case cimg::keyV : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { // Save object as a .SVG file + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.svg",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu).draw_text(0,0," Saving SVG snapshot... ", + foreground_color._data,background_color._data,0.7f,13).display(disp); + LibBoard::Board board; + (+visu)._draw_object3d(&board,zbuffer.fill(0), + Xoff + visu._width/2.0f,Yoff + visu._height/2.0f,Zoff, + rotated_vertices,reverse_primitives?reverse_primitives:primitives, + colors,opacities,clicked?nrender_motion:nrender_static, + _is_double_sided==1,focale, + visu.width()/2.0f + light_x,visu.height()/2.0f + light_y,light_z + Zoff, + specular_lightness,specular_shininess, + sprite_scale); + board.saveSVG(filename); + (+visu).draw_text(0,0," Object '%s' saved. ", + foreground_color._data,background_color._data,0.7f,13,filename._data).display(disp); + disp.set_key(key,false); key = 0; + } break; +#endif + } + if (disp.is_resized()) { + disp.resize(false); visu0 = get_resize(disp,1); + if (zbuffer) zbuffer.assign(disp.width(),disp.height()); + redraw = true; + } + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + if (pose_matrix) { + std::memcpy(pose_matrix,pose._data,12*sizeof(float)); + pose_matrix[12] = Xoff; pose_matrix[13] = Yoff; pose_matrix[14] = Zoff; pose_matrix[15] = sprite_scale; + } + disp.set_button().set_key(key); + return *this; + } + + //! Display 1d graph in an interactive window. + /** + \param disp Display window. + \param plot_type Plot type. Can be { 0=points | 1=segments | 2=splines | 3=bars }. + \param vertex_type Vertex type. + \param labelx Title for the horizontal axis, as a C-string. + \param xmin Minimum value along the X-axis. + \param xmax Maximum value along the X-axis. + \param labely Title for the vertical axis, as a C-string. + \param ymin Minimum value along the X-axis. + \param ymax Maximum value along the X-axis. + **/ + const CImg& display_graph(CImgDisplay &disp, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + return _display_graph(disp,0,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + //! Display 1d graph in an interactive window \overloading. + const CImg& display_graph(const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _display_graph(disp,title,plot_type,vertex_type,labelx,xmin,xmax,labely,ymin,ymax,exit_on_anykey); + } + + const CImg& _display_graph(CImgDisplay &disp, const char *const title=0, + const unsigned int plot_type=1, const unsigned int vertex_type=1, + const char *const labelx=0, const double xmin=0, const double xmax=0, + const char *const labely=0, const double ymin=0, const double ymax=0, + const bool exit_on_anykey=false) const { + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "display_graph(): Empty instance.", + cimg_instance); + if (!disp) disp.assign(cimg_fitscreen(CImgDisplay::screen_width()/2,CImgDisplay::screen_height()/2,1),0,0). + set_title(title?"%s":"CImg<%s>",title?title:pixel_type()); + const ulongT siz = (ulongT)_width*_height*_depth, siz1 = std::max((ulongT)1,siz - 1); + const unsigned int old_normalization = disp.normalization(); + disp.show().flush()._normalization = 0; + + double y0 = ymin, y1 = ymax, nxmin = xmin, nxmax = xmax; + if (nxmin==nxmax) { nxmin = 0; nxmax = siz1; } + int x0 = 0, x1 = width()*height()*depth() - 1, key = 0; + + for (bool reset_view = true; !key && !disp.is_closed(); ) { + if (reset_view) { x0 = 0; x1 = width()*height()*depth() - 1; y0 = ymin; y1 = ymax; reset_view = false; } + CImg zoom(x1 - x0 + 1,1,1,spectrum()); + cimg_forC(*this,c) zoom.get_shared_channel(c) = CImg(data(x0,0,0,c),x1 - x0 + 1,1,1,1,true); + if (y0==y1) { y0 = zoom.min_max(y1); const double dy = y1 - y0; y0-=dy/20; y1+=dy/20; } + if (y0==y1) { --y0; ++y1; } + + const CImg selection = zoom.get_select_graph(disp,plot_type,vertex_type, + labelx, + nxmin + x0*(nxmax - nxmin)/siz1, + nxmin + x1*(nxmax - nxmin)/siz1, + labely,y0,y1,true); + const int mouse_x = disp.mouse_x(), mouse_y = disp.mouse_y(); + if (selection[0]>=0) { + if (selection[2]<0) reset_view = true; + else { + x1 = x0 + selection[2]; x0+=selection[0]; + if (selection[1]>=0 && selection[3]>=0) { + y0 = y1 - selection[3]*(y1 - y0)/(disp.height() - 32); + y1-=selection[1]*(y1 - y0)/(disp.height() - 32); + } + } + } else { + bool go_in = false, go_out = false, go_left = false, go_right = false, go_up = false, go_down = false; + switch (key = (int)disp.key()) { + case cimg::keyHOME : reset_view = true; key = 0; disp.set_key(); break; + case cimg::keyPADADD : go_in = true; go_out = false; key = 0; disp.set_key(); break; + case cimg::keyPADSUB : go_out = true; go_in = false; key = 0; disp.set_key(); break; + case cimg::keyARROWLEFT : case cimg::keyPAD4 : go_left = true; go_right = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWRIGHT : case cimg::keyPAD6 : go_right = true; go_left = false; key = 0; disp.set_key(); + break; + case cimg::keyARROWUP : case cimg::keyPAD8 : go_up = true; go_down = false; key = 0; disp.set_key(); break; + case cimg::keyARROWDOWN : case cimg::keyPAD2 : go_down = true; go_up = false; key = 0; disp.set_key(); break; + case cimg::keyPAD7 : go_left = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD9 : go_right = true; go_up = true; key = 0; disp.set_key(); break; + case cimg::keyPAD1 : go_left = true; go_down = true; key = 0; disp.set_key(); break; + case cimg::keyPAD3 : go_right = true; go_down = true; key = 0; disp.set_key(); break; + } + if (disp.wheel()) { + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) go_up = !(go_down = disp.wheel()<0); + else if (disp.is_keySHIFTLEFT() || disp.is_keySHIFTRIGHT()) go_left = !(go_right = disp.wheel()>0); + else go_out = !(go_in = disp.wheel()>0); + key = 0; + } + + if (go_in) { + const int + xsiz = x1 - x0, + mx = (mouse_x - 16)*xsiz/(disp.width() - 32), + cx = x0 + cimg::cut(mx,0,xsiz); + if (x1 - x0>4) { + x0 = cx - 7*(cx - x0)/8; x1 = cx + 7*(x1 - cx)/8; + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + const double + ysiz = y1 - y0, + my = (mouse_y - 16)*ysiz/(disp.height() - 32), + cy = y1 - cimg::cut(my,0.0,ysiz); + y0 = cy - 7*(cy - y0)/8; y1 = cy + 7*(y1 - cy)/8; + } else y0 = y1 = 0; + } + } + if (go_out) { + if (x0>0 || x1<(int)siz1) { + const int delta_x = (x1 - x0)/8, ndelta_x = delta_x?delta_x:(siz>1); + const double ndelta_y = (y1 - y0)/8; + x0-=ndelta_x; x1+=ndelta_x; + y0-=ndelta_y; y1+=ndelta_y; + if (x0<0) { x1-=x0; x0 = 0; if (x1>=(int)siz) x1 = (int)siz1; } + if (x1>=(int)siz) { x0-=(x1 - siz1); x1 = (int)siz1; if (x0<0) x0 = 0; } + } + } + if (go_left) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x0 - ndelta>=0) { x0-=ndelta; x1-=ndelta; } + else { x1-=x0; x0 = 0; } + go_left = false; + } + if (go_right) { + const int delta = (x1 - x0)/5, ndelta = delta?delta:1; + if (x1 + ndelta<(int)siz) { x0+=ndelta; x1+=ndelta; } + else { x0+=(siz1 - x1); x1 = (int)siz1; } + go_right = false; + } + if (go_up) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0+=ndelta; y1+=ndelta; + go_up = false; + } + if (go_down) { + const double delta = (y1 - y0)/10, ndelta = delta?delta:1; + y0-=ndelta; y1-=ndelta; + go_down = false; + } + } + if (!exit_on_anykey && key && key!=(int)cimg::keyESC && + (key!=(int)cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + disp.set_key(key,false); + key = 0; + } + } + disp._normalization = old_normalization; + return *this; + } + + //! Save image as a file. + /** + \param filename Filename, as a C-string. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + \note + - The used file format is defined by the file extension in the filename \p filename. + - Parameter \p number can be used to add a 6-digit number to the filename before saving. + + **/ + const CImg& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save(): Specified filename is (null).", + cimg_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:(number>=0)?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimg_save_plugin + cimg_save_plugin(fn); +#endif +#ifdef cimg_save_plugin1 + cimg_save_plugin1(fn); +#endif +#ifdef cimg_save_plugin2 + cimg_save_plugin2(fn); +#endif +#ifdef cimg_save_plugin3 + cimg_save_plugin3(fn); +#endif +#ifdef cimg_save_plugin4 + cimg_save_plugin4(fn); +#endif +#ifdef cimg_save_plugin5 + cimg_save_plugin5(fn); +#endif +#ifdef cimg_save_plugin6 + cimg_save_plugin6(fn); +#endif +#ifdef cimg_save_plugin7 + cimg_save_plugin7(fn); +#endif +#ifdef cimg_save_plugin8 + cimg_save_plugin8(fn); +#endif + // Ascii formats + if (!cimg::strcasecmp(ext,"asc")) return save_ascii(fn); + else if (!cimg::strcasecmp(ext,"dlm") || + !cimg::strcasecmp(ext,"txt")) return save_dlm(fn); + else if (!cimg::strcasecmp(ext,"cpp") || + !cimg::strcasecmp(ext,"hpp") || + !cimg::strcasecmp(ext,"h") || + !cimg::strcasecmp(ext,"c")) return save_cpp(fn); + + // 2d binary formats + else if (!cimg::strcasecmp(ext,"bmp")) return save_bmp(fn); + else if (!cimg::strcasecmp(ext,"jpg") || + !cimg::strcasecmp(ext,"jpeg") || + !cimg::strcasecmp(ext,"jpe") || + !cimg::strcasecmp(ext,"jfif") || + !cimg::strcasecmp(ext,"jif")) return save_jpeg(fn); + else if (!cimg::strcasecmp(ext,"rgb")) return save_rgb(fn); + else if (!cimg::strcasecmp(ext,"rgba")) return save_rgba(fn); + else if (!cimg::strcasecmp(ext,"png")) return save_png(fn); + else if (!cimg::strcasecmp(ext,"pgm") || + !cimg::strcasecmp(ext,"ppm") || + !cimg::strcasecmp(ext,"pnm")) return save_pnm(fn); + else if (!cimg::strcasecmp(ext,"pnk")) return save_pnk(fn); + else if (!cimg::strcasecmp(ext,"pfm")) return save_pfm(fn); + else if (!cimg::strcasecmp(ext,"exr")) return save_exr(fn); + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); + + // 3d binary formats + else if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg") || !*ext) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"dcm")) return save_medcon_external(fn); + else if (!cimg::strcasecmp(ext,"hdr") || + !cimg::strcasecmp(ext,"nii")) return save_analyze(fn); + else if (!cimg::strcasecmp(ext,"inr")) return save_inr(fn); + else if (!cimg::strcasecmp(ext,"mnc")) return save_minc2(fn); + else if (!cimg::strcasecmp(ext,"pan")) return save_pandore(fn); + else if (!cimg::strcasecmp(ext,"raw")) return save_raw(fn); + + // Archive files + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + + // Image sequences + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); + return save_other(fn); + } + + //! Save image as an ascii file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_ascii(const char *const filename) const { + return _save_ascii(0,filename); + } + + //! Save image as an ascii file \overloading. + const CImg& save_ascii(std::FILE *const file) const { + return _save_ascii(file,0); + } + + const CImg& _save_ascii(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_ascii(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + 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,"%.17g ",(double)*(ptrs++)); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a .cpp source file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_cpp(const char *const filename) const { + return _save_cpp(0,filename); + } + + //! Save image as a .cpp source file \overloading. + const CImg& save_cpp(std::FILE *const file) const { + return _save_cpp(file,0); + } + + const CImg& _save_cpp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_cpp(): Specified filename is (null).", + cimg_instance); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + CImg varname(1024); *varname = 0; + if (filename) cimg_sscanf(cimg::basename(filename),"%1023[a-zA-Z0-9_]",varname._data); + if (!*varname) cimg_snprintf(varname,varname._width,"unnamed"); + std::fprintf(nfile, + "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n" + "%s data_%s[] = { %s\n ", + varname._data,_width,_height,_depth,_spectrum,pixel_type(),pixel_type(),varname._data, + is_empty()?"};":""); + if (!is_empty()) for (ulongT off = 0, siz = size() - 1; off<=siz; ++off) { + std::fprintf(nfile,cimg::type::format(),cimg::type::format((*this)[off])); + if (off==siz) std::fprintf(nfile," };\n"); + else if (!((off + 1)%16)) std::fprintf(nfile,",\n "); + else std::fprintf(nfile,", "); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a DLM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_dlm(const char *const filename) const { + return _save_dlm(0,filename); + } + + //! Save image as a DLM file \overloading. + const CImg& save_dlm(std::FILE *const file) const { + return _save_dlm(file,0); + } + + const CImg& _save_dlm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_dlm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is volumetric, values along Z will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_dlm(): Instance is multispectral, values along C will be unrolled in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + 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,"%.17g%s",(double)*(ptrs++),(x==width() - 1)?"":","); + std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a BMP file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_bmp(const char *const filename) const { + return _save_bmp(0,filename); + } + + //! Save image as a BMP file \overloading. + const CImg& save_bmp(std::FILE *const file) const { + return _save_bmp(file,0); + } + + const CImg& _save_bmp(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_bmp(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_bmp(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_bmp(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(54,1,1,1,0); + unsigned char align_buf[4] = { 0 }; + const unsigned int + align = (4 - (3*_width)%4)%4, + buf_size = (3*_width + align)*height(), + file_size = 54 + buf_size; + header[0] = 'B'; header[1] = 'M'; + header[0x02] = file_size&0xFF; + header[0x03] = (file_size>>8)&0xFF; + header[0x04] = (file_size>>16)&0xFF; + header[0x05] = (file_size>>24)&0xFF; + header[0x0A] = 0x36; + header[0x0E] = 0x28; + header[0x12] = _width&0xFF; + header[0x13] = (_width>>8)&0xFF; + header[0x14] = (_width>>16)&0xFF; + header[0x15] = (_width>>24)&0xFF; + header[0x16] = _height&0xFF; + header[0x17] = (_height>>8)&0xFF; + header[0x18] = (_height>>16)&0xFF; + header[0x19] = (_height>>24)&0xFF; + header[0x1A] = 1; + header[0x1B] = 0; + header[0x1C] = 24; + header[0x1D] = 0; + header[0x22] = buf_size&0xFF; + header[0x23] = (buf_size>>8)&0xFF; + header[0x24] = (buf_size>>16)&0xFF; + header[0x25] = (buf_size>>24)&0xFF; + header[0x27] = 0x1; + header[0x2B] = 0x1; + cimg::fwrite(header._data,54,nfile); + + const T + *ptr_r = data(0,_height - 1,0,0), + *ptr_g = (_spectrum>=2)?data(0,_height - 1,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,_height - 1,0,2):0; + + switch (_spectrum) { + case 1 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + const unsigned char val = (unsigned char)*(ptr_r++); + std::fputc(val,nfile); std::fputc(val,nfile); std::fputc(val,nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; + } + } break; + case 2 : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc(0,nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; + } + } break; + default : { + cimg_forY(*this,y) { + cimg_forX(*this,x) { + std::fputc((unsigned char)(*(ptr_b++)),nfile); + std::fputc((unsigned char)(*(ptr_g++)),nfile); + std::fputc((unsigned char)(*(ptr_r++)),nfile); + } + cimg::fwrite(align_buf,align,nfile); + ptr_r-=2*_width; ptr_g-=2*_width; ptr_b-=2*_width; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a JPEG file. + /** + \param filename Filename, as a C-string. + \param quality Image quality (in %) + **/ + const CImg& save_jpeg(const char *const filename, const unsigned int quality=100) const { + return _save_jpeg(0,filename,quality); + } + + //! Save image as a JPEG file \overloading. + const CImg& save_jpeg(std::FILE *const file, const unsigned int quality=100) const { + return _save_jpeg(file,0,quality); + } + + const CImg& _save_jpeg(std::FILE *const file, const char *const filename, const unsigned int quality) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_jpeg(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + +#ifndef cimg_use_jpeg + if (!file) return save_other(filename,quality); + else throw CImgIOException(_cimg_instance + "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.", + cimg_instance); +#else + unsigned int dimbuf = 0; + J_COLOR_SPACE colortype = JCS_RGB; + + switch (_spectrum) { + case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE; break; + case 2 : dimbuf = 3; colortype = JCS_RGB; break; + case 3 : dimbuf = 3; colortype = JCS_RGB; break; + default : dimbuf = 4; colortype = JCS_CMYK; break; + } + + // Call libjpeg functions + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + jpeg_stdio_dest(&cinfo,nfile); + cinfo.image_width = _width; + cinfo.image_height = _height; + cinfo.input_components = dimbuf; + cinfo.in_color_space = colortype; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE); + jpeg_start_compress(&cinfo,TRUE); + + JSAMPROW row_pointer[1]; + CImg buffer(_width*dimbuf); + + while (cinfo.next_scanline& save_magick(const char *const filename, const unsigned int bytes_per_pixel=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_magick(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_magick + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_magick(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_magick(): Instance is multispectral, only the three first channels will be " + "saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_magick(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + Magick::Image image(Magick::Geometry(_width,_height),"black"); + image.type(Magick::TrueColorType); + image.depth(bytes_per_pixel?(8*bytes_per_pixel):(stmax>=256?16:8)); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = _spectrum>1?data(0,0,0,1):0, + *ptr_b = _spectrum>2?data(0,0,0,2):0; + Magick::PixelPacket *pixels = image.getPixels(0,0,_width,_height); + switch (_spectrum) { + case 1 : // Scalar images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = pixels->green = pixels->blue = (Magick::Quantum)*(ptr_r++); + ++pixels; + } + break; + case 2 : // RG images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = 0; ++pixels; + } + break; + default : // RGB images + for (ulongT off = (ulongT)_width*_height; off; --off) { + pixels->red = (Magick::Quantum)*(ptr_r++); + pixels->green = (Magick::Quantum)*(ptr_g++); + pixels->blue = (Magick::Quantum)*(ptr_b++); + ++pixels; + } + } + image.syncPixels(); + image.write(filename); + return *this; +#else + cimg::unused(bytes_per_pixel); + throw CImgIOException(_cimg_instance + "save_magick(): Unable to save file '%s' unless libMagick++ is enabled.", + cimg_instance, + filename); +#endif + } + + //! Save image as a PNG file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving, when possible. + **/ + const CImg& save_png(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_png(0,filename,bytes_per_pixel); + } + + //! Save image as a PNG file \overloading. + const CImg& save_png(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_png(file,0,bytes_per_pixel); + } + + const CImg& _save_png(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_png(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + +#ifndef cimg_use_png + cimg::unused(bytes_per_pixel); + if (!file) return save_other(filename); + else throw CImgIOException(_cimg_instance + "save_png(): Unable to save data in '(*FILE)' unless libpng is enabled.", + cimg_instance); +#else + const char *volatile nfilename = filename; // two 'volatile' here to remove a g++ warning due to 'setjmp'. + std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"wb"); + volatile double stmin, stmax = (double)max_min(stmin); + + if (_depth>1) + cimg::warn(_cimg_instance + "save_png(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + + if (_spectrum>4) + cimg::warn(_cimg_instance + "save_png(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename); + + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_png(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + filename,stmin,stmax); + + // Setup PNG structures for write + png_voidp user_error_ptr = 0; + png_error_ptr user_error_fn = 0, user_warning_fn = 0; + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,user_error_ptr, user_error_fn, + user_warning_fn); + if(!png_ptr){ + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'png_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)0); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Failed to initialize 'info_ptr' structure when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_init_io(png_ptr, nfile); + + const int bit_depth = bytes_per_pixel?(bytes_per_pixel*8):(stmax>=256?16:8); + + int color_type; + switch (spectrum()) { + case 1 : color_type = PNG_COLOR_TYPE_GRAY; break; + case 2 : color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; + case 3 : color_type = PNG_COLOR_TYPE_RGB; break; + default : color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + const int interlace_type = PNG_INTERLACE_NONE; + const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT; + const int filter_method = PNG_FILTER_TYPE_DEFAULT; + png_set_IHDR(png_ptr,info_ptr,_width,_height,bit_depth,color_type,interlace_type,compression_type,filter_method); + png_write_info(png_ptr,info_ptr); + const int byte_depth = bit_depth>>3; + const int numChan = spectrum()>4?4:spectrum(); + const int pixel_bit_depth_flag = numChan * (bit_depth - 1); + + // Allocate Memory for Image Save and Fill pixel data + png_bytep *const imgData = new png_byte*[_height]; + for (unsigned int row = 0; row<_height; ++row) imgData[row] = new png_byte[byte_depth*numChan*_width]; + const T *pC0 = data(0,0,0,0); + switch (pixel_bit_depth_flag) { + case 7 : { // Gray 8-bit + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) *(ptrd++) = (unsigned char)*(pC0++); + } + } break; + case 14 : { // Gray w/ Alpha 8-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + } + } + } break; + case 21 : { // RGB 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x) { + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + } + } + } break; + case 28 : { // RGB x/ Alpha 8-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y){ + unsigned char *ptrd = imgData[y]; + cimg_forX(*this,x){ + *(ptrd++) = (unsigned char)*(pC0++); + *(ptrd++) = (unsigned char)*(pC1++); + *(ptrd++) = (unsigned char)*(pC2++); + *(ptrd++) = (unsigned char)*(pC3++); + } + } + } break; + case 15 : { // Gray 16-bit + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) *(ptrd++) = (unsigned short)*(pC0++); + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],_width); + } + } break; + case 30 : { // Gray w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1); + cimg_forY(*this,y){ + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],2*_width); + } + } break; + case 45 : { // RGB 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],3*_width); + } + } break; + case 60 : { // RGB w/ Alpha 16-bit + const T *pC1 = data(0,0,0,1), *pC2 = data(0,0,0,2), *pC3 = data(0,0,0,3); + cimg_forY(*this,y) { + unsigned short *ptrd = (unsigned short*)(imgData[y]); + cimg_forX(*this,x) { + *(ptrd++) = (unsigned short)*(pC0++); + *(ptrd++) = (unsigned short)*(pC1++); + *(ptrd++) = (unsigned short)*(pC2++); + *(ptrd++) = (unsigned short)*(pC3++); + } + if (!cimg::endianness()) cimg::invert_endianness((unsigned short*)imgData[y],4*_width); + } + } break; + default : + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimg_instance + "save_png(): Encountered unknown fatal error in libpng when saving file '%s'.", + cimg_instance, + nfilename?nfilename:"(FILE*)"); + } + png_write_image(png_ptr,imgData); + png_write_end(png_ptr,info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + // Deallocate Image Write Memory + cimg_forY(*this,n) delete[] imgData[n]; + delete[] imgData; + + if (!file) cimg::fclose(nfile); + return *this; +#endif + } + + //! Save image as a PNM file. + /** + \param filename Filename, as a C-string. + \param bytes_per_pixel Force the number of bytes per pixels for the saving. + **/ + const CImg& save_pnm(const char *const filename, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(0,filename,bytes_per_pixel); + } + + //! Save image as a PNM file \overloading. + const CImg& save_pnm(std::FILE *const file, const unsigned int bytes_per_pixel=0) const { + return _save_pnm(file,0,bytes_per_pixel); + } + + const CImg& _save_pnm(std::FILE *const file, const char *const filename, + const unsigned int bytes_per_pixel=0) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + double stmin, stmax = (double)max_min(stmin); + if (_depth>1) + cimg::warn(_cimg_instance + "save_pnm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pnm(): Instance is multispectral, only the three first channels will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536) + cimg::warn(_cimg_instance + "save_pnm(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.", + cimg_instance, + stmin,stmax,filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const ulongT buf_size = std::min((ulongT)(1024*1024),(ulongT)(_width*_height*(_spectrum==1?1UL:3UL))); + + std::fprintf(nfile,"P%c\n%u %u\n%u\n", + (_spectrum==1?'5':'6'),_width,_height,stmax<256?255:(stmax<4096?4095:65535)); + + switch (_spectrum) { + case 1 : { // Scalar image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PGM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr_r++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Binary PGM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned short)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + } break; + case 2 : { // RG image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = 0; + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } break; + default : { // RGB image + if (bytes_per_pixel==1 || (!bytes_per_pixel && stmax<256)) { // Binary PPM 8 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned char)*(ptr_r++); + *(ptrd++) = (unsigned char)*(ptr_g++); + *(ptrd++) = (unsigned char)*(ptr_b++); + } + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } else { // Binary PPM 16 bits + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size/3); + unsigned short *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (unsigned short)*(ptr_r++); + *(ptrd++) = (unsigned short)*(ptr_g++); + *(ptrd++) = (unsigned short)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PNK file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pnk(const char *const filename) const { + return _save_pnk(0,filename); + } + + //! Save image as a PNK file \overloading. + const CImg& save_pnk(std::FILE *const file) const { + return _save_pnk(file,0); + } + + const CImg& _save_pnk(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pnk(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum>1) + cimg::warn(_cimg_instance + "save_pnk(): Instance is multispectral, only the first channel will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + const ulongT buf_size = std::min((ulongT)1024*1024,(ulongT)_width*_height*_depth); + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T *ptr = data(0,0,0,0); + + if (!cimg::type::is_float() && sizeof(T)==1 && _depth<2) // Can be saved as regular PNM file. + _save_pnm(file,filename,0); + else if (!cimg::type::is_float() && sizeof(T)==1) { // Save as extended P5 file: Binary byte-valued 3d. + std::fprintf(nfile,"P5\n%u %u %u\n255\n",_width,_height,_depth); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + unsigned char *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (unsigned char)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else if (!cimg::type::is_float()) { // Save as P8: Binary int32-valued 3d. + if (_depth>1) std::fprintf(nfile,"P8\n%u %u %u\n%d\n",_width,_height,_depth,(int)max()); + else std::fprintf(nfile,"P8\n%u %u\n%d\n",_width,_height,(int)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + int *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (int)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } else { // Save as P9: Binary float-valued 3d. + if (_depth>1) std::fprintf(nfile,"P9\n%u %u %u\n%g\n",_width,_height,_depth,(double)max()); + else std::fprintf(nfile,"P9\n%u %u\n%g\n",_width,_height,(double)max()); + CImg buf((unsigned int)buf_size); + for (longT to_write = (longT)width()*height()*depth(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr++); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a PFM file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_pfm(const char *const filename) const { + get_mirror('y')._save_pfm(0,filename); + return *this; + } + + //! Save image as a PFM file \overloading. + const CImg& save_pfm(std::FILE *const file) const { + get_mirror('y')._save_pfm(file,0); + return *this; + } + + const CImg& _save_pfm(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pfm(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_pfm(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + if (_spectrum>3) + cimg::warn(_cimg_instance + "save_pfm(): image instance is multispectral, only the three first channels will be saved " + "in file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const T + *ptr_r = data(0,0,0,0), + *ptr_g = (_spectrum>=2)?data(0,0,0,1):0, + *ptr_b = (_spectrum>=3)?data(0,0,0,2):0; + const unsigned int buf_size = std::min(1024*1024U,_width*_height*(_spectrum==1?1:3)); + + std::fprintf(nfile,"P%c\n%u %u\n1.0\n", + (_spectrum==1?'f':'F'),_width,_height); + + switch (_spectrum) { + case 1 : { // Scalar image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const ulongT N = std::min((ulongT)to_write,(ulongT)buf_size); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) *(ptrd++) = (float)*(ptr_r++); + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,N,nfile); + to_write-=N; + } + } break; + case 2 : { // RG image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = 0; + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } break; + default : { // RGB image + CImg buf(buf_size); + for (longT to_write = (longT)width()*height(); to_write>0; ) { + const unsigned int N = std::min((unsigned int)to_write,buf_size/3); + float *ptrd = buf._data; + for (ulongT i = N; i>0; --i) { + *(ptrd++) = (float)*(ptr_r++); + *(ptrd++) = (float)*(ptr_g++); + *(ptrd++) = (float)*(ptr_b++); + } + if (!cimg::endianness()) cimg::invert_endianness(buf._data,buf_size); + cimg::fwrite(buf._data,3*N,nfile); + to_write-=N; + } + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a RGB file. + /** + \param filename Filename, as a C-string. + **/ + const CImg& save_rgb(const char *const filename) const { + return _save_rgb(0,filename); + } + + //! Save image as a RGB file \overloading. + const CImg& save_rgb(std::FILE *const file) const { + return _save_rgb(file,0); + } + + const CImg& _save_rgb(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgb(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=3) + cimg::warn(_cimg_instance + "save_rgb(): image instance has not exactly 3 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[3*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0; + switch (_spectrum) { + case 1 : { // Scalar image + for (ulongT k = 0; k& save_rgba(const char *const filename) const { + return _save_rgba(0,filename); + } + + //! Save image as a RGBA file \overloading. + const CImg& save_rgba(std::FILE *const file) const { + return _save_rgba(file,0); + } + + const CImg& _save_rgba(std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_rgba(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if (_spectrum!=4) + cimg::warn(_cimg_instance + "save_rgba(): image instance has not exactly 4 channels, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT wh = (ulongT)_width*_height; + unsigned char *const buffer = new unsigned char[4*wh], *nbuffer = buffer; + const T + *ptr1 = data(0,0,0,0), + *ptr2 = _spectrum>1?data(0,0,0,1):0, + *ptr3 = _spectrum>2?data(0,0,0,2):0, + *ptr4 = _spectrum>3?data(0,0,0,3):0; + switch (_spectrum) { + case 1 : { // Scalar images + for (ulongT k = 0; k{ 0=None | 1=LZW | 2=JPEG }. + \note + - libtiff support is enabled by defining the precompilation + directive \c cimg_use_tif. + - When libtiff is enabled, 2D and 3D (multipage) several + channel per pixel are supported for + char,uchar,short,ushort,float and \c double pixel types. + - If \c cimg_use_tif is not defined at compile time the + function uses CImg&save_other(const char*). + **/ + const CImg& save_tiff(const char *const filename, const unsigned int compression_type=0, + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_tiff(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifdef cimg_use_tiff + const bool + _use_bigtiff = use_bigtiff && sizeof(ulongT)>=8 && size()*sizeof(T)>=1UL<<31; // No bigtiff for small images. + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + cimg_forZ(*this,z) _save_tiff(tif,z,z,compression_type,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimg_instance + "save_tiff(): Failed to open file '%s' for writing.", + cimg_instance, + filename); + return *this; +#else + cimg::unused(compression_type,voxel_size,description,use_bigtiff); + return save_other(filename); +#endif + } + +#ifdef cimg_use_tiff + +#define _cimg_save_tiff(types,typed,compression_type) if (!std::strcmp(types,pixel_type())) { \ + const typed foo = (typed)0; return _save_tiff(tif,directory,z,foo,compression_type,voxel_size,description); } + + // [internal] Save a plane into a tiff file + template + const CImg& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, const t& pixel_t, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + if (is_empty() || !tif || pixel_t) return *this; + const char *const filename = TIFFFileName(tif); + uint32 rowsperstrip = (uint32)-1; + uint16 spp = _spectrum, bpp = sizeof(t)*8, photometric; + if (spp==3 || spp==4) photometric = PHOTOMETRIC_RGB; + else photometric = PHOTOMETRIC_MINISBLACK; + TIFFSetDirectory(tif,directory); + TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,_width); + TIFFSetField(tif,TIFFTAG_IMAGELENGTH,_height); + if (voxel_size) { + const float vx = voxel_size[0], vy = voxel_size[1], vz = voxel_size[2]; + TIFFSetField(tif,TIFFTAG_RESOLUTIONUNIT,RESUNIT_NONE); + TIFFSetField(tif,TIFFTAG_XRESOLUTION,1.0f/vx); + TIFFSetField(tif,TIFFTAG_YRESOLUTION,1.0f/vy); + CImg s_description(256); + cimg_snprintf(s_description,s_description._width,"VX=%g VY=%g VZ=%g spacing=%g",vx,vy,vz,vz); + TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,s_description.data()); + } + if (description) TIFFSetField(tif,TIFFTAG_IMAGEDESCRIPTION,description); + TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT); + TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,spp); + if (cimg::type::is_float()) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,3); + else if (cimg::type::min()==0) TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,1); + else TIFFSetField(tif,TIFFTAG_SAMPLEFORMAT,2); + TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,bpp); + TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); + TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,photometric); + TIFFSetField(tif,TIFFTAG_COMPRESSION,compression_type==2?COMPRESSION_JPEG: + compression_type==1?COMPRESSION_LZW:COMPRESSION_NONE); + rowsperstrip = TIFFDefaultStripSize(tif,rowsperstrip); + TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP,rowsperstrip); + TIFFSetField(tif,TIFFTAG_FILLORDER,FILLORDER_MSB2LSB); + TIFFSetField(tif,TIFFTAG_SOFTWARE,"CImg"); + t *const buf = (t*)_TIFFmalloc(TIFFStripSize(tif)); + if (buf) { + for (unsigned int row = 0; row<_height; row+=rowsperstrip) { + uint32 nrow = (row + rowsperstrip>_height?_height - row:rowsperstrip); + tstrip_t strip = TIFFComputeStrip(tif,row,0); + tsize_t i = 0; + for (unsigned int rr = 0; rr& _save_tiff(TIFF *tif, const unsigned int directory, const unsigned int z, + const unsigned int compression_type, const float *const voxel_size, + const char *const description) const { + _cimg_save_tiff("bool",unsigned char,compression_type); + _cimg_save_tiff("unsigned char",unsigned char,compression_type); + _cimg_save_tiff("char",char,compression_type); + _cimg_save_tiff("unsigned short",unsigned short,compression_type); + _cimg_save_tiff("short",short,compression_type); + _cimg_save_tiff("unsigned int",unsigned int,compression_type); + _cimg_save_tiff("int",int,compression_type); + _cimg_save_tiff("unsigned int64",unsigned int,compression_type); + _cimg_save_tiff("int64",int,compression_type); + _cimg_save_tiff("float",float,compression_type); + _cimg_save_tiff("double",float,compression_type); + const char *const filename = TIFFFileName(tif); + throw CImgInstanceException(_cimg_instance + "save_tiff(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + return *this; + } +#endif + + //! Save image as a MINC2 file. + /** + \param filename Filename, as a C-string. + \param imitate_file If non-zero, reference filename, as a C-string, to borrow header from. + **/ + const CImg& save_minc2(const char *const filename, + const char *const imitate_file=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_minc2(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_minc2 + cimg::unused(imitate_file); + return save_other(filename); +#else + minc::minc_1_writer wtr; + if (imitate_file) + wtr.open(filename, imitate_file); + else { + minc::minc_info di; + if(width()) di.push_back(minc::dim_info(width(),width()*0.5,-1,minc::dim_info::DIM_X)); + if(height()) di.push_back(minc::dim_info(height(),height()*0.5,-1,minc::dim_info::DIM_Y)); + if(depth()) di.push_back(minc::dim_info(depth(),depth()*0.5,-1,minc::dim_info::DIM_Z)); + if(spectrum()) di.push_back(minc::dim_info(spectrum(),spectrum()*0.5,-1,minc::dim_info::DIM_TIME)); + wtr.open(filename,di,1,NC_FLOAT,0); + } + if(typeid(T)==typeid(unsigned char)) + wtr.setup_write_byte(); + else if(typeid(T)==typeid(int)) + wtr.setup_write_int(); + else if(typeid(T)==typeid(double)) + wtr.setup_write_double(); + else + wtr.setup_write_float(); + minc::save_standard_volume(wtr, this->_data); + return *this; +#endif + } + + //! Save image as an ANALYZE7.5 or NIFTI file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 consecutive values that tell about the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_analyze(const char *const filename, const float *const voxel_size=0) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_analyze(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + std::FILE *file; + CImg hname(1024), iname(1024); + const char *const ext = cimg::split_filename(filename); + short datatype = -1; + if (!*ext) { + cimg_snprintf(hname,hname._width,"%s.hdr",filename); + cimg_snprintf(iname,iname._width,"%s.img",filename); + } + if (!cimg::strncasecmp(ext,"hdr",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(iname._data + std::strlen(iname) - 3,"img"); + } + if (!cimg::strncasecmp(ext,"img",3)) { + std::strcpy(hname,filename); + std::strncpy(iname,filename,iname._width - 1); + cimg_sprintf(hname._data + std::strlen(iname) - 3,"hdr"); + } + if (!cimg::strncasecmp(ext,"nii",3)) { + std::strncpy(hname,filename,hname._width - 1); *iname = 0; + } + + CImg header(*iname?348:352,1,1,1,0); + int *const iheader = (int*)header._data; + *iheader = 348; + std::strcpy(header._data + 4,"CImg"); + std::strcpy(header._data + 14," "); + ((short*)&(header[36]))[0] = 4096; + ((char*)&(header[38]))[0] = 114; + ((short*)&(header[40]))[0] = 4; + ((short*)&(header[40]))[1] = (short)_width; + ((short*)&(header[40]))[2] = (short)_height; + ((short*)&(header[40]))[3] = (short)_depth; + ((short*)&(header[40]))[4] = (short)_spectrum; + if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2; + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4; + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"unsigned int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"int64")) datatype = 8; + if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16; + if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64; + if (datatype<0) + throw CImgIOException(_cimg_instance + "save_analyze(): Unsupported pixel type '%s' for file '%s'.", + cimg_instance, + pixel_type(),filename); + + ((short*)&(header[70]))[0] = datatype; + ((short*)&(header[72]))[0] = sizeof(T); + ((float*)&(header[108]))[0] = (float)(*iname?0:header.width()); + ((float*)&(header[112]))[0] = 1; + ((float*)&(header[76]))[0] = 0; + if (voxel_size) { + ((float*)&(header[76]))[1] = voxel_size[0]; + ((float*)&(header[76]))[2] = voxel_size[1]; + ((float*)&(header[76]))[3] = voxel_size[2]; + } else ((float*)&(header[76]))[1] = ((float*)&(header[76]))[2] = ((float*)&(header[76]))[3] = 1; + file = cimg::fopen(hname,"wb"); + cimg::fwrite(header._data,header.width(),file); + if (*iname) { cimg::fclose(file); file = cimg::fopen(iname,"wb"); } + cimg::fwrite(_data,size(),file); + cimg::fclose(file); + return *this; + } + + //! Save image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param is_compressed Tells if the file contains compressed image data. + **/ + const CImg& save_cimg(const char *const filename, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(filename,is_compressed); + return *this; + } + + //! Save image as a .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, const bool is_compressed=false) const { + CImgList(*this,true).save_cimg(file,is_compressed); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file. + /** + \param filename Filename, as a C-string. + \param n0 Index of the image inside the file. + \param x0 X-coordinate of the sub-image location. + \param y0 Y-coordinate of the sub-image location. + \param z0 Z-coordinate of the sub-image location. + \param c0 C-coordinate of the sub-image location. + **/ + const CImg& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(filename,n0,x0,y0,z0,c0); + return *this; + } + + //! Save image as a sub-image into an existing .cimg file \overloading. + const CImg& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + CImgList(*this,true).save_cimg(file,n0,x0,y0,z0,c0); + return *this; + } + + //! Save blank image as a .cimg file. + /** + \param filename Filename, as a C-string. + \param dx Width of the image. + \param dy Height of the image. + \param dz Depth of the image. + \param dc Number of channels of the image. + \note + - All pixel values of the saved image are set to \c 0. + - Use this method to save large images without having to instanciate and allocate them. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(filename,1,dx,dy,dz,dc); + } + + //! Save blank image as a .cimg file \overloading. + /** + Same as save_empty_cimg(const char *,unsigned int,unsigned int,unsigned int,unsigned int) + with a file stream argument instead of a filename string. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return CImgList::save_empty_cimg(file,1,dx,dy,dz,dc); + } + + //! Save image as an INRIMAGE-4 file. + /** + \param filename Filename, as a C-string. + \param voxel_size Pointer to 3 values specifying the voxel sizes along the X,Y and Z dimensions. + **/ + const CImg& save_inr(const char *const filename, const float *const voxel_size=0) const { + return _save_inr(0,filename,voxel_size); + } + + //! Save image as an INRIMAGE-4 file \overloading. + const CImg& save_inr(std::FILE *const file, const float *const voxel_size=0) const { + return _save_inr(file,0,voxel_size); + } + + const CImg& _save_inr(std::FILE *const file, const char *const filename, const float *const voxel_size) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_inr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + int inrpixsize = -1; + const char *inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; + if (!cimg::strcasecmp(pixel_type(),"unsigned char")) { + inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"char")) { + inrtype = "fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned short")) { + inrtype = "unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"short")) { + inrtype = "fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2; + } + if (!cimg::strcasecmp(pixel_type(),"unsigned int")) { + inrtype = "unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"int")) { + inrtype = "fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"float")) { + inrtype = "float\nPIXSIZE=32 bits"; inrpixsize = 4; + } + if (!cimg::strcasecmp(pixel_type(),"double")) { + inrtype = "float\nPIXSIZE=64 bits"; inrpixsize = 8; + } + if (inrpixsize<=0) + throw CImgIOException(_cimg_instance + "save_inr(): Unsupported pixel type '%s' for file '%s'", + cimg_instance, + pixel_type(),filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + CImg header(257); + int err = cimg_snprintf(header,header._width,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n", + _width,_height,_depth,_spectrum); + if (voxel_size) err+=cimg_sprintf(header._data + err,"VX=%g\nVY=%g\nVZ=%g\n", + voxel_size[0],voxel_size[1],voxel_size[2]); + err+=cimg_sprintf(header._data + err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endianness()?"sun":"decm"); + std::memset(header._data + err,'\n',252 - err); + std::memcpy(header._data + 252,"##}\n",4); + cimg::fwrite(header._data,256,nfile); + cimg_forXYZ(*this,x,y,z) cimg_forC(*this,c) cimg::fwrite(&((*this)(x,y,z,c)),1,nfile); + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as an OpenEXR file. + /** + \param filename Filename, as a C-string. + \note The OpenEXR file format is described here. + **/ + const CImg& save_exr(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_exr(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_exr(): Instance is volumetric, only the first slice will be saved in file '%s'.", + cimg_instance, + filename); + +#ifndef cimg_use_openexr + return save_other(filename); +#else + Imf::Rgba *const ptrd0 = new Imf::Rgba[(size_t)_width*_height], *ptrd = ptrd0, rgba; + switch (_spectrum) { + case 1 : { // Grayscale image. + for (const T *ptr_r = data(), *const ptr_e = ptr_r + (ulongT)_width*_height; ptr_rPandore file specifications + for more information). + **/ + const CImg& save_pandore(const char *const filename, const unsigned int colorspace=0) const { + return _save_pandore(0,filename,colorspace); + } + + //! Save image as a Pandore-5 file \overloading. + /** + Same as save_pandore(const char *,unsigned int) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_pandore(std::FILE *const file, const unsigned int colorspace=0) const { + return _save_pandore(file,0,colorspace); + } + + unsigned int _save_pandore_header_length(unsigned int id, unsigned int *dims, const unsigned int colorspace) const { + unsigned int nbdims = 0; + if (id==2 || id==3 || id==4) { + dims[0] = 1; dims[1] = _width; nbdims = 2; + } + if (id==5 || id==6 || id==7) { + dims[0] = 1; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==8 || id==9 || id==10) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + if (id==16 || id==17 || id==18) { + dims[0] = 3; dims[1] = _height; dims[2] = _width; dims[3] = colorspace; nbdims = 4; + } + if (id==19 || id==20 || id==21) { + dims[0] = 3; dims[1] = _depth; dims[2] = _height; dims[3] = _width; dims[4] = colorspace; nbdims = 5; + } + if (id==22 || id==23 || id==25) { + dims[0] = _spectrum; dims[1] = _width; nbdims = 2; + } + if (id==26 || id==27 || id==29) { + dims[0] = _spectrum; dims[1] = _height; dims[2] = _width; nbdims=3; + } + if (id==30 || id==31 || id==33) { + dims[0] = _spectrum; dims[1] = _depth; dims[2] = _height; dims[3] = _width; nbdims = 4; + } + return nbdims; + } + + const CImg& _save_pandore(std::FILE *const file, const char *const filename, + const unsigned int colorspace) const { + +#define __cimg_save_pandore_case(dtype) \ + dtype *buffer = new dtype[size()]; \ + const T *ptrs = _data; \ + cimg_foroff(*this,off) *(buffer++) = (dtype)(*(ptrs++)); \ + buffer-=size(); \ + cimg::fwrite(buffer,size(),nfile); \ + delete[] buffer + +#define _cimg_save_pandore_case(sy,sz,sv,stype,id) \ + if (!saved && (sy?(sy==_height):true) && (sz?(sz==_depth):true) && \ + (sv?(sv==_spectrum):true) && !std::strcmp(stype,pixel_type())) { \ + unsigned int *iheader = (unsigned int*)(header + 12); \ + nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \ + cimg::fwrite(header,36,nfile); \ + if (sizeof(unsigned long)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned long)dims[d]; cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned int)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned int)dims[d]; cimg::fwrite(ndims._data,nbdims,nfile); } \ + else if (sizeof(unsigned short)==4) { CImg ndims(5); \ + for (int d = 0; d<5; ++d) ndims[d] = (unsigned short)dims[d]; cimg::fwrite(ndims._data,nbdims,nfile); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \ + __cimg_save_pandore_case(unsigned char); \ + } else if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \ + if (sizeof(unsigned long)==4) { __cimg_save_pandore_case(unsigned long); } \ + else if (sizeof(unsigned int)==4) { __cimg_save_pandore_case(unsigned int); } \ + else if (sizeof(unsigned short)==4) { __cimg_save_pandore_case(unsigned short); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } else if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \ + if (sizeof(double)==4) { __cimg_save_pandore_case(double); } \ + else if (sizeof(float)==4) { __cimg_save_pandore_case(float); } \ + else throw CImgIOException(_cimg_instance \ + "save_pandore(): Unsupported datatype for file '%s'.",\ + cimg_instance, \ + filename?filename:"(FILE*)"); \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_pandore(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0, + 0,0,0,0,'C','I','m','g',0,0,0,0,0, + 'N','o',' ','d','a','t','e',0,0,0,0 }; + unsigned int nbdims, dims[5] = { 0 }; + bool saved = false; + _cimg_save_pandore_case(1,1,1,"unsigned char",2); + _cimg_save_pandore_case(1,1,1,"char",3); + _cimg_save_pandore_case(1,1,1,"unsigned short",3); + _cimg_save_pandore_case(1,1,1,"short",3); + _cimg_save_pandore_case(1,1,1,"unsigned int",3); + _cimg_save_pandore_case(1,1,1,"int",3); + _cimg_save_pandore_case(1,1,1,"unsigned int64",3); + _cimg_save_pandore_case(1,1,1,"int64",3); + _cimg_save_pandore_case(1,1,1,"float",4); + _cimg_save_pandore_case(1,1,1,"double",4); + + _cimg_save_pandore_case(0,1,1,"unsigned char",5); + _cimg_save_pandore_case(0,1,1,"char",6); + _cimg_save_pandore_case(0,1,1,"unsigned short",6); + _cimg_save_pandore_case(0,1,1,"short",6); + _cimg_save_pandore_case(0,1,1,"unsigned int",6); + _cimg_save_pandore_case(0,1,1,"int",6); + _cimg_save_pandore_case(0,1,1,"unsigned int64",6); + _cimg_save_pandore_case(0,1,1,"int64",6); + _cimg_save_pandore_case(0,1,1,"float",7); + _cimg_save_pandore_case(0,1,1,"double",7); + + _cimg_save_pandore_case(0,0,1,"unsigned char",8); + _cimg_save_pandore_case(0,0,1,"char",9); + _cimg_save_pandore_case(0,0,1,"unsigned short",9); + _cimg_save_pandore_case(0,0,1,"short",9); + _cimg_save_pandore_case(0,0,1,"unsigned int",9); + _cimg_save_pandore_case(0,0,1,"int",9); + _cimg_save_pandore_case(0,0,1,"unsigned int64",9); + _cimg_save_pandore_case(0,0,1,"int64",9); + _cimg_save_pandore_case(0,0,1,"float",10); + _cimg_save_pandore_case(0,0,1,"double",10); + + _cimg_save_pandore_case(0,1,3,"unsigned char",16); + _cimg_save_pandore_case(0,1,3,"char",17); + _cimg_save_pandore_case(0,1,3,"unsigned short",17); + _cimg_save_pandore_case(0,1,3,"short",17); + _cimg_save_pandore_case(0,1,3,"unsigned int",17); + _cimg_save_pandore_case(0,1,3,"int",17); + _cimg_save_pandore_case(0,1,3,"unsigned int64",17); + _cimg_save_pandore_case(0,1,3,"int64",17); + _cimg_save_pandore_case(0,1,3,"float",18); + _cimg_save_pandore_case(0,1,3,"double",18); + + _cimg_save_pandore_case(0,0,3,"unsigned char",19); + _cimg_save_pandore_case(0,0,3,"char",20); + _cimg_save_pandore_case(0,0,3,"unsigned short",20); + _cimg_save_pandore_case(0,0,3,"short",20); + _cimg_save_pandore_case(0,0,3,"unsigned int",20); + _cimg_save_pandore_case(0,0,3,"int",20); + _cimg_save_pandore_case(0,0,3,"unsigned int64",20); + _cimg_save_pandore_case(0,0,3,"int64",20); + _cimg_save_pandore_case(0,0,3,"float",21); + _cimg_save_pandore_case(0,0,3,"double",21); + + _cimg_save_pandore_case(1,1,0,"unsigned char",22); + _cimg_save_pandore_case(1,1,0,"char",23); + _cimg_save_pandore_case(1,1,0,"unsigned short",23); + _cimg_save_pandore_case(1,1,0,"short",23); + _cimg_save_pandore_case(1,1,0,"unsigned int",23); + _cimg_save_pandore_case(1,1,0,"int",23); + _cimg_save_pandore_case(1,1,0,"unsigned int64",23); + _cimg_save_pandore_case(1,1,0,"int64",23); + _cimg_save_pandore_case(1,1,0,"float",25); + _cimg_save_pandore_case(1,1,0,"double",25); + + _cimg_save_pandore_case(0,1,0,"unsigned char",26); + _cimg_save_pandore_case(0,1,0,"char",27); + _cimg_save_pandore_case(0,1,0,"unsigned short",27); + _cimg_save_pandore_case(0,1,0,"short",27); + _cimg_save_pandore_case(0,1,0,"unsigned int",27); + _cimg_save_pandore_case(0,1,0,"int",27); + _cimg_save_pandore_case(0,1,0,"unsigned int64",27); + _cimg_save_pandore_case(0,1,0,"int64",27); + _cimg_save_pandore_case(0,1,0,"float",29); + _cimg_save_pandore_case(0,1,0,"double",29); + + _cimg_save_pandore_case(0,0,0,"unsigned char",30); + _cimg_save_pandore_case(0,0,0,"char",31); + _cimg_save_pandore_case(0,0,0,"unsigned short",31); + _cimg_save_pandore_case(0,0,0,"short",31); + _cimg_save_pandore_case(0,0,0,"unsigned int",31); + _cimg_save_pandore_case(0,0,0,"int",31); + _cimg_save_pandore_case(0,0,0,"unsigned int64",31); + _cimg_save_pandore_case(0,0,0,"int64",31); + _cimg_save_pandore_case(0,0,0,"float",33); + _cimg_save_pandore_case(0,0,0,"double",33); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a raw data file. + /** + \param filename Filename, as a C-string. + \param is_multiplexed Tells if the image channels are stored in a multiplexed way (\c true) or not (\c false). + \note The .raw format does not store the image dimensions in the output file, + so you have to keep track of them somewhere to be able to read the file correctly afterwards. + **/ + const CImg& save_raw(const char *const filename, const bool is_multiplexed=false) const { + return _save_raw(0,filename,is_multiplexed); + } + + //! Save image as a raw data file \overloading. + /** + Same as save_raw(const char *,bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_raw(std::FILE *const file, const bool is_multiplexed=false) const { + return _save_raw(file,0,is_multiplexed); + } + + const CImg& _save_raw(std::FILE *const file, const char *const filename, const bool is_multiplexed) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_raw(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + if (!is_multiplexed) cimg::fwrite(_data,size(),nfile); + else { + CImg buf(_spectrum); + cimg_forXYZ(*this,x,y,z) { + cimg_forC(*this,c) buf[c] = (*this)(x,y,z,c); + cimg::fwrite(buf._data,_spectrum,nfile); + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save image as a .yuv video file. + /** + \param filename Filename, as a C-string. + \param is_rgb Tells if pixel values of the instance image are RGB-coded (\c true) or YUV-coded (\c false). + \note Each slice of the instance image is considered to be a single frame of the output video file. + **/ + const CImg& save_yuv(const char *const filename, const bool is_rgb=true) const { + get_split('z').save_yuv(filename,is_rgb); + return *this; + } + + //! Save image as a .yuv video file \overloading. + /** + Same as save_yuv(const char*,bool) const + with a file stream argument instead of a filename string. + **/ + const CImg& save_yuv(std::FILE *const file, const bool is_rgb=true) const { + get_split('z').save_yuv(file,is_rgb); + return *this; + } + + //! Save 3d object as an Object File Format (.off) file. + /** + \param filename Filename, as a C-string. + \param primitives List of 3d object primitives. + \param colors List of 3d object colors. + \note + - Instance image contains the vertices data of the 3d object. + - Textured, transparent or sphere-shaped primitives cannot be managed by the .off file format. + Such primitives will be lost or simplified during file saving. + - The .off file format is described here. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + const char *const filename) const { + return _save_off(primitives,colors,0,filename); + } + + //! Save 3d object as an Object File Format (.off) file \overloading. + /** + Same as save_off(const CImgList&,const CImgList&,const char*) const + with a file stream argument instead of a filename string. + **/ + template + const CImg& save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file) const { + return _save_off(primitives,colors,file,0); + } + + template + const CImg& _save_off(const CImgList& primitives, const CImgList& colors, + std::FILE *const file, const char *const filename) const { + if (!file && !filename) + throw CImgArgumentException(_cimg_instance + "save_off(): Specified filename is (null).", + cimg_instance); + if (is_empty()) + throw CImgInstanceException(_cimg_instance + "save_off(): Empty instance, for file '%s'.", + cimg_instance, + filename?filename:"(FILE*)"); + + CImgList opacities; + CImg error_message(1024); + if (!is_object3d(primitives,colors,opacities,true,error_message)) + throw CImgInstanceException(_cimg_instance + "save_off(): Invalid specified 3d object, for file '%s' (%s).", + cimg_instance, + filename?filename:"(FILE*)",error_message.data()); + + const CImg default_color(1,3,1,1,200); + std::FILE *const nfile = file?file:cimg::fopen(filename,"w"); + unsigned int supported_primitives = 0; + cimglist_for(primitives,l) if (primitives[l].size()!=5) ++supported_primitives; + std::fprintf(nfile,"OFF\n%u %u %u\n",_width,supported_primitives,3*primitives._width); + cimg_forX(*this,i) std::fprintf(nfile,"%f %f %f\n", + (float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2))); + cimglist_for(primitives,l) { + const CImg& color = l1?color[1]:r)/255.0f, b = (csiz>2?color[2]:g)/255.0f; + switch (psiz) { + case 1 : std::fprintf(nfile,"1 %u %f %f %f\n", + (unsigned int)primitives(l,0),r,g,b); break; + case 2 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 3 : std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),r,g,b); break; + case 4 : std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),r,g,b); break; + case 5 : std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),r,g,b); break; + case 6 : { + const unsigned int xt = (unsigned int)primitives(l,2), yt = (unsigned int)primitives(l,3); + const float + rt = color.atXY(xt,yt,0)/255.0f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f; + std::fprintf(nfile,"2 %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 9 : { + const unsigned int xt = (unsigned int)primitives(l,3), yt = (unsigned int)primitives(l,4); + const float + rt = color.atXY(xt,yt,0)/255.0f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f; + std::fprintf(nfile,"3 %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,2), + (unsigned int)primitives(l,1),rt,gt,bt); + } break; + case 12 : { + const unsigned int xt = (unsigned int)primitives(l,4), yt = (unsigned int)primitives(l,5); + const float + rt = color.atXY(xt,yt,0)/255.0f, + gt = (csiz>1?color.atXY(xt,yt,1):r)/255.0f, + bt = (csiz>2?color.atXY(xt,yt,2):g)/255.0f; + std::fprintf(nfile,"4 %u %u %u %u %f %f %f\n", + (unsigned int)primitives(l,0),(unsigned int)primitives(l,3), + (unsigned int)primitives(l,2),(unsigned int)primitives(l,1),rt,gt,bt); + } break; + } + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save volumetric image as a video, using the OpenCV library. + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImg& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { + if (is_empty()) { CImgList().save_video(filename,fps,codec,keep_open); return *this; } + CImgList list; + get_split('z').move_to(list); + list.save_video(filename,fps,codec,keep_open); + return *this; + } + + //! Save volumetric image as a video, using ffmpeg external binary. + /** + \param filename Filename, as a C-string. + \param fps Video framerate. + \param codec Video codec, as a C-string. + \param bitrate Video bitrate. + \note + - Each slice of the instance image is considered to be a single frame of the output video file. + - This method uses \c ffmpeg, an external executable binary provided by + FFmpeg. + It must be installed for the method to succeed. + **/ + const CImg& save_ffmpeg_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_ffmpeg_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImgList list; + get_split('z').move_to(list); + list.save_ffmpeg_external(filename,fps,codec,bitrate); + return *this; + } + + //! Save image using gzip external binary. + /** + \param filename Filename, as a C-string. + \note This method uses \c gzip, an external executable binary provided by + gzip. + It must be installed for the method to succeed. + **/ + const CImg& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_gzip_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save(filename_tmp); + cimg_snprintf(command,command._width,"%s -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command); + file = std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimg_instance, + filename); + + else cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using GraphicsMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c gm, an external executable binary provided by + GraphicsMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_graphicsmagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_graphicsmagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + +#ifdef cimg_use_png +#define _cimg_sge_ext1 "png" +#define _cimg_sge_ext2 "png" +#else +#define _cimg_sge_ext1 "pgm" +#define _cimg_sge_ext2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(), + _spectrum==1?_cimg_sge_ext1:_cimg_sge_ext2); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"%s convert -quality %u \"%s\" \"%s\"", + cimg::graphicsmagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command); + file = std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_graphicsmagick_external(): Failed to save file '%s' with external command 'gm'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image using ImageMagick's external binary. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note This method uses \c convert, an external executable binary provided by + ImageMagick. + It must be installed for the method to succeed. + **/ + const CImg& save_imagemagick_external(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_imagemagick_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick only writes the first image slice.", + cimg_instance,filename); +#ifdef cimg_use_png +#define _cimg_sie_ext1 "png" +#define _cimg_sie_ext2 "png" +#else +#define _cimg_sie_ext1 "pgm" +#define _cimg_sie_ext2 "ppm" +#endif + CImg command(1024), filename_tmp(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s",cimg::temporary_path(), + cimg_file_separator,cimg::filenamerand(),_spectrum==1?_cimg_sie_ext1:_cimg_sie_ext2); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); +#ifdef cimg_use_png + save_png(filename_tmp); +#else + save_pnm(filename_tmp); +#endif + cimg_snprintf(command,command._width,"%s -quality %u \"%s\" \"%s\"", + cimg::imagemagick_path(),quality, + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command); + file = std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimg_instance + "save_imagemagick_external(): Failed to save file '%s' with external command 'convert'.", + cimg_instance, + filename); + + if (file) cimg::fclose(file); + std::remove(filename_tmp); + return *this; + } + + //! Save image as a Dicom file. + /** + \param filename Filename, as a C-string. + \note This method uses \c medcon, an external executable binary provided by + (X)Medcon. + It must be installed for the method to succeed. + **/ + const CImg& save_medcon_external(const char *const filename) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_medcon_external(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + CImg command(1024), filename_tmp(256), body(256); + std::FILE *file; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.hdr",cimg::filenamerand()); + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + save_analyze(filename_tmp); + cimg_snprintf(command,command._width,"%s -w -c dicom -o \"%s\" -f \"%s\"", + cimg::medcon_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command); + std::remove(filename_tmp); + cimg::split_filename(filename_tmp,body); + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.img",body._data); + std::remove(filename_tmp); + + file = std_fopen(filename,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"m000-%s",filename); + file = std_fopen(command,"rb"); + if (!file) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimg_instance + "save_medcon_external(): Failed to save file '%s' with external command 'medcon'.", + cimg_instance, + filename); + } + } + cimg::fclose(file); + std::rename(command,filename); + return *this; + } + + // Save image for non natively supported formats. + /** + \param filename Filename, as a C-string. + \param quality Image quality (expressed in percent), when the file format supports it. + \note + - The filename extension tells about the desired file format. + - This method tries to save the instance image as a file, using external tools from + ImageMagick or + GraphicsMagick. + At least one of these tool must be installed for the method to succeed. + - It is recommended to use the generic method save(const char*, int) const instead, + as it can handle some file formats natively. + **/ + const CImg& save_other(const char *const filename, const unsigned int quality=100) const { + if (!filename) + throw CImgArgumentException(_cimg_instance + "save_other(): Specified filename is (null).", + cimg_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + if (_depth>1) + cimg::warn(_cimg_instance + "save_other(): File '%s', saving a volumetric image with an external call to " + "ImageMagick or GraphicsMagick only writes the first image slice.", + cimg_instance,filename); + + const unsigned int omode = cimg::exception_mode(); + bool is_saved = true; + cimg::exception_mode(0); + try { save_magick(filename); } + catch (CImgException&) { + try { save_imagemagick_external(filename,quality); } + catch (CImgException&) { + try { save_graphicsmagick_external(filename,quality); } + catch (CImgException&) { + is_saved = false; + } + } + } + cimg::exception_mode(omode); + if (!is_saved) + throw CImgIOException(_cimg_instance + "save_other(): Failed to save file '%s'. Format is not natively supported, " + "and no external commands succeeded.", + cimg_instance, + filename); + return *this; + } + + //! Serialize a CImg instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { + return CImgList(*this,true).get_serialize(is_compressed); + } + + // [internal] Return a 40x38 color logo of a 'danger' item. + static CImg _logo40x38() { + CImg res(40,38,1,3); + const unsigned char *ptrs = cimg::logo40x38; + T *ptr1 = res.data(0,0,0,0), *ptr2 = res.data(0,0,0,1), *ptr3 = res.data(0,0,0,2); + for (ulongT off = 0; off<(ulongT)res._width*res._height;) { + const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++); + for (unsigned int l = 0; l structure + # + # + # + #------------------------------------------ + */ + //! Represent a list of images CImg. + template + struct CImgList { + unsigned int _width, _allocated_width; + CImg *_data; + + //! Simple iterator type, to loop through each image of a list. + /** + \note + - The \c CImgList::iterator type is defined as a CImg*. + - You may use it like this: + \code + CImgList<> list; // Assuming this image list is not empty. + for (CImgList<>::iterator it = list.begin(); it* iterator; + + //! Simple const iterator type, to loop through each image of a \c const list instance. + /** + \note + - The \c CImgList::const_iterator type is defined to be a const CImg*. + - Similar to CImgList::iterator, but for constant list instances. + **/ + typedef const CImg* const_iterator; + + //! Pixel value type. + /** + Refer to the pixels value type of the images in the list. + \note + - The \c CImgList::value_type type of a \c CImgList is defined to be a \c T. + It is then similar to CImg::value_type. + - \c CImgList::value_type is actually not used in %CImg methods. It has been mainly defined for + compatibility with STL naming conventions. + **/ + typedef T value_type; + + // Define common types related to template type T. + typedef typename cimg::superset::type Tbool; + typedef typename cimg::superset::type Tuchar; + typedef typename cimg::superset::type Tchar; + typedef typename cimg::superset::type Tushort; + typedef typename cimg::superset::type Tshort; + typedef typename cimg::superset::type Tuint; + typedef typename cimg::superset::type Tint; + typedef typename cimg::superset::type Tulong; + typedef typename cimg::superset::type Tlong; + typedef typename cimg::superset::type Tfloat; + typedef typename cimg::superset::type Tdouble; + typedef typename cimg::last::type boolT; + typedef typename cimg::last::type ucharT; + typedef typename cimg::last::type charT; + typedef typename cimg::last::type ushortT; + typedef typename cimg::last::type shortT; + typedef typename cimg::last::type uintT; + typedef typename cimg::last::type intT; + typedef typename cimg::last::type ulongT; + typedef typename cimg::last::type longT; + typedef typename cimg::last::type uint64T; + typedef typename cimg::last::type int64T; + typedef typename cimg::last::type floatT; + typedef typename cimg::last::type doubleT; + + //@} + //--------------------------- + // + //! \name Plugins + //@{ + //--------------------------- +#ifdef cimglist_plugin +#include cimglist_plugin +#endif +#ifdef cimglist_plugin1 +#include cimglist_plugin1 +#endif +#ifdef cimglist_plugin2 +#include cimglist_plugin2 +#endif +#ifdef cimglist_plugin3 +#include cimglist_plugin3 +#endif +#ifdef cimglist_plugin4 +#include cimglist_plugin4 +#endif +#ifdef cimglist_plugin5 +#include cimglist_plugin5 +#endif +#ifdef cimglist_plugin6 +#include cimglist_plugin6 +#endif +#ifdef cimglist_plugin7 +#include cimglist_plugin7 +#endif +#ifdef cimglist_plugin8 +#include cimglist_plugin8 +#endif + + //@} + //-------------------------------------------------------- + // + //! \name Constructors / Destructor / Instance Management + //@{ + //-------------------------------------------------------- + + //! Destructor. + /** + Destroy current list instance. + \note + - Any allocated buffer is deallocated. + - Destroying an empty list does nothing actually. + **/ + ~CImgList() { + delete[] _data; + } + + //! Default constructor. + /** + Construct a new empty list instance. + \note + - An empty list has no pixel data and its dimension width() is set to \c 0, as well as its + image buffer pointer data(). + - An empty list may be reassigned afterwards, with the family of the assign() methods. + In all cases, the type of pixels stays \c T. + **/ + CImgList(): + _width(0),_allocated_width(0),_data(0) {} + + //! Construct list containing empty images. + /** + \param n Number of empty images. + \note Useful when you know by advance the number of images you want to manage, as + it will allocate the right amount of memory for the list, without needs for reallocation + (that may occur when starting from an empty list and inserting several images in it). + **/ + explicit CImgList(const unsigned int n):_width(n) { + if (n) _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + else { _allocated_width = 0; _data = 0; } + } + + //! Construct list containing images of specified size. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \note Pixel values are not initialized and may probably contain garbage. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + } + + //! Construct list containing images of specified size, and initialize pixel values. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val Initialization value for images pixels. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + } + + //! Construct list containing images of specified size, and initialize pixel values from a sequence of integers. + /** + \param n Number of images. + \param width Width of images. + \param height Height of images. + \param depth Depth of images. + \param spectrum Number of channels of images. + \param val0 First value of the initializing integers sequence. + \param val1 Second value of the initializing integers sequence. + \warning You must specify at least width*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...): + _width(0),_allocated_width(0),_data(0) { +#define _CImgList_stdarg(t) { \ + assign(n,width,height,depth,spectrum); \ + const ulongT siz = (ulongT)width*height*depth*spectrum, nsiz = siz*n; \ + T *ptrd = _data->_data; \ + va_list ap; \ + va_start(ap,val1); \ + for (ulongT l = 0, s = 0, i = 0; iwidth*height*depth*spectrum values in your argument list, + or you will probably segfault. + **/ + CImgList(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const double val0, const double val1, ...): + _width(0),_allocated_width(0),_data(0) { + _CImgList_stdarg(double); + } + + //! Construct list containing copies of an input image. + /** + \param n Number of images. + \param img Input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of \c img. + **/ + template + CImgList(const unsigned int n, const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + } + + //! Construct list from one image. + /** + \param img Input image to copy in the constructed list. + \param is_shared Tells if the element of the list is a shared or non-shared copy of \c img. + **/ + template + explicit CImgList(const CImg& img, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(1); + _data[0].assign(img,is_shared); + } + + //! Construct list from two images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + } + + //! Construct list from three images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + } + + //! Construct list from four images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + } + + //! Construct list from five images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + } + + //! Construct list from six images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + } + + //! Construct list from seven images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + } + + //! Construct list from eight images. + /** + \param img1 First input image to copy in the constructed list. + \param img2 Second input image to copy in the constructed list. + \param img3 Third input image to copy in the constructed list. + \param img4 Fourth input image to copy in the constructed list. + \param img5 Fifth input image to copy in the constructed list. + \param img6 Sixth input image to copy in the constructed list. + \param img7 Seventh input image to copy in the constructed list. + \param img8 Eighth input image to copy in the constructed list. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false): + _width(0),_allocated_width(0),_data(0) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + } + + //! Construct list copy. + /** + \param list Input list to copy. + \note The shared state of each element of the constructed list is kept the same as in \c list. + **/ + template + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + } + + //! Construct list copy \specialization. + CImgList(const CImgList& list):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],list[l]._is_shared); + } + + //! Construct list copy, and force the shared state of the list elements. + /** + \param list Input list to copy. + \param is_shared Tells if the elements of the list are shared or non-shared copies of input images. + **/ + template + CImgList(const CImgList& list, const bool is_shared):_width(0),_allocated_width(0),_data(0) { + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],is_shared); + } + + //! Construct list by reading the content of a file. + /** + \param filename Filename, as a C-string. + **/ + explicit CImgList(const char *const filename):_width(0),_allocated_width(0),_data(0) { + assign(filename); + } + + //! Construct list from the content of a display window. + /** + \param disp Display window to get content from. + \note Constructed list contains a single image only. + **/ + explicit CImgList(const CImgDisplay& disp):_width(0),_allocated_width(0),_data(0) { + assign(disp); + } + + //! Return a list with elements being shared copies of images in the list instance. + /** + \note list2 = list1.get_shared() is equivalent to list2.assign(list1,true). + **/ + CImgList get_shared() { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Return a list with elements being shared copies of images in the list instance \const. + const CImgList get_shared() const { + CImgList res(_width); + cimglist_for(*this,l) res[l].assign(_data[l],true); + return res; + } + + //! Destructor \inplace. + /** + \see CImgList(). + **/ + CImgList& assign() { + delete[] _data; + _width = _allocated_width = 0; + _data = 0; + return *this; + } + + //! Destructor \inplace. + /** + Equivalent to assign(). + \note Only here for compatibility with STL naming conventions. + **/ + CImgList& clear() { + return assign(); + } + + //! Construct list containing empty images \inplace. + /** + \see CImgList(unsigned int). + **/ + CImgList& assign(const unsigned int n) { + if (!n) return assign(); + if (_allocated_width(n<<2)) { + delete[] _data; + _data = new CImg[_allocated_width = std::max(16U,(unsigned int)cimg::nearest_pow2(n))]; + } + _width = n; + return *this; + } + + //! Construct list containing images of specified size \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height=1, + const unsigned int depth=1, const unsigned int spectrum=1) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum); + return *this; + } + + //! Construct list containing images of specified size, and initialize pixel values \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const T). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const T& val) { + assign(n); + cimglist_apply(*this,assign)(width,height,depth,spectrum,val); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of integers \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const int, const int, ...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, const int val0, const int val1, ...) { + _CImgList_stdarg(int); + return *this; + } + + //! Construct list with images of specified size, and initialize pixel values from a sequence of doubles \inplace. + /** + \see CImgList(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, const double, const double, ...). + **/ + CImgList& assign(const unsigned int n, const unsigned int width, const unsigned int height, + const unsigned int depth, const unsigned int spectrum, + const double val0, const double val1, ...) { + _CImgList_stdarg(double); + return *this; + } + + //! Construct list containing copies of an input image \inplace. + /** + \see CImgList(unsigned int, const CImg&, bool). + **/ + template + CImgList& assign(const unsigned int n, const CImg& img, const bool is_shared=false) { + assign(n); + cimglist_apply(*this,assign)(img,is_shared); + return *this; + } + + //! Construct list from one image \inplace. + /** + \see CImgList(const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img, const bool is_shared=false) { + assign(1); + _data[0].assign(img,is_shared); + return *this; + } + + //! Construct list from two images \inplace. + /** + \see CImgList(const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const bool is_shared=false) { + assign(2); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); + return *this; + } + + //! Construct list from three images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const bool is_shared=false) { + assign(3); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + return *this; + } + + //! Construct list from four images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const bool is_shared=false) { + assign(4); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); + return *this; + } + + //! Construct list from five images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const bool is_shared=false) { + assign(5); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); + return *this; + } + + //! Construct list from six images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const bool is_shared=false) { + assign(6); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + return *this; + } + + //! Construct list from seven images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const bool is_shared=false) { + assign(7); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); + return *this; + } + + //! Construct list from eight images \inplace. + /** + \see CImgList(const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, const CImg&, bool). + **/ + template + CImgList& assign(const CImg& img1, const CImg& img2, const CImg& img3, const CImg& img4, + const CImg& img5, const CImg& img6, const CImg& img7, const CImg& img8, + const bool is_shared=false) { + assign(8); + _data[0].assign(img1,is_shared); _data[1].assign(img2,is_shared); _data[2].assign(img3,is_shared); + _data[3].assign(img4,is_shared); _data[4].assign(img5,is_shared); _data[5].assign(img6,is_shared); + _data[6].assign(img7,is_shared); _data[7].assign(img8,is_shared); + return *this; + } + + //! Construct list as a copy of an existing list and force the shared state of the list elements \inplace. + /** + \see CImgList(const CImgList&, bool is_shared). + **/ + template + CImgList& assign(const CImgList& list, const bool is_shared=false) { + cimg::unused(is_shared); + assign(list._width); + cimglist_for(*this,l) _data[l].assign(list[l],false); + return *this; + } + + //! Construct list as a copy of an existing list and force shared state of elements \inplace \specialization. + CImgList& assign(const CImgList& list, const bool is_shared=false) { + if (this==&list) return *this; + CImgList res(list._width); + cimglist_for(res,l) res[l].assign(list[l],is_shared); + return res.move_to(*this); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& assign(const char *const filename) { + return load(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& assign(const CImgDisplay &disp) { + return assign(CImg(disp)); + } + + //! Transfer the content of the list instance to another list. + /** + \param list Destination list. + \note When returning, the current list instance is empty and the initial content of \c list is destroyed. + **/ + template + CImgList& move_to(CImgList& list) { + list.assign(_width); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[l]); + assign(); + return list; + } + + //! Transfer the content of the list instance at a specified position in another list. + /** + \param list Destination list. + \param pos Index of the insertion in the list. + \note When returning, the list instance is empty and the initial content of \c list is preserved + (only images indexes may be modified). + **/ + template + CImgList& move_to(CImgList& list, const unsigned int pos) { + if (is_empty()) return list; + const unsigned int npos = pos>list._width?list._width:pos; + list.insert(_width,npos); + bool is_one_shared_element = false; + cimglist_for(*this,l) is_one_shared_element|=_data[l]._is_shared; + if (is_one_shared_element) cimglist_for(*this,l) list[npos + l].assign(_data[l]); + else cimglist_for(*this,l) _data[l].move_to(list[npos + l]); + assign(); + return list; + } + + //! Swap all fields between two list instances. + /** + \param list List to swap fields with. + \note Can be used to exchange the content of two lists in a fast way. + **/ + CImgList& swap(CImgList& list) { + cimg::swap(_width,list._width,_allocated_width,list._allocated_width); + cimg::swap(_data,list._data); + return list; + } + + //! Return a reference to an empty list. + /** + \note Can be used to define default values in a function taking a CImgList as an argument. + \code + void f(const CImgList& list=CImgList::empty()); + \endcode + **/ + static CImgList& empty() { + static CImgList _empty; + return _empty.assign(); + } + + //! Return a reference to an empty list \const. + static const CImgList& const_empty() { + static const CImgList _empty; + return _empty; + } + + //@} + //------------------------------------------ + // + //! \name Overloaded Operators + //@{ + //------------------------------------------ + + //! Return a reference to one image element of the list. + /** + \param pos Indice of the image element. + **/ + CImg& operator()(const unsigned int pos) { +#if cimg_verbosity>=3 + if (pos>=_width) { + cimg::warn(_cimglist_instance + "operator(): Invalid image request, at position [%u].", + cimglist_instance, + pos); + return *_data; + } +#endif + return _data[pos]; + } + + //! Return a reference to one image of the list. + /** + \param pos Indice of the image element. + **/ + const CImg& operator()(const unsigned int pos) const { + return const_cast*>(this)->operator()(pos); + } + + //! Return a reference to one pixel value of one image of the list. + /** + \param pos Indice of the image element. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list(n,x,y,z,c) is equivalent to list[n](x,y,z,c). + **/ + T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) { + return (*this)[pos](x,y,z,c); + } + + //! Return a reference to one pixel value of one image of the list \const. + const T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0, + const unsigned int z=0, const unsigned int c=0) const { + return (*this)[pos](x,y,z,c); + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + operator CImg*() { + return _data; + } + + //! Return pointer to the first image of the list \const. + operator const CImg*() const { + return _data; + } + + //! Construct list from one image \inplace. + /** + \param img Input image to copy in the constructed list. + \note list = img; is equivalent to list.assign(img);. + **/ + template + CImgList& operator=(const CImg& img) { + return assign(img); + } + + //! Construct list from another list. + /** + \param list Input list to copy. + \note list1 = list2 is equivalent to list1.assign(list2);. + **/ + template + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list from another list \specialization. + CImgList& operator=(const CImgList& list) { + return assign(list); + } + + //! Construct list by reading the content of a file \inplace. + /** + \see CImgList(const char *const). + **/ + CImgList& operator=(const char *const filename) { + return assign(filename); + } + + //! Construct list from the content of a display window \inplace. + /** + \see CImgList(const CImgDisplay&). + **/ + CImgList& operator=(const CImgDisplay& disp) { + return assign(disp); + } + + //! Return a non-shared copy of a list. + /** + \note +list is equivalent to CImgList(list,false). + It forces the copy to have non-shared elements. + **/ + CImgList operator+() const { + return CImgList(*this,false); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end. + /** + \param img Image inserted at the end of the instance copy. + \note Define a convenient way to create temporary lists of images, as in the following code: + \code + (img1,img2,img3,img4).display("My four images"); + \endcode + **/ + template + CImgList& operator,(const CImg& img) { + return insert(img); + } + + //! Return a copy of the list instance, where image \c img has been inserted at the end \const. + template + CImgList operator,(const CImg& img) const { + return (+*this).insert(img); + } + + //! Return a copy of the list instance, where all elements of input list \c list have been inserted at the end. + /** + \param list List inserted at the end of the instance copy. + **/ + template + CImgList& operator,(const CImgList& list) { + return insert(list); + } + + //! Return a copy of the list instance, where all elements of input \c list have been inserted at the end \const. + template + CImgList& operator,(const CImgList& list) const { + return (+*this).insert(list); + } + + //! Return image corresponding to the appending of all images of the instance list along specified axis. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \note list>'x' is equivalent to list.get_append('x'). + **/ + CImg operator>(const char axis) const { + return get_append(axis,0); + } + + //! Return list corresponding to the splitting of all images of the instance list along specified axis. + /** + \param axis Axis used for image splitting. + \note list<'x' is equivalent to list.get_split('x'). + **/ + CImgList operator<(const char axis) const { + return get_split(axis); + } + + //@} + //------------------------------------- + // + //! \name Instance Characteristics + //@{ + //------------------------------------- + + //! Return the type of image pixel values as a C string. + /** + Return a \c char* string containing the usual type name of the image pixel values + (i.e. a stringified version of the template parameter \c T). + \note + - The returned string may contain spaces (as in \c "unsigned char"). + - If the pixel type \c T does not correspond to a registered type, the string "unknown" is returned. + **/ + static const char* pixel_type() { + return cimg::type::string(); + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to size() but returns result as a (signed) integer. + **/ + int width() const { + return (int)_width; + } + + //! Return the size of the list, i.e. the number of images contained in it. + /** + \note Similar to width() but returns result as an unsigned integer. + **/ + unsigned int size() const { + return _width; + } + + //! Return pointer to the first image of the list. + /** + \note Images in a list are stored as a buffer of \c CImg. + **/ + CImg *data() { + return _data; + } + + //! Return pointer to the first image of the list \const. + const CImg *data() const { + return _data; + } + + //! Return pointer to the pos-th image of the list. + /** + \param pos Indice of the image element to access. + \note list.data(n); is equivalent to list.data + n;. + **/ +#if cimg_verbosity>=3 + CImg *data(const unsigned int pos) { + if (pos>=size()) + cimg::warn(_cimglist_instance + "data(): Invalid pointer request, at position [%u].", + cimglist_instance, + pos); + return _data + pos; + } + + const CImg *data(const unsigned int l) const { + return const_cast*>(this)->data(l); + } +#else + CImg *data(const unsigned int l) { + return _data + l; + } + + //! Return pointer to the pos-th image of the list \const. + const CImg *data(const unsigned int l) const { + return _data + l; + } +#endif + + //! Return iterator to the first image of the list. + /** + **/ + iterator begin() { + return _data; + } + + //! Return iterator to the first image of the list \const. + const_iterator begin() const { + return _data; + } + + //! Return iterator to one position after the last image of the list. + /** + **/ + iterator end() { + return _data + _width; + } + + //! Return iterator to one position after the last image of the list \const. + const_iterator end() const { + return _data + _width; + } + + //! Return reference to the first image of the list. + /** + **/ + CImg& front() { + return *_data; + } + + //! Return reference to the first image of the list \const. + const CImg& front() const { + return *_data; + } + + //! Return a reference to the last image of the list. + /** + **/ + const CImg& back() const { + return *(_data + _width - 1); + } + + //! Return a reference to the last image of the list \const. + CImg& back() { + return *(_data + _width - 1); + } + + //! Return pos-th image of the list. + /** + \param pos Indice of the image element to access. + **/ + CImg& at(const int pos) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "at(): Empty instance.", + cimglist_instance); + + return _data[cimg::cut(pos,0,width() - 1)]; + } + + //! Access to pixel value with Dirichlet boundary conditions. + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=(int)_width)?(cimg::temporary(out_value)=out_value):_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=(int)_width)?out_value:_data[pos].atXYZC(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions. + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZC(p,x,y,z,c); is equivalent to list[p].atXYZC(x,y,z,c);. + **/ + T& atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions \const. + T atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZC(): Empty instance.", + cimglist_instance); + + return _atNXYZC(pos,x,y,z,c); + } + + T& _atNXYZC(const int pos, const int x, const int y, const int z, const int c) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + T _atNXYZC(const int pos, const int x, const int y, const int z, const int c) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZC(x,y,z,c); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 first coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=(int)_width)?(cimg::temporary(out_value)=out_value):_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access pixel value with Dirichlet boundary conditions for the 3 first coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=(int)_width)?out_value:_data[pos].atXYZ(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 first coordinates (\c pos, \c x,\c y,\c z). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 4 first coordinates (\c pos, \c x,\c y,\c z) \const. + T atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXYZ(): Empty instance.", + cimglist_instance); + + return _atNXYZ(pos,x,y,z,c); + } + + T& _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + T _atNXYZ(const int pos, const int x, const int y, const int z, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXYZ(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 first coordinates (\c pos, \c x,\c y). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=(int)_width)?(cimg::temporary(out_value)=out_value):_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 3 first coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=(int)_width)?out_value:_data[pos].atXY(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 first coordinates (\c pos, \c x,\c y). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 3 first coordinates (\c pos, \c x,\c y) \const. + T atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNXY(): Empty instance.", + cimglist_instance); + + return _atNXY(pos,x,y,z,c); + } + + T& _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + T _atNXY(const int pos, const int x, const int y, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atXY(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 first coordinates (\c pos,\c x). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=(int)_width)?(cimg::temporary(out_value)=out_value):_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Dirichlet boundary conditions for the 2 first coordinates (\c pos,\c x) \const. + T atNX(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=(int)_width)?out_value:_data[pos].atX(x,y,z,c,out_value); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 first coordinates (\c pos, \c x). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + //! Access to pixel value with Neumann boundary conditions for the 2 first coordinates (\c pos, \c x) \const. + T atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atNX(): Empty instance.", + cimglist_instance); + + return _atNX(pos,x,y,z,c); + } + + T& _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + T _atNX(const int pos, const int x, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)].atX(x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the first coordinate (\c pos). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \param out_value Default value returned if \c offset is outside image bounds. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) { + return (pos<0 || pos>=(int)_width)?(cimg::temporary(out_value)=out_value):(*this)(pos,x,y,z,c); + } + + //! Access to pixel value with Dirichlet boundary conditions for the first coordinate (\c pos) \const. + T atN(const int pos, const int x, const int y, const int z, const int c, const T& out_value) const { + return (pos<0 || pos>=(int)_width)?out_value:(*this)(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the first coordinate (\c pos). + /** + \param pos Indice of the image element to access. + \param x X-coordinate of the pixel value. + \param y Y-coordinate of the pixel value. + \param z Z-coordinate of the pixel value. + \param c C-coordinate of the pixel value. + \note list.atNXYZ(p,x,y,z,c); is equivalent to list[p].atXYZ(x,y,z,c);. + **/ + T& atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + //! Return pixel value with Neumann boundary conditions for the first coordinate (\c pos) \const. + T atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "atN(): Empty instance.", + cimglist_instance); + return _atN(pos,x,y,z,c); + } + + T& _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + T _atN(const int pos, const int x=0, const int y=0, const int z=0, const int c=0) const { + return _data[cimg::cut(pos,0,width() - 1)](x,y,z,c); + } + + //! Return a C-string containing the values of all images in the instance list. + /** + \param separator Character separator set between consecutive pixel values. + \param max_size Maximum size of the returned string. + \note The result is returne as a CImg image whose pixel buffer contains the desired C-string. + **/ + CImg value_string(const char separator=',', const unsigned int max_size=0) const { + if (is_empty()) return CImg(1,1,1,1,0); + CImgList items; + for (unsigned int l = 0; l<_width - 1; ++l) { + CImg item = _data[l].value_string(separator,0); + item.back() = separator; + item.move_to(items); + } + _data[_width - 1].value_string(separator,0).move_to(items); + CImg res; (items>'x').move_to(res); + if (max_size) { res.crop(0,max_size); res(max_size) = 0; } + return res; + } + + //@} + //------------------------------------- + // + //! \name Instance Checking + //@{ + //------------------------------------- + + //! Return \c true if list is empty. + /** + **/ + bool is_empty() const { + return (!_data || !_width); + } + + //! Test if number of image elements is equal to specified value. + /** + \param size_n Number of image elements to test. + **/ + bool is_sameN(const unsigned int size_n) const { + return _width==size_n; + } + + //! Test if number of image elements is equal between two images lists. + /** + \param list Input list to compare with. + **/ + template + bool is_sameN(const CImgList& list) const { + return is_sameN(list._width); + } + + // Define useful functions to check list dimensions. + // (cannot be documented because macro-generated). +#define _cimglist_def_is_same1(axis) \ + bool is_same##axis(const unsigned int val) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(val); return res; \ + } \ + bool is_sameN##axis(const unsigned int n, const unsigned int val) const { \ + return is_sameN(n) && is_same##axis(val); \ + } \ + +#define _cimglist_def_is_same2(axis1,axis2) \ + bool is_same##axis1##axis2(const unsigned int val1, const unsigned int val2) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2(val1,val2); return res; \ + } \ + bool is_sameN##axis1##axis2(const unsigned int n, const unsigned int val1, const unsigned int val2) const { \ + return is_sameN(n) && is_same##axis1##axis2(val1,val2); \ + } \ + +#define _cimglist_def_is_same3(axis1,axis2,axis3) \ + bool is_same##axis1##axis2##axis3(const unsigned int val1, const unsigned int val2, \ + const unsigned int val3) const { \ + bool res = true; \ + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis1##axis2##axis3(val1,val2,val3); \ + return res; \ + } \ + bool is_sameN##axis1##axis2##axis3(const unsigned int n, const unsigned int val1, \ + const unsigned int val2, const unsigned int val3) const { \ + return is_sameN(n) && is_same##axis1##axis2##axis3(val1,val2,val3); \ + } \ + +#define _cimglist_def_is_same(axis) \ + template bool is_same##axis(const CImg& img) const { \ + bool res = true; for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_same##axis(img); return res; \ + } \ + template bool is_same##axis(const CImgList& list) const { \ + const unsigned int lmin = std::min(_width,list._width); \ + bool res = true; for (unsigned int l = 0; l bool is_sameN##axis(const unsigned int n, const CImg& img) const { \ + return (is_sameN(n) && is_same##axis(img)); \ + } \ + template bool is_sameN##axis(const CImgList& list) const { \ + return (is_sameN(list) && is_same##axis(list)); \ + } + + _cimglist_def_is_same(XY) + _cimglist_def_is_same(XZ) + _cimglist_def_is_same(XC) + _cimglist_def_is_same(YZ) + _cimglist_def_is_same(YC) + _cimglist_def_is_same(XYZ) + _cimglist_def_is_same(XYC) + _cimglist_def_is_same(YZC) + _cimglist_def_is_same(XYZC) + _cimglist_def_is_same1(X) + _cimglist_def_is_same1(Y) + _cimglist_def_is_same1(Z) + _cimglist_def_is_same1(C) + _cimglist_def_is_same2(X,Y) + _cimglist_def_is_same2(X,Z) + _cimglist_def_is_same2(X,C) + _cimglist_def_is_same2(Y,Z) + _cimglist_def_is_same2(Y,C) + _cimglist_def_is_same2(Z,C) + _cimglist_def_is_same3(X,Y,Z) + _cimglist_def_is_same3(X,Y,C) + _cimglist_def_is_same3(X,Z,C) + _cimglist_def_is_same3(Y,Z,C) + + //! Test if dimensions of each image of the list match specified arguments. + /** + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameXYZC(const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + bool res = true; + for (unsigned int l = 0; l<_width && res; ++l) res = _data[l].is_sameXYZC(dx,dy,dz,dc); + return res; + } + + //! Test if list dimensions match specified arguments. + /** + \param n Number of images in the list. + \param dx Checked image width. + \param dy Checked image height. + \param dz Checked image depth. + \param dc Checked image spectrum. + **/ + bool is_sameNXYZC(const unsigned int n, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) const { + return is_sameN(n) && is_sameXYZC(dx,dy,dz,dc); + } + + //! Test if list contains one particular pixel location. + /** + \param n Index of the image whom checked pixel value belong to. + \param x X-coordinate of the checked pixel value. + \param y Y-coordinate of the checked pixel value. + \param z Z-coordinate of the checked pixel value. + \param c C-coordinate of the checked pixel value. + **/ + bool containsNXYZC(const int n, const int x=0, const int y=0, const int z=0, const int c=0) const { + if (is_empty()) return false; + return n>=0 && n<(int)_width && x>=0 && x<_data[n].width() && y>=0 && y<_data[n].height() && + z>=0 && z<_data[n].depth() && c>=0 && c<_data[n].spectrum(); + } + + //! Test if list contains image with specified indice. + /** + \param n Index of the checked image. + **/ + bool containsN(const int n) const { + if (is_empty()) return false; + return n>=0 && n<(int)_width; + } + + //! Test if one image of the list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \param[out] z Z-coordinate of the pixel value, if test succeeds. + \param[out] c C-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y,z,c). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y, t& z, t& c) const { + if (is_empty()) return false; + cimglist_for(*this,l) if (_data[l].contains(pixel,x,y,z,c)) { n = (t)l; return true; } + return false; + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \param[out] z Z-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y,z). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y, t& z) const { + t c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \param[out] y Y-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x,y). + **/ + template + bool contains(const T& pixel, t& n, t& x, t&y) const { + t z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \param[out] x X-coordinate of the pixel value, if test succeeds. + \note If true, set coordinates (n,x). + **/ + template + bool contains(const T& pixel, t& n, t& x) const { + t y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + \param[out] n Index of image containing the pixel value, if test succeeds. + \note If true, set coordinates (n). + **/ + template + bool contains(const T& pixel, t& n) const { + t x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if one of the image list contains the specified referenced value. + /** + \param pixel Reference to pixel value to test. + **/ + bool contains(const T& pixel) const { + unsigned int n, x, y, z, c; + return contains(pixel,n,x,y,z,c); + } + + //! Test if the list contains the image 'img'. + /** + \param img Reference to image to test. + \param[out] n Index of image in the list, if test succeeds. + \note If true, returns the position (n) of the image in the list. + **/ + template + bool contains(const CImg& img, t& n) const { + if (is_empty()) return false; + const CImg *const ptr = &img; + cimglist_for(*this,i) if (_data + i==ptr) { n = (t)i; return true; } + return false; + } + + //! Test if the list contains the image img. + /** + \param img Reference to image to test. + **/ + bool contains(const CImg& img) const { + unsigned int n; + return contains(img,n); + } + + //@} + //------------------------------------- + // + //! \name Mathematical Functions + //@{ + //------------------------------------- + + //! Return a reference to the minimum pixel value of the instance list. + /** + **/ + T& min() { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "min(): Empty instance.", + cimglist_instance); + T *ptr_min = _data->_data; + T min_value = *ptr_min; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs_data; + T min_value = *ptr_min; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs_data; + T max_value = *ptr_max; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the maximum pixel value of the instance list \const. + const T& max() const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "max(): Empty instance.", + cimglist_instance); + const T *ptr_max = _data->_data; + T max_value = *ptr_max; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) if (*ptrs>max_value) max_value = *(ptr_max=ptrs); + } + return *ptr_max; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + T& min_max(t& max_val) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "min_max(): Empty instance.", + cimglist_instance); + T *ptr_min = _data->_data; + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the maximum vvalue as well \const. + /** + \param[out] max_val Value of the maximum value found. + **/ + template + const T& min_max(t& max_val) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "min_max(): Empty instance.", + cimglist_instance); + const T *ptr_min = _data->_data; + T min_value = *ptr_min, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (valmax_value) max_value = val; + } + } + max_val = (t)max_value; + return *ptr_min; + } + + //! Return a reference to the minimum pixel value of the instance list and return the minimum value as well. + /** + \param[out] min_val Value of the minimum value found. + **/ + template + T& max_min(t& min_val) { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "max_min(): Empty instance.", + cimglist_instance); + T *ptr_max = _data->_data; + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + const T& max_min(t& min_val) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "max_min(): Empty instance.", + cimglist_instance); + const T *ptr_max = _data->_data; + T min_value = *ptr_max, max_value = min_value; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_for(img,ptrs,T) { + const T val = *ptrs; + if (val>max_value) { max_value = val; ptr_max = ptrs; } + if (val + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + if (is_shared) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified shared image " + "CImg<%s>(%u,%u,%u,%u,%p) at position %u (pixel types are different).", + cimglist_instance, + img.pixel_type(),img._width,img._height,img._depth,img._spectrum,img._data,npos); + + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list. + _data = new_data; + *_data = img; + } else { + if (new_data) { // Insert with re-allocation. + if (npos) std::memcpy(new_data,_data,sizeof(CImg)*npos); + if (npos!=_width - 1) std::memcpy(new_data + npos + 1,_data + npos,sizeof(CImg)*(_width - 1 - npos)); + std::memset(_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else if (npos!=_width - 1) // Insert without re-allocation. + std::memmove(_data + npos + 1,_data + npos,sizeof(CImg)*(_width - 1 - npos)); + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \specialization. + CImgList& insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if (npos>_width) + throw CImgArgumentException(_cimglist_instance + "insert(): Invalid insertion request of specified image (%u,%u,%u,%u,%p) " + "at position %u.", + cimglist_instance, + img._width,img._height,img._depth,img._spectrum,img._data,npos); + CImg *const new_data = (++_width>_allocated_width)?new CImg[_allocated_width?(_allocated_width<<=1): + (_allocated_width=16)]:0; + if (!_data) { // Insert new element into empty list. + _data = new_data; + if (is_shared && img) { + _data->_width = img._width; + _data->_height = img._height; + _data->_depth = img._depth; + _data->_spectrum = img._spectrum; + _data->_is_shared = true; + _data->_data = img._data; + } else *_data = img; + } + else { + if (new_data) { // Insert with re-allocation. + if (npos) std::memcpy(new_data,_data,sizeof(CImg)*npos); + if (npos!=_width - 1) std::memcpy(new_data + npos + 1,_data + npos,sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + new_data[npos]._width = img._width; + new_data[npos]._height = img._height; + new_data[npos]._depth = img._depth; + new_data[npos]._spectrum = img._spectrum; + new_data[npos]._is_shared = true; + new_data[npos]._data = img._data; + } else { + new_data[npos]._width = new_data[npos]._height = new_data[npos]._depth = new_data[npos]._spectrum = 0; + new_data[npos]._data = 0; + new_data[npos] = img; + } + std::memset(_data,0,sizeof(CImg)*(_width - 1)); + delete[] _data; + _data = new_data; + } else { // Insert without re-allocation. + if (npos!=_width - 1) std::memmove(_data + npos + 1,_data + npos,sizeof(CImg)*(_width - 1 - npos)); + if (is_shared && img) { + _data[npos]._width = img._width; + _data[npos]._height = img._height; + _data[npos]._depth = img._depth; + _data[npos]._spectrum = img._spectrum; + _data[npos]._is_shared = true; + _data[npos]._data = img._data; + } else { + _data[npos]._width = _data[npos]._height = _data[npos]._depth = _data[npos]._spectrum = 0; + _data[npos]._data = 0; + _data[npos] = img; + } + } + } + return *this; + } + + //! Insert a copy of the image \c img into the current image list, at position \c pos \newinstance. + template + CImgList get_insert(const CImg& img, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(img,pos,is_shared); + } + + //! Insert n empty images img into the current image list, at position \p pos. + /** + \param n Number of empty images to insert. + \param pos Index of the insertion. + **/ + CImgList& insert(const unsigned int n, const unsigned int pos=~0U) { + CImg empty; + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i get_insert(const unsigned int n, const unsigned int pos=~0U) const { + return (+*this).insert(n,pos); + } + + //! Insert \c n copies of the image \c img into the current image list, at position \c pos. + /** + \param n Number of image copies to insert. + \param img Image to insert by copy. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of \c img or not. + **/ + template + CImgList& insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + insert(img,npos,is_shared); + for (unsigned int i = 1; i + CImgList get_insert(const unsigned int n, const CImg& img, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,img,pos,is_shared); + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos. + /** + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) { + const unsigned int npos = pos==~0U?_width:pos; + if ((void*)this!=(void*)&list) cimglist_for(list,l) insert(list[l],npos + l,is_shared); + else insert(CImgList(list),npos,is_shared); + return *this; + } + + //! Insert a copy of the image list \c list into the current image list, starting from position \c pos \newinstance. + template + CImgList get_insert(const CImgList& list, const unsigned int pos=~0U, const bool is_shared=false) const { + return (+*this).insert(list,pos,is_shared); + } + + //! Insert n copies of the list \c list at position \c pos of the current list. + /** + \param n Number of list copies to insert. + \param list Image list to insert. + \param pos Index of the insertion. + \param is_shared Tells if inserted images are shared copies of images of \c list or not. + **/ + template + CImgList& insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) { + if (!n) return *this; + const unsigned int npos = pos==~0U?_width:pos; + for (unsigned int i = 0; i + CImgList get_insert(const unsigned int n, const CImgList& list, const unsigned int pos=~0U, + const bool is_shared=false) const { + return (+*this).insert(n,list,pos,is_shared); + } + + //! Remove all images between from indexes. + /** + \param pos1 Starting index of the removal. + \param pos2 Ending index of the removal. + **/ + CImgList& remove(const unsigned int pos1, const unsigned int pos2) { + const unsigned int + npos1 = pos1=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + else { + if (tpos2>=_width) + throw CImgArgumentException(_cimglist_instance + "remove(): Invalid remove request at positions %u->%u.", + cimglist_instance, + npos1,tpos2); + + for (unsigned int k = npos1; k<=npos2; ++k) _data[k].assign(); + const unsigned int nb = 1 + npos2 - npos1; + if (!(_width-=nb)) return assign(); + if (_width>(_allocated_width>>2) || _allocated_width<=16) { // Removing items without reallocation. + if (npos1!=_width) std::memmove(_data + npos1,_data + npos2 + 1,sizeof(CImg)*(_width - npos1)); + std::memset(_data + _width,0,sizeof(CImg)*nb); + } else { // Removing items with reallocation. + _allocated_width>>=2; + while (_allocated_width>16 && _width<(_allocated_width>>1)) _allocated_width>>=1; + CImg *const new_data = new CImg[_allocated_width]; + if (npos1) std::memcpy(new_data,_data,sizeof(CImg)*npos1); + if (npos1!=_width) std::memcpy(new_data + npos1,_data + npos2 + 1,sizeof(CImg)*(_width - npos1)); + if (_width!=_allocated_width) std::memset(new_data + _width,0,sizeof(CImg)*(_allocated_width - _width)); + std::memset(_data,0,sizeof(CImg)*(_width + nb)); + delete[] _data; + _data = new_data; + } + } + return *this; + } + + //! Remove all images between from indexes \newinstance. + CImgList get_remove(const unsigned int pos1, const unsigned int pos2) const { + return (+*this).remove(pos1,pos2); + } + + //! Remove image at index \c pos from the image list. + /** + \param pos Index of the image to remove. + **/ + CImgList& remove(const unsigned int pos) { + return remove(pos,pos); + } + + //! Remove image at index \c pos from the image list \newinstance. + CImgList get_remove(const unsigned int pos) const { + return (+*this).remove(pos); + } + + //! Remove last image. + /** + **/ + CImgList& remove() { + return remove(_width - 1); + } + + //! Remove last image \newinstance. + CImgList get_remove() const { + return (+*this).remove(); + } + + //! Reverse list order. + CImgList& reverse() { + for (unsigned int l = 0; l<_width/2; ++l) (*this)[l].swap((*this)[_width - 1 - l]); + return *this; + } + + //! Reverse list order \newinstance. + CImgList get_reverse() const { + return (+*this).reverse(); + } + + //! Return a sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList& images(const unsigned int pos0, const unsigned int pos1) { + return get_images(pos0,pos1).move_to(*this); + } + + //! Return a sublist \newinstance. + CImgList get_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l]); + return res; + } + + //! Return a shared sublist. + /** + \param pos0 Starting index of the sublist. + \param pos1 Ending index of the sublist. + **/ + CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a shared sublist \newinstance. + const CImgList get_shared_images(const unsigned int pos0, const unsigned int pos1) const { + if (pos0>pos1 || pos1>=_width) + throw CImgArgumentException(_cimglist_instance + "get_shared_images(): Specified sub-list indices (%u->%u) are out of bounds.", + cimglist_instance, + pos0,pos1); + CImgList res(pos1 - pos0 + 1); + cimglist_for(res,l) res[l].assign(_data[pos0 + l],_data[pos0 + l]?true:false); + return res; + } + + //! Return a single image which is the appending of all images of the current CImgList instance. + /** + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + CImg get_append(const char axis, const float align=0) const { + if (is_empty()) return CImg(); + if (_width==1) return +((*this)[0]); + unsigned int dx = 0, dy = 0, dz = 0, dc = 0, pos = 0; + CImg res; + switch (cimg::lowercase(axis)) { + case 'x' : { // Along the X-axis. + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx+=img._width; + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) res.draw_image(pos, + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + pos+=img._width; + } + } break; + case 'y' : { // Along the Y-axis. + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy+=img._height; + dz = std::max(dz,img._depth); + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) res.draw_image((int)(align*(dx - img._width)), + pos, + (int)(align*(dz - img._depth)), + (int)(align*(dc - img._spectrum)), + img); + pos+=img._height; + } + } break; + case 'z' : { // Along the Z-axis. + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz+=img._depth; + dc = std::max(dc,img._spectrum); + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + pos, + (int)(align*(dc - img._spectrum)), + img); + pos+=img._depth; + } + } break; + default : { // Along the C-axis. + cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) { + dx = std::max(dx,img._width); + dy = std::max(dy,img._height); + dz = std::max(dz,img._depth); + dc+=img._spectrum; + } + } + res.assign(dx,dy,dz,dc,(T)0); + if (res) cimglist_for(*this,l) { + const CImg& img = (*this)[l]; + if (img) res.draw_image((int)(align*(dx - img._width)), + (int)(align*(dy - img._height)), + (int)(align*(dz - img._depth)), + pos, + img); + pos+=img._spectrum; + } + } + } + return res; + } + + //! Return a list where each image has been split along the specified axis. + /** + \param axis Axis to split images along. + \param nb Number of spliting parts for each image. + **/ + CImgList& split(const char axis, const int nb=-1) { + return get_split(axis,nb).move_to(*this); + } + + //! Return a list where each image has been split along the specified axis \newinstance. + CImgList get_split(const char axis, const int nb=-1) const { + CImgList res; + cimglist_for(*this,l) _data[l].get_split(axis,nb).move_to(res,~0U); + return res; + } + + //! Insert image at the end of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_back(const CImg& img) { + return insert(img); + } + + //! Insert image at the front of the list. + /** + \param img Image to insert. + **/ + template + CImgList& push_front(const CImg& img) { + return insert(img,0); + } + + //! Insert list at the end of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_back(const CImgList& list) { + return insert(list); + } + + //! Insert list at the front of the current list. + /** + \param list List to insert. + **/ + template + CImgList& push_front(const CImgList& list) { + return insert(list,0); + } + + //! Remove last image. + /** + **/ + CImgList& pop_back() { + return remove(_width - 1); + } + + //! Remove first image. + /** + **/ + CImgList& pop_front() { + return remove(0); + } + + //! Remove image pointed by iterator. + /** + \param iter Iterator pointing to the image to remove. + **/ + CImgList& erase(const iterator iter) { + return remove(iter - _data); + } + + //@} + //---------------------------------- + // + //! \name Data Input + //@{ + //---------------------------------- + + //! Display a simple interactive interface to select images or sublists. + /** + \param disp Window instance to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \return A one-column vector containing the selected image indexes. + **/ + CImg 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 _select(disp,0,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + //! Display a simple interactive interface to select images or sublists. + /** + \param title Title of a new window used to display selection and user interface. + \param feature_type Can be \c false to select a single image, or \c true to select a sublist. + \param axis Axis along whom images are appended for visualization. + \param align Alignment setting when images have not all the same size. + \return A one-column vector containing the selected image indexes. + **/ + CImg get_select(const char *const title, const bool feature_type=true, + const char axis='x', const float align=0, + const bool exit_on_anykey=false) const { + CImgDisplay disp; + return _select(disp,title,feature_type,axis,align,exit_on_anykey,0,false,false,false); + } + + CImg _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.", + cimglist_instance); + + // Create image correspondence table and get list dimensions for visualization. + CImgList _indices; + unsigned int max_width = 0, max_height = 0, sum_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg& img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + if (h>max_height) max_height = h; + sum_width+=w; sum_height+=h; + if (axis=='x') CImg(w,1,1,1,(unsigned int)l).move_to(_indices); + else CImg(h,1,1,1,(unsigned int)l).move_to(_indices); + } + const CImg indices0 = _indices>'x'; + + // Create display window. + if (!disp) { + if (axis=='x') disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:0,1); + else disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:0,1); + if (!title) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else if (title) disp.set_title("%s",title); + if (resize_disp) { + if (axis=='x') disp.resize(cimg_fitscreen(sum_width,max_height,1),false); + else disp.resize(cimg_fitscreen(max_width,sum_height,1),false); + } + + const unsigned int old_normalization = disp.normalization(); + bool old_is_resized = disp.is_resized(); + disp._normalization = 0; + disp.show().set_key(0); + static const unsigned char foreground_color[] = { 255,255,255 }, background_color[] = { 0,0,0 }; + + // Enter event loop. + CImg visu0, visu; + CImg indices; + CImg positions(_width,4,1,1,-1); + int oindice0 = -1, oindice1 = -1, indice0 = -1, indice1 = -1; + bool is_clicked = false, is_selected = false, text_down = false, update_display = true; + unsigned int key = 0; + + while (!is_selected && !disp.is_closed() && !key) { + + // Create background image. + if (!visu0) { + visu0.assign(disp._width,disp._height,1,3,0); visu.assign(); + (indices0.get_resize(axis=='x'?visu0._width:visu0._height,1)).move_to(indices); + unsigned int ind = 0; + if (axis=='x') for (unsigned int x = 0; x + onexone(1,1,1,1,(T)0), + &src = _data[ind]?_data[ind]:onexone; + CImg res; + src.__get_select(disp,old_normalization,(src._width - 1)/2,(src._height - 1)/2,(src._depth - 1)/2). + move_to(res); + const unsigned int h = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,true); + res.resize(x - x0,std::max(32U,h*disp._height/max_height),1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)x0; + positions(ind,1) = positions(ind,3) = (int)(align*(visu0.height() - res.height())); + positions(ind,2)+=res._width; + positions(ind,3)+=res._height - 1; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } else for (unsigned int y = 0; y &src = _data[ind]; + const CImg + img2d = src._depth>1?src.get_projections2d((src._width - 1)/2,(src._height - 1)/2,(src._depth - 1)/2): + cimg::type::string()==cimg::type::string()?src.get_shared():src; + CImg res = old_normalization==1 || + (old_normalization==3 && cimg::type::string()!=cimg::type::string())? + CImg(img2d.get_normalize((Tuchar)0,(Tuchar)255)): + CImg(img2d); + if (res._spectrum>3) res.channels(0,2); + const unsigned int w = CImgDisplay::_fitscreen(res._width,res._height,1,128,-85,false); + res.resize(std::max(32U,w*disp._width/max_width),y - y0,1,res._spectrum==1?3:-100); + positions(ind,0) = positions(ind,2) = (int)(align*(visu0.width() - res.width())); + positions(ind,1) = positions(ind,3) = (int)y0; + positions(ind,2)+=res._width - 1; + positions(ind,3)+=res._height; + visu0.draw_image(positions(ind,0),positions(ind,1),res); + } + if (axis=='x') --positions(ind,2); else --positions(ind,3); + update_display = true; + } + + if (!visu || oindice0!=indice0 || oindice1!=indice1) { + if (indice0>=0 && indice1>=0) { + visu.assign(visu0,false); + const int indm = std::min(indice0,indice1), indM = std::max(indice0,indice1); + for (int ind = indm; ind<=indM; ++ind) if (positions(ind,0)>=0) { + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + background_color,0.2f); + if ((axis=='x' && positions(ind,2) - positions(ind,0)>=8) || + (axis!='x' && positions(ind,3) - positions(ind,1)>=8)) + visu.draw_rectangle(positions(ind,0),positions(ind,1),positions(ind,2),positions(ind,3), + foreground_color,0.9f,0xAAAAAAAA); + } + const int yt = (int)text_down?visu.height() - 13:0; + if (is_clicked) visu.draw_text(0,yt," Images #%u - #%u, Size = %u", + foreground_color,background_color,0.7f,13, + orig + indm,orig + indM,indM - indm + 1); + else visu.draw_text(0,yt," Image #%u (%u,%u,%u,%u)",foreground_color,background_color,0.7f,13, + orig + indice0, + _data[indice0]._width, + _data[indice0]._height, + _data[indice0]._depth, + _data[indice0]._spectrum); + update_display = true; + } else visu.assign(); + } + if (!visu) { visu.assign(visu0,true); update_display = true; } + if (update_display) { visu.display(disp); update_display = false; } + disp.wait(); + + // Manage user events. + const int xm = disp.mouse_x(), ym = disp.mouse_y(); + int indice = -1; + + if (xm>=0) { + indice = (int)indices(axis=='x'?xm:ym); + if (disp.button()&1) { + if (!is_clicked) { is_clicked = true; oindice0 = indice0; indice0 = indice; } + oindice1 = indice1; indice1 = indice; + if (!feature_type) is_selected = true; + } else { + if (!is_clicked) { oindice0 = oindice1 = indice0; indice0 = indice1 = indice; } + else is_selected = true; + } + } else { + if (is_clicked) { + if (!(disp.button()&1)) { is_clicked = is_selected = false; indice0 = indice1 = -1; } + else indice1 = -1; + } else indice0 = indice1 = -1; + } + + if (disp.button()&4) { is_clicked = is_selected = false; indice0 = indice1 = -1; } + if (disp.button()&2 && exit_on_rightbutton) { is_selected = true; indice1 = indice0 = -1; } + if (disp.wheel() && exit_on_wheel) is_selected = true; + + CImg filename(32); + switch (key = disp.key()) { +#if cimg_OS!=2 + case cimg::keyCTRLRIGHT : +#endif + case 0 : case cimg::keyCTRLLEFT : key = 0; break; + case cimg::keyD : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,false), + CImgDisplay::_fitscreen(3*disp.width()/2,3*disp.height()/2,1,128,-100,true),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyC : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(2*disp.width()/3,2*disp.height()/3,1),false)._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyR : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.set_fullscreen(false). + resize(cimg_fitscreen(axis=='x'?sum_width:max_width,axis=='x'?max_height:sum_height,1),false). + _is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyF : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + disp.resize(disp.screen_width(),disp.screen_height(),false).toggle_fullscreen()._is_resized = true; + disp.set_key(key,false); key = 0; visu0.assign(); + } break; + case cimg::keyS : if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.bmp",snap_number++); + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + if (visu0) { + (+visu0).draw_text(0,0," Saving snapshot... ", + foreground_color,background_color,0.7f,13).display(disp); + visu0.save(filename); + (+visu0).draw_text(0,0," Snapshot '%s' saved. ", + foreground_color,background_color,0.7f,13,filename._data).display(disp); + } + disp.set_key(key,false).wait(); key = 0; + } break; + case cimg::keyO : + if (disp.is_keyCTRLLEFT() || disp.is_keyCTRLRIGHT()) { + static unsigned int snap_number = 0; + std::FILE *file; + do { +#ifdef cimg_use_zlib + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimgz",snap_number++); +#else + cimg_snprintf(filename,filename._width,cimg_appname "_%.4u.cimg",snap_number++); +#endif + if ((file=std_fopen(filename,"r"))!=0) cimg::fclose(file); + } while (file); + (+visu0).draw_text(0,0," Saving instance... ", + foreground_color,background_color,0.7f,13).display(disp); + save(filename); + (+visu0).draw_text(0,0," Instance '%s' saved. ", + foreground_color,background_color,0.7f,13,filename._data).display(disp); + disp.set_key(key,false).wait(); key = 0; + } break; + } + if (disp.is_resized()) { disp.resize(false); visu0.assign(); } + if (ym>=0 && ym<13) { if (!text_down) { visu.assign(); text_down = true; }} + else if (ym>=visu.height() - 13) { if(text_down) { visu.assign(); text_down = false; }} + if (!exit_on_anykey && key && key!=cimg::keyESC && + (key!=cimg::keyW || (!disp.is_keyCTRLLEFT() && !disp.is_keyCTRLRIGHT()))) { + key = 0; + } + } + CImg res(1,2,1,1,-1); + if (is_selected) { + if (feature_type) res.fill(std::min(indice0,indice1),std::max(indice0,indice1)); + else res.fill(indice0); + } + if (!(disp.button()&2)) disp.set_button(); + disp._normalization = old_normalization; + disp._is_resized = old_is_resized; + disp.set_key(key); + return res; + } + + //! Load a list from a file. + /** + \param filename Filename to read data from. + **/ + CImgList& load(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load(): Specified filename is (null).", + cimglist_instance); + + if (!cimg::strncasecmp(filename,"http://",7) || !cimg::strncasecmp(filename,"https://",8)) { + CImg filename_local(256); + load(cimg::load_network(filename,filename_local)); + std::remove(filename_local); + return *this; + } + + const bool is_stdin = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + bool is_loaded = true; + try { +#ifdef cimglist_load_plugin + cimglist_load_plugin(filename); +#endif +#ifdef cimglist_load_plugin1 + cimglist_load_plugin1(filename); +#endif +#ifdef cimglist_load_plugin2 + cimglist_load_plugin2(filename); +#endif +#ifdef cimglist_load_plugin3 + cimglist_load_plugin3(filename); +#endif +#ifdef cimglist_load_plugin4 + cimglist_load_plugin4(filename); +#endif +#ifdef cimglist_load_plugin5 + cimglist_load_plugin5(filename); +#endif +#ifdef cimglist_load_plugin6 + cimglist_load_plugin6(filename); +#endif +#ifdef cimglist_load_plugin7 + cimglist_load_plugin7(filename); +#endif +#ifdef cimglist_load_plugin8 + cimglist_load_plugin8(filename); +#endif + if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) load_tiff(filename); + else if (!cimg::strcasecmp(ext,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(ext,"cimg") || + !cimg::strcasecmp(ext,"cimgz") || + !*ext) load_cimg(filename); + else if (!cimg::strcasecmp(ext,"rec") || + !cimg::strcasecmp(ext,"par")) load_parrec(filename); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) load_video(filename); + else if (!cimg::strcasecmp(ext,"gz")) load_gzip_external(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + + // If nothing loaded, try to guess file format from magic number in file. + if (!is_loaded && !is_stdin) { + std::FILE *const file = std::fopen(filename,"rb"); + if (!file) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to open file '%s'.", + cimglist_instance, + filename); + } + + const char *const f_type = cimg::ftype(file,filename); + std::fclose(file); + is_loaded = true; + try { + if (!cimg::strcasecmp(f_type,"gif")) load_gif_external(filename); + else if (!cimg::strcasecmp(f_type,"tif")) load_tiff(filename); + else is_loaded = false; + } catch (CImgIOException&) { is_loaded = false; } + } + + // If nothing loaded, try to load file as a single image. + if (!is_loaded) { + assign(1); + try { + _data->load(filename); + } catch (CImgIOException&) { + cimg::exception_mode(omode); + throw CImgIOException(_cimglist_instance + "load(): Failed to recognize format of file '%s'.", + cimglist_instance, + filename); + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load a list from a file \newinstance. + static CImgList get_load(const char *const filename) { + return CImgList().load(filename); + } + + //! Load a list from a .cimg file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_cimg(const char *const filename) { + return _load_cimg(0,filename); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename) { + return CImgList().load_cimg(filename); + } + + //! Load a list from a .cimg file. + /** + \param file File to read data from. + **/ + CImgList& load_cimg(std::FILE *const file) { + return _load_cimg(file,0); + } + + //! Load a list from a .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file) { + return CImgList().load_cimg(file); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename) { +#ifdef cimg_use_zlib +#define _cimgz_load_cimg_case(Tss) { \ + Bytef *const cbuf = new Bytef[csiz]; \ + cimg::fread(cbuf,csiz,nfile); \ + raw.assign(W,H,D,C); \ + uLongf destlen = (ulongT)raw.size()*sizeof(Tss); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,csiz); \ + delete[] cbuf; \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ +} +#else +#define _cimgz_load_cimg_case(Tss) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Unable to load compressed data from file '%s' unless zlib is enabled.", \ + cimglist_instance, \ + filename?filename:"(FILE*)"); +#endif + +#define _cimg_load_cimg_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; csiz = 0; \ + if ((err = cimg_sscanf(tmp,"%u %u %u %u #%lu",&W,&H,&D,&C,&csiz))<4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'.", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:("(FILE*)")); \ + if (W*H*D*C>0) { \ + CImg raw; \ + CImg &img = _data[l]; \ + if (err==5) _cimgz_load_cimg_case(Tss) \ + else { \ + img.assign(W,H,D,C); \ + T *ptrd = img._data; \ + for (ulongT to_read = img.size(); to_read; ) { \ + raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + const Tss *ptrs = raw._data; \ + for (ulongT off = (ulongT)raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + to_read-=raw._width; \ + } \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + + const ulongT cimg_iobuffer = (ulongT)24*1024*1024; + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N = 0, W, H, D, C; + 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; + } while (*tmp=='#' && i>=0); + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + assign(N); + _cimg_load_cimg_case("bool",bool); + _cimg_load_cimg_case("unsigned_char",unsigned char); + _cimg_load_cimg_case("uchar",unsigned char); + _cimg_load_cimg_case("char",char); + _cimg_load_cimg_case("unsigned_short",unsigned short); + _cimg_load_cimg_case("ushort",unsigned short); + _cimg_load_cimg_case("short",short); + _cimg_load_cimg_case("unsigned_int",unsigned int); + _cimg_load_cimg_case("uint",unsigned int); + _cimg_load_cimg_case("int",int); + _cimg_load_cimg_case("unsigned_long",ulongT); + _cimg_load_cimg_case("ulong",ulongT); + _cimg_load_cimg_case("long",longT); + _cimg_load_cimg_case("unsigned_int64",uint64T); + _cimg_load_cimg_case("uint64",uint64T); + _cimg_load_cimg_case("int64",int64T); + _cimg_load_cimg_case("float",float); + _cimg_load_cimg_case("double",double); + + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a sublist list from a (non compressed) .cimg file. + /** + \param filename Filename to read data from. + \param n0 Starting index of images to read (~0U for max). + \param n1 Ending index of images to read (~0U for max). + \param x0 Starting X-coordinates of image regions to read. + \param y0 Starting Y-coordinates of image regions to read. + \param z0 Starting Z-coordinates of image regions to read. + \param c0 Starting C-coordinates of image regions to read. + \param x1 Ending X-coordinates of image regions to read (~0U for max). + \param y1 Ending Y-coordinates of image regions to read (~0U for max). + \param z1 Ending Z-coordinates of image regions to read (~0U for max). + \param c1 Ending C-coordinates of image regions to read (~0U for max). + **/ + CImgList& load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(0,filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sublist list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(filename,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \overloading. + CImgList& load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return _load_cimg(file,0,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + //! Load a sub-image list from a (non compressed) .cimg file \newinstance. + static CImgList get_load_cimg(std::FILE *const file, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { + return CImgList().load_cimg(file,n0,n1,x0,y0,z0,c0,x1,y1,z1,c1); + } + + CImgList& _load_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, const unsigned int n1, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0, + const unsigned int x1, const unsigned int y1, + const unsigned int z1, const unsigned int c1) { +#define _cimg_load_cimg_case2(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l<=nn1; ++l) { \ + j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \ + W = H = D = C = 0; \ + if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \ + throw CImgIOException(_cimglist_instance \ + "load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \ + cimglist_instance, \ + W,H,D,C,l,filename?filename:"(FILE*)"); \ + if (W*H*D*C>0) { \ + if (l=W || ny0>=H || nz0>=D || nc0>=C) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const unsigned int \ + _nx1 = nx1==~0U?W - 1:nx1, \ + _ny1 = ny1==~0U?H - 1:ny1, \ + _nz1 = nz1==~0U?D - 1:nz1, \ + _nc1 = nc1==~0U?C - 1:nc1; \ + if (_nx1>=W || _ny1>=H || _nz1>=D || _nc1>=C) \ + throw CImgArgumentException(_cimglist_instance \ + "load_cimg(): Invalid specified coordinates " \ + "[%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " \ + "because image [%u] in file '%s' has size (%u,%u,%u,%u).", \ + cimglist_instance, \ + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,l,filename?filename:"(FILE*)",W,H,D,C); \ + CImg raw(1 + _nx1 - nx0); \ + CImg &img = _data[l - nn0]; \ + img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \ + T *ptrd = img._data; \ + ulongT skipvb = nc0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \ + const ulongT skipzb = nz0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \ + const ulongT skipyb = ny0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \ + const ulongT skipxb = nx0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + cimg::fread(raw._data,raw._width,nfile); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw._width); \ + const Tss *ptrs = raw._data; \ + for (unsigned int off = raw._width; off; --off) *(ptrd++) = (T)*(ptrs++); \ + const ulongT skipxe = (W - 1 - _nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const ulongT skipye = (H - 1 - _ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const ulongT skipze = (D - 1 - _nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const ulongT skipve = (C - 1 - _nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + loaded = true; \ + } + + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Specified filename is (null).", + cimglist_instance); + unsigned int + nn0 = std::min(n0,n1), nn1 = std::max(n0,n1), + nx0 = std::min(x0,x1), nx1 = std::max(x0,x1), + ny0 = std::min(y0,y1), ny1 = std::max(y0,y1), + nz0 = std::min(z0,z1), nz1 = std::max(z0,z1), + nc0 = std::min(c0,c1), nc1 = std::max(c0,c1); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool loaded = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]", + &N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + nn1 = n1==~0U?N - 1:n1; + if (nn1>=N) + throw CImgArgumentException(_cimglist_instance + "load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " + "because file '%s' contains only %u images.", + cimglist_instance, + n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,filename?filename:"(FILE*)",N); + assign(1 + nn1 - n0); + _cimg_load_cimg_case2("bool",bool); + _cimg_load_cimg_case2("unsigned_char",unsigned char); + _cimg_load_cimg_case2("uchar",unsigned char); + _cimg_load_cimg_case2("char",char); + _cimg_load_cimg_case2("unsigned_short",unsigned short); + _cimg_load_cimg_case2("ushort",unsigned short); + _cimg_load_cimg_case2("short",short); + _cimg_load_cimg_case2("unsigned_int",unsigned int); + _cimg_load_cimg_case2("uint",unsigned int); + _cimg_load_cimg_case2("int",int); + _cimg_load_cimg_case2("unsigned_long",ulongT); + _cimg_load_cimg_case2("ulong",ulongT); + _cimg_load_cimg_case2("long",longT); + _cimg_load_cimg_case2("unsigned_int64",uint64T); + _cimg_load_cimg_case2("uint64",uint64T); + _cimg_load_cimg_case2("int64",int64T); + _cimg_load_cimg_case2("float",float); + _cimg_load_cimg_case2("double",double); + if (!loaded) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_cimg(): Unsupported pixel type '%s' for file '%s'.", + cimglist_instance, + str_pixeltype._data,filename?filename:"(FILE*)"); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file. + /** + \param filename Filename to read data from. + **/ + CImgList& load_parrec(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_parrec(): Specified filename is (null).", + cimglist_instance); + + CImg body(1024), filenamepar(1024), filenamerec(1024); + *body = *filenamepar = *filenamerec = 0; + const char *const ext = cimg::split_filename(filename,body); + if (!std::strcmp(ext,"par")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.rec",body._data); + } + if (!std::strcmp(ext,"PAR")) { + std::strncpy(filenamepar,filename,filenamepar._width - 1); + cimg_snprintf(filenamerec,filenamerec._width,"%s.REC",body._data); + } + if (!std::strcmp(ext,"rec")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.par",body._data); + } + if (!std::strcmp(ext,"REC")) { + std::strncpy(filenamerec,filename,filenamerec._width - 1); + cimg_snprintf(filenamepar,filenamepar._width,"%s.PAR",body._data); + } + std::FILE *file = cimg::fopen(filenamepar,"r"); + + // Parse header file + CImgList st_slices; + CImgList st_global; + CImg line(256); *line = 0; + int err; + do { err = std::fscanf(file,"%255[^\n]%*c",line._data); } while (err!=EOF && (*line=='#' || *line=='.')); + do { + unsigned int sn,size_x,size_y,pixsize; + float rs,ri,ss; + err = std::fscanf(file,"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&size_x,&size_y,&ri,&rs,&ss); + if (err==7) { + CImg::vector((float)sn,(float)pixsize,(float)size_x,(float)size_y,ri,rs,ss,0).move_to(st_slices); + unsigned int i; for (i = 0; i::vector(size_x,size_y,sn).move_to(st_global); + else { + CImg &vec = st_global[i]; + if (size_x>vec[0]) vec[0] = size_x; + if (size_y>vec[1]) vec[1] = size_y; + vec[2] = sn; + } + st_slices[st_slices._width - 1][7] = (float)i; + } + } while (err==7); + + // Read data + std::FILE *file2 = cimg::fopen(filenamerec,"rb"); + cimglist_for(st_global,l) { + const CImg& vec = st_global[l]; + CImg(vec[0],vec[1],vec[2]).move_to(*this); + } + + cimglist_for(st_slices,l) { + const CImg& vec = st_slices[l]; + const unsigned int + sn = (unsigned int)vec[0] - 1, + pixsize = (unsigned int)vec[1], + size_x = (unsigned int)vec[2], + size_y = (unsigned int)vec[3], + imn = (unsigned int)vec[7]; + const float ri = vec[4], rs = vec[5], ss = vec[6]; + switch (pixsize) { + case 8 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 16 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + case 32 : { + CImg buf(size_x,size_y); + cimg::fread(buf._data,size_x*size_y,file2); + if (cimg::endianness()) cimg::invert_endianness(buf._data,size_x*size_y); + CImg& img = (*this)[imn]; + cimg_forXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss)); + } break; + default : + cimg::fclose(file); + cimg::fclose(file2); + throw CImgIOException(_cimglist_instance + "load_parrec(): Unsupported %d-bits pixel type for file '%s'.", + cimglist_instance, + pixsize,filename); + } + } + cimg::fclose(file); + cimg::fclose(file2); + if (!_width) + throw CImgIOException(_cimglist_instance + "load_parrec(): Failed to recognize valid PAR-REC data in file '%s'.", + cimglist_instance, + filename); + return *this; + } + + //! Load a list from a PAR/REC (Philips) file \newinstance. + static CImgList get_load_parrec(const char *const filename) { + return CImgList().load_parrec(filename); + } + + //! Load a list from a YUV image sequence file. + /** + \param filename Filename to read data from. + \param size_x Width of the images. + \param size_y Height of the images. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + \param yuv2rgb Apply YUV to RGB transformation during reading. + **/ + CImgList& load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(0,filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from a YUV image sequence file \newinstance. + static CImgList get_load_yuv(const char *const filename, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(filename,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \overloading. + CImgList& load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return _load_yuv(file,0,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb); + } + + //! Load a list from an image sequence YUV file \newinstance. + static CImgList get_load_yuv(std::FILE *const file, + const unsigned int size_x, const unsigned int size_y=1, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, const bool yuv2rgb=true) { + return CImgList().load_yuv(file,size_x,size_y,first_frame,last_frame,step_frame,yuv2rgb); + } + + CImgList& _load_yuv(std::FILE *const file, const char *const filename, + const unsigned int size_x, const unsigned int size_y, + const unsigned int first_frame, const unsigned int last_frame, + const unsigned int step_frame, const bool yuv2rgb) { + if (!filename && !file) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Specified filename is (null).", + cimglist_instance); + if (size_x%2 || size_y%2) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Invalid odd XY dimensions %ux%u in file '%s'.", + cimglist_instance, + size_x,size_y,filename?filename:"(FILE*)"); + if (!size_x || !size_y) + throw CImgArgumentException(_cimglist_instance + "load_yuv(): Invalid sequence size (%u,%u) in file '%s'.", + cimglist_instance, + size_x,size_y,filename?filename:"(FILE*)"); + + const unsigned int + nfirst_frame = first_frame tmp(size_x,size_y,1,3), UV(size_x/2,size_y/2,1,2); + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb"); + bool stop_flag = false; + int err; + if (nfirst_frame) { + err = cimg::fseek(nfile,nfirst_frame*(size_x*size_y + size_x*size_y/2),SEEK_CUR); + if (err) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "load_yuv(): File '%s' doesn't contain frame number %u.", + cimglist_instance, + filename?filename:"(FILE*)",nfirst_frame); + } + } + unsigned int frame; + for (frame = nfirst_frame; !stop_flag && frame<=nlast_frame; frame+=nstep_frame) { + tmp.fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(tmp._data),1,(ulongT)tmp._width*tmp._height,nfile); + if (err!=(int)(tmp._width*tmp._height)) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions " + "(%u,%u) are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + UV.fill(0); + // *TRY* to read the luminance part, do not replace by cimg::fread! + err = (int)std::fread((void*)(UV._data),1,(size_t)(UV.size()),nfile); + if (err!=(int)(UV.size())) { + stop_flag = true; + if (err>0) + cimg::warn(_cimglist_instance + "load_yuv(): File '%s' contains incomplete data or given image dimensions (%u,%u) " + "are incorrect.", + cimglist_instance, + filename?filename:"(FILE*)",size_x,size_y); + } else { + cimg_forXY(UV,x,y) { + const int x2 = x*2, y2 = y*2; + tmp(x2,y2,1) = tmp(x2 + 1,y2,1) = tmp(x2,y2 + 1,1) = tmp(x2 + 1,y2 + 1,1) = UV(x,y,0); + tmp(x2,y2,2) = tmp(x2 + 1,y2,2) = tmp(x2,y2 + 1,2) = tmp(x2 + 1,y2 + 1,2) = UV(x,y,1); + } + if (yuv2rgb) tmp.YCbCrtoRGB(); + insert(tmp); + if (nstep_frame>1) cimg::fseek(nfile,(nstep_frame - 1)*(size_x*size_y + size_x*size_y/2),SEEK_CUR); + } + } + } + if (stop_flag && nlast_frame!=~0U && frame!=nlast_frame) + cimg::warn(_cimglist_instance + "load_yuv(): Frame %d not reached since only %u frames were found in file '%s'.", + cimglist_instance, + nlast_frame,frame - 1,filename?filename:"(FILE*)"); + + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Load an image from a video file, using OpenCV library. + /** + \param filename Filename, as a C-string. + \param first_frame Index of the first frame to read. + \param last_frame Index of the last frame to read. + \param step_frame Step value for frame reading. + \note If step_frame==0, the current video stream is forced to be released (without any frames read). + **/ + CImgList& load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { +#ifndef cimg_use_opencv + if (first_frame || last_frame!=~0U || step_frame>1) + throw CImgArgumentException(_cimglist_instance + "load_video() : File '%s', arguments 'first_frame', 'last_frame' " + "and 'step_frame' can be only set when using OpenCV " + "(-Dcimg_use_opencv must be enabled).", + cimglist_instance,filename); + return load_ffmpeg_external(filename); +#else + static CvCapture *captures[32] = { 0 }; + static CImgList filenames(32); + static CImg positions(32,1,1,1,0); + static int last_used_index = -1; + + // Detect if a video capture already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Release stream if needed. + if (!step_frame || (index>=0 && positions[index]>first_frame)) { + if (index>=0) { + cimg::mutex(9); + cvReleaseCapture(&captures[index]); + captures[index] = 0; filenames[index].assign(); positions[index] = 0; + if (last_used_index==index) last_used_index = -1; + index = -1; + cimg::mutex(9,0); + } else + if (filename) + cimg::warn(_cimglist_instance + "load_video() : File '%s', no opened video stream associated with filename found.", + cimglist_instance,filename); + else + cimg::warn(_cimglist_instance + "load_video() : No opened video stream found.", + cimglist_instance,filename); + if (!step_frame) return *this; + } + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_video(): No already open video reader found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', no video reader slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + cimg::mutex(9); + captures[index] = cvCaptureFromFile(filename); + CImg::string(filename).move_to(filenames[index]); + positions[index] = 0; + cimg::mutex(9,0); + if (!captures[index]) { + filenames[index].assign(); + std::fclose(cimg::fopen(filename,"rb")); // Check file availability. + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to detect format of video file.", + cimglist_instance,filename); + } + } + + cimg::mutex(9); + const unsigned int nb_frames = (unsigned int)std::max(0.,cvGetCaptureProperty(captures[index], + CV_CAP_PROP_FRAME_COUNT)); + cimg::mutex(9,0); + assign(); + + // Skip frames if necessary. + bool go_on = true; + unsigned int &pos = positions[index]; + while (pos frame(src->width,src->height,1,3); + const int step = (int)(src->widthStep - 3*src->width); + const unsigned char* ptrs = (unsigned char*)src->imageData; + T *ptr_r = frame.data(0,0,0,0), *ptr_g = frame.data(0,0,0,1), *ptr_b = frame.data(0,0,0,2); + if (step>0) cimg_forY(frame,y) { + cimg_forX(frame,x) { *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); } + ptrs+=step; + } else for (ulongT siz = (ulongT)src->width*src->height; siz; --siz) { + *(ptr_b++) = (T)*(ptrs++); *(ptr_g++) = (T)*(ptrs++); *(ptr_r++) = (T)*(ptrs++); + } + frame.move_to(*this); + ++pos; + + bool skip_failed = false; + for (unsigned int i = 1; i=nb_frames)) { // Close video stream when necessary. + cimg::mutex(9); + cvReleaseCapture(&captures[index]); + captures[index] = 0; + filenames[index].assign(); + positions[index] = 0; + index = -1; + cimg::mutex(9,0); + } + + cimg::mutex(9); + last_used_index = index; + cimg::mutex(9,0); + + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_video(): File '%s', unable to locate frame %u.", + cimglist_instance,filename,first_frame); + return *this; +#endif + } + + //! Load an image from a video file, using OpenCV library \newinstance. + static CImgList get_load_video(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1) { + return CImgList().load_video(filename,first_frame,last_frame,step_frame); + } + + //! Load an image from a video file using the external tool 'ffmpeg'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_ffmpeg_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_ffmpeg_external(): Specified filename is (null).", + cimglist_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%%6d.ppm",filename_tmp._data); +#if cimg_OS!=2 + cimg_snprintf(command,command._width,"%s -i \"%s\" \"%s\" >/dev/null 2>&1", + cimg::ffmpeg_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp2)._system_strescape().data()); +#else + cimg_snprintf(command,command._width,"\"%s -i \"%s\" \"%s\"\" >NUL 2>&1", + cimg::ffmpeg_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp2)._system_strescape().data()); +#endif + cimg::system(command,0); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + unsigned int i = 1; + for (bool stop_flag = false; !stop_flag; ++i) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,i); + CImg img; + try { img.load_pnm(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + cimg::exception_mode(omode); + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_ffmpeg_external(): Failed to open file '%s' with external command 'ffmpeg'.", + cimglist_instance, + filename); + return *this; + } + + //! Load an image from a video file using the external tool 'ffmpeg' \newinstance. + static CImgList get_load_ffmpeg_external(const char *const filename) { + return CImgList().load_ffmpeg_external(filename); + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools. + /** + \param filename Filename to read data from. + \param use_graphicsmagick Tells if GraphicsMagick's tool 'gm' is used instead of ImageMagick's tool 'convert'. + **/ + CImgList& load_gif_external(const char *const filename) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "load_gif_external(): Specified filename is (null).", + cimglist_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + if (!_load_gif_external(filename,false)) + if (!_load_gif_external(filename,true)) + try { assign(CImg().load_other(filename)); } catch (CImgException&) { assign(); } + if (is_empty()) + throw CImgIOException(_cimglist_instance + "load_gif_external(): Failed to open file '%s'.", + cimglist_instance,filename); + return *this; + } + + CImgList& _load_gif_external(const char *const filename, const bool use_graphicsmagick=false) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + std::FILE *file = 0; + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.0",filename_tmp._data); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-0.png",filename_tmp._data); + if ((file=std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); +#if cimg_OS!=2 + if (use_graphicsmagick) cimg_snprintf(command,command._width,"%s convert \"%s\" \"%s.png\" >/dev/null 2>&1", + cimg::graphicsmagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + else cimg_snprintf(command,command._width,"%s \"%s\" \"%s.png\" >/dev/null 2>&1", + cimg::imagemagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); +#else + if (use_graphicsmagick) cimg_snprintf(command,command._width,"\"%s convert \"%s\" \"%s.png\"\" >NUL 2>&1", + cimg::graphicsmagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + else cimg_snprintf(command,command._width,"\"%s \"%s\" \"%s.png\"\" >NUL 2>&1", + cimg::imagemagick_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); +#endif + cimg::system(command,0); + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + assign(); + + // Try to read a single frame gif. + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png",filename_tmp._data); + CImg img; + try { img.load_png(filename_tmp2); } + catch (CImgException&) { } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + else { // Try to read animated gif. + unsigned int i = 0; + for (bool stop_flag = false; !stop_flag; ++i) { + if (use_graphicsmagick) cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s.png.%u",filename_tmp._data,i); + else cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s-%u.png",filename_tmp._data,i); + CImg img; + try { img.load_png(filename_tmp2); } + catch (CImgException&) { stop_flag = true; } + if (img) { img.move_to(*this); std::remove(filename_tmp2); } + } + } + cimg::exception_mode(omode); + return *this; + } + + //! Load gif file, using ImageMagick or GraphicsMagick's external tools \newinstance. + static CImgList get_load_gif_external(const char *const filename) { + return CImgList().load_gif_external(filename); + } + + //! Load a gzipped list, using external tool 'gunzip'. + /** + \param filename Filename to read data from. + **/ + CImgList& load_gzip_external(const char *const filename) { + if (!filename) + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Specified filename is (null).", + cimglist_instance); + std::fclose(cimg::fopen(filename,"rb")); // Check if file exists. + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file = 0; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + cimg_snprintf(command,command._width,"%s -c \"%s\" > \"%s\"", + cimg::gunzip_path(), + CImg::string(filename)._system_strescape().data(), + CImg::string(filename_tmp)._system_strescape().data()); + cimg::system(command); + if (!(file = std_fopen(filename_tmp,"rb"))) { + cimg::fclose(cimg::fopen(filename,"r")); + throw CImgIOException(_cimglist_instance + "load_gzip_external(): Failed to open file '%s'.", + cimglist_instance, + filename); + + } else cimg::fclose(file); + load(filename_tmp); + std::remove(filename_tmp); + return *this; + } + + //! Load a gzipped list, using external tool 'gunzip' \newinstance. + static CImgList get_load_gzip_external(const char *const filename) { + return CImgList().load_gzip_external(filename); + } + + //! Load a 3d object from a .OFF file. + /** + \param filename Filename to read data from. + \param[out] primitives At return, contains the list of 3d object primitives. + \param[out] colors At return, contains the list of 3d object colors. + \return List of 3d object vertices. + **/ + template + CImgList& load_off(const char *const filename, + CImgList& primitives, CImgList& colors) { + return get_load_off(filename,primitives,colors).move_to(*this); + } + + //! Load a 3d object from a .OFF file \newinstance. + template + static CImgList get_load_off(const char *const filename, + CImgList& primitives, CImgList& colors) { + return CImg().load_off(filename,primitives,colors)<'x'; + } + + //! Load images from a TIFF file. + /** + \param filename Filename to read data from. + \param first_frame Index of first image frame to read. + \param last_frame Index of last image frame to read. + \param step_frame Step applied between each frame. + **/ + CImgList& load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + float *const voxel_size=0, + CImg *const description=0) { + const unsigned int + nfirst_frame = first_frame::get_load_tiff(filename)); +#else + TIFF *tif = TIFFOpen(filename,"r"); + if (tif) { + unsigned int nb_images = 0; + do ++nb_images; while (TIFFReadDirectory(tif)); + if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images)) + cimg::warn(_cimglist_instance + "load_tiff(): Invalid specified frame range is [%u,%u] (step %u) since " + "file '%s' contains %u image(s).", + cimglist_instance, + nfirst_frame,nlast_frame,nstep_frame,filename,nb_images); + + if (nfirst_frame>=nb_images) return assign(); + if (nlast_frame>=nb_images) nlast_frame = nb_images - 1; + assign(1 + (nlast_frame - nfirst_frame)/nstep_frame); + TIFFSetDirectory(tif,0); +#if cimg_verbosity>=3 + TIFFSetWarningHandler(0); + TIFFSetErrorHandler(0); +#endif + cimglist_for(*this,l) _data[l]._load_tiff(tif,nfirst_frame + l*nstep_frame,voxel_size,description); + TIFFClose(tif); + } else throw CImgIOException(_cimglist_instance + "load_tiff(): Failed to open file '%s'.", + cimglist_instance, + filename); + return *this; +#endif + } + + //! Load a multi-page TIFF file \newinstance. + static CImgList get_load_tiff(const char *const filename, + const unsigned int first_frame=0, const unsigned int last_frame=~0U, + const unsigned int step_frame=1, + float *const voxel_size=0, + CImg *const description=0) { + return CImgList().load_tiff(filename,first_frame,last_frame,step_frame,voxel_size,description); + } + + //@} + //---------------------------------- + // + //! \name Data Output + //@{ + //---------------------------------- + + //! Print information about the list on the standard output. + /** + \param title Label set to the information displayed. + \param display_stats Tells if image statistics must be computed and displayed. + **/ + const CImgList& print(const char *const title=0, const bool display_stats=true) const { + unsigned int msiz = 0; + cimglist_for(*this,l) msiz+=_data[l].size(); + msiz*=sizeof(T); + const unsigned int mdisp = msiz<8*1024?0U:msiz<8*1024*1024?1U:2U; + CImg _title(64); + if (!title) cimg_snprintf(_title,_title._width,"CImgList<%s>",pixel_type()); + std::fprintf(cimg::output(),"%s%s%s%s: %sthis%s = %p, %ssize%s = %u/%u [%u %s], %sdata%s = (CImg<%s>*)%p", + 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,_allocated_width, + 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) std::fprintf(cimg::output(),"..%p.\n",(void*)((char*)end() - 1)); + else std::fprintf(cimg::output(),".\n"); + + char tmp[16] = { 0 }; + cimglist_for(*this,ll) { + cimg_snprintf(tmp,sizeof(tmp),"[%d]",ll); + std::fprintf(cimg::output()," "); + _data[ll].print(tmp,display_stats); + if (ll==3 && width()>8) { ll = width() - 5; std::fprintf(cimg::output()," ...\n"); } + } + std::fflush(cimg::output()); + return *this; + } + + //! Display the current CImgList instance in an existing CImgDisplay window (by reference). + /** + \param disp Reference to an existing CImgDisplay instance, where the current image list will be displayed. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignmenet. + \note This function displays the list images of the current CImgList instance into an existing + CImgDisplay window. + Images of the list are appended in a single temporarly image for visualization purposes. + The function returns immediately. + **/ + const CImgList& display(CImgDisplay &disp, const char axis='x', const float align=0) const { + disp.display(*this,axis,align); + return *this; + } + + //! Display the current CImgList instance in a new display window. + /** + \param disp Display window. + \param display_info Tells if image information are displayed on the standard output. + \param axis Alignment axis for images viewing. + \param align Apending alignment. + \note This function opens a new window with a specific title and displays the list images of the + current CImgList instance into it. + Images of the list are appended in a single temporarly image for visualization purposes. + The function returns when a key is pressed or the display window is closed by the user. + **/ + const CImgList& display(CImgDisplay &disp, const bool display_info, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + bool is_exit = false; + return _display(disp,0,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + //! Display the current CImgList instance in a new display window. + /** + \param title Title of the opening display window. + \param display_info Tells if list information must be written on standard output. + \param axis Appending axis. Can be { 'x' | 'y' | 'z' | 'c' }. + \param align Appending alignment. + **/ + const CImgList& display(const char *const title=0, const bool display_info=true, + const char axis='x', const float align=0, + unsigned int *const XYZ=0, const bool exit_on_anykey=false) const { + CImgDisplay disp; + bool is_exit = false; + return _display(disp,title,0,display_info,axis,align,XYZ,exit_on_anykey,0,true,is_exit); + } + + const CImgList& _display(CImgDisplay &disp, const char *const title, const CImgList *const titles, + const bool display_info, const char axis, const float align, unsigned int *const XYZ, + const bool exit_on_anykey, const unsigned int orig, const bool is_first_call, + bool &is_exit) const { + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "display(): Empty instance.", + cimglist_instance); + if (!disp) { + if (axis=='x') { + unsigned int sum_width = 0, max_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + sum_width+=w; + if (h>max_height) max_height = h; + } + disp.assign(cimg_fitscreen(sum_width,max_height,1),title?title:titles?titles->__display()._data:0,1); + } else { + unsigned int max_width = 0, sum_height = 0; + cimglist_for(*this,l) { + const CImg &img = _data[l]; + const unsigned int + w = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,false), + h = CImgDisplay::_fitscreen(img._width,img._height,img._depth,128,-85,true); + if (w>max_width) max_width = w; + sum_height+=h; + } + disp.assign(cimg_fitscreen(max_width,sum_height,1),title?title:titles?titles->__display()._data:0,1); + } + if (!title && !titles) disp.set_title("CImgList<%s> (%u)",pixel_type(),_width); + } else if (title) disp.set_title("%s",title); + else if (titles) disp.set_title("%s",titles->__display()._data); + const CImg dtitle = CImg::string(disp.title()); + if (display_info) print(disp.title()); + disp.show().flush(); + + if (_width==1) { + const unsigned int dw = disp._width, dh = disp._height; + if (!is_first_call) + disp.resize(cimg_fitscreen(_data[0]._width,_data[0]._height,_data[0]._depth),false); + disp.set_title("%s (%ux%ux%ux%u)", + dtitle.data(),_data[0]._width,_data[0]._height,_data[0]._depth,_data[0]._spectrum); + _data[0]._display(disp,0,false,XYZ,exit_on_anykey,!is_first_call); + if (disp.key()) is_exit = true; + disp.resize(cimg_fitscreen(dw,dh,1),false).set_title("%s",dtitle.data()); + } else { + bool disp_resize = !is_first_call; + while (!disp.is_closed() && !is_exit) { + const CImg 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; } + is_exit = true; + } else if (disp.wheel()) { // Zoom in/out. + const int wheel = disp.wheel(); + disp.set_wheel(); + if (!is_first_call && wheel<0) break; + if (wheel>0 && _width>=4) { + const unsigned int + delta = std::max(1U,(unsigned int)cimg::round(0.3*_width)), + ind0 = (unsigned int)std::max(0,s[0] - (int)delta), + ind1 = (unsigned int)std::min(width() - 1,s[0] + (int)delta); + if ((ind0!=0 || ind1!=_width - 1) && ind1 - ind0>=3) { + const CImgList sublist = get_shared_images(ind0,ind1); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(ind0,ind1); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + ind0,false,is_exit); + } + } + } else if (s[0]!=0 || s[1]!=width() - 1) { + const CImgList sublist = get_shared_images(s[0],s[1]); + CImgList t_sublist; + if (titles) t_sublist = titles->get_shared_images(s[0],s[1]); + sublist._display(disp,0,titles?&t_sublist:0,false,axis,align,XYZ,exit_on_anykey, + orig + s[0],false,is_exit); + } + disp.set_title("%s",dtitle.data()); + } + } + return *this; + } + + // [internal] Return string to describe display title. + CImg __display() const { + CImg res, str; + cimglist_for(*this,l) { + CImg::string(_data[l]).move_to(str); + if (l!=width() - 1) { + str.resize(str._width + 1,1,1,1,0); + str[str._width - 2] = ','; + str[str._width - 1] = ' '; + } + res.append(str,'x'); + } + if (!res) return CImg(1,1,1,1,0).move_to(res); + cimg::strellipsize(res,128,false); + if (_width>1) { + const unsigned int l = (unsigned int)std::strlen(res); + if (res._width<=l + 16) res.resize(l + 16,1,1,1,0); + cimg_snprintf(res._data + l,16," (#%u)",_width); + } + return res; + } + + //! Save list into a file. + /** + \param filename Filename to write data to. + \param number When positive, represents an index added to the filename. Otherwise, no number is added. + \param digits Number of digits used for adding the number to the filename. + **/ + const CImgList& save(const char *const filename, const int number=-1, const unsigned int digits=6) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save(): Specified filename is (null).", + cimglist_instance); + // Do not test for empty instances, since .cimg format is able to manage empty instances. + const bool is_stdout = *filename=='-' && (!filename[1] || filename[1]=='.'); + const char *const ext = cimg::split_filename(filename); + CImg nfilename(1024); + const char *const fn = is_stdout?filename:number>=0?cimg::number_filename(filename,number,digits,nfilename): + filename; + +#ifdef cimglist_save_plugin + cimglist_save_plugin(fn); +#endif +#ifdef cimglist_save_plugin1 + cimglist_save_plugin1(fn); +#endif +#ifdef cimglist_save_plugin2 + cimglist_save_plugin2(fn); +#endif +#ifdef cimglist_save_plugin3 + cimglist_save_plugin3(fn); +#endif +#ifdef cimglist_save_plugin4 + cimglist_save_plugin4(fn); +#endif +#ifdef cimglist_save_plugin5 + cimglist_save_plugin5(fn); +#endif +#ifdef cimglist_save_plugin6 + cimglist_save_plugin6(fn); +#endif +#ifdef cimglist_save_plugin7 + cimglist_save_plugin7(fn); +#endif +#ifdef cimglist_save_plugin8 + cimglist_save_plugin8(fn); +#endif + if (!cimg::strcasecmp(ext,"cimgz")) return save_cimg(fn,true); + else if (!cimg::strcasecmp(ext,"cimg") || !*ext) return save_cimg(fn,false); + else if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(fn,true); + else if (!cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return save_video(fn); +#ifdef cimg_use_tiff + else if (!cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff")) return save_tiff(fn); +#endif + else if (!cimg::strcasecmp(ext,"gz")) return save_gzip_external(fn); + else { + if (_width==1) _data[0].save(fn,-1); + else cimglist_for(*this,l) { _data[l].save(fn,is_stdout?-1:l); if (is_stdout) std::fputc(EOF,cimg::_stdout()); } + } + return *this; + } + + //! Tell if an image list can be saved as one single file. + /** + \param filename Filename, as a C-string. + \return \c true if the file format supports multiple images, \c false otherwise. + **/ + static bool is_saveable(const char *const filename) { + const char *const ext = cimg::split_filename(filename); + if (!cimg::strcasecmp(ext,"cimgz") || +#ifdef cimg_use_tiff + !cimg::strcasecmp(ext,"tif") || + !cimg::strcasecmp(ext,"tiff") || +#endif + !cimg::strcasecmp(ext,"yuv") || + !cimg::strcasecmp(ext,"avi") || + !cimg::strcasecmp(ext,"mov") || + !cimg::strcasecmp(ext,"asf") || + !cimg::strcasecmp(ext,"divx") || + !cimg::strcasecmp(ext,"flv") || + !cimg::strcasecmp(ext,"mpg") || + !cimg::strcasecmp(ext,"m1v") || + !cimg::strcasecmp(ext,"m2v") || + !cimg::strcasecmp(ext,"m4v") || + !cimg::strcasecmp(ext,"mjp") || + !cimg::strcasecmp(ext,"mp4") || + !cimg::strcasecmp(ext,"mkv") || + !cimg::strcasecmp(ext,"mpe") || + !cimg::strcasecmp(ext,"movie") || + !cimg::strcasecmp(ext,"ogm") || + !cimg::strcasecmp(ext,"ogg") || + !cimg::strcasecmp(ext,"ogv") || + !cimg::strcasecmp(ext,"qt") || + !cimg::strcasecmp(ext,"rm") || + !cimg::strcasecmp(ext,"vob") || + !cimg::strcasecmp(ext,"wmv") || + !cimg::strcasecmp(ext,"xvid") || + !cimg::strcasecmp(ext,"mpeg")) return true; + return false; + } + + //! Save image sequence as a GIF animated file. + /** + \param filename Filename to write data to. + \param fps Number of desired frames per second. + \param nb_loops Number of loops (\c 0 for infinite looping). + **/ + const CImgList& save_gif_external(const char *const filename, const float fps=25, + const unsigned int nb_loops=0) { + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + +#ifdef cimg_use_png +#define _cimg_save_gif_ext "png" +#else +#define _cimg_save_gif_ext "ppm" +#endif + + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001." _cimg_save_gif_ext,filename_tmp._data); + if ((file=std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u." _cimg_save_gif_ext,filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save(filename_tmp2); + else _data[l].save(filename_tmp2); + } + +#if cimg_OS!=2 + cimg_snprintf(command,command._width,"%s -delay %u -loop %u", + cimg::imagemagick_path(),(unsigned int)std::max(0.0f,cimg::round(100/fps)),nb_loops); + CImg::string(command).move_to(filenames,0); + cimg_snprintf(command,command._width,"\"%s\" >/dev/null 2>&1", + CImg::string(filename)._system_strescape().data()); + CImg::string(command).move_to(filenames); +#else + cimg_snprintf(command,command._width,"\"%s -delay %u -loop %u", + cimg::imagemagick_path(),(unsigned int)std::max(0.0f,cimg::round(100/fps)),nb_loops); + CImg::string(command).move_to(filenames,0); + cimg_snprintf(command,command._width,"\"%s\"\" >NUL 2>&1", + CImg::string(filename)._system_strescape().data()); + CImg::string(command).move_to(filenames); +#endif + CImg _command = filenames>'x'; + cimg_for(_command,p,char) if (!*p) *p = ' '; + _command.back() = 0; + + cimg::system(_command); + file = std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gif_external(): Failed to save file '%s' with external command 'convert'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for_in(*this,1,filenames._width - 1,l) std::remove(filenames[l]); + return *this; + } + + const CImgList& _save_yuv(std::FILE *const file, const char *const filename, const bool is_rgb) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_yuv(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(file,filename); return *this; } + if ((*this)[0].width()%2 || (*this)[0].height()%2) + throw CImgInstanceException(_cimglist_instance + "save_yuv(): Invalid odd instance dimensions (%u,%u) for file '%s'.", + cimglist_instance, + (*this)[0].width(),(*this)[0].height(), + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + cimglist_for(*this,l) { + CImg YCbCr((*this)[l]); + if (is_rgb) YCbCr.RGBtoYCbCr(); + cimg::fwrite(YCbCr._data,(size_t)YCbCr._width*YCbCr._height,nfile); + cimg::fwrite(YCbCr.get_resize(YCbCr._width/2, YCbCr._height/2,1,3,3).data(0,0,0,1), + (size_t)YCbCr._width*YCbCr._height/2,nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list as a YUV image sequence file. + /** + \param filename Filename to write data to. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(const char *const filename=0, const bool is_rgb=true) const { + return _save_yuv(0,filename,is_rgb); + } + + //! Save image sequence into a YUV file. + /** + \param file File to write data to. + \param is_rgb Tells if the RGB to YUV conversion must be done for saving. + **/ + const CImgList& save_yuv(std::FILE *const file, const bool is_rgb=true) const { + return _save_yuv(file,0,is_rgb); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, const bool is_compressed) const { + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "save_cimg(): Unable to save compressed data in file '%s' unless zlib is enabled, " + "saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); +#endif + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + if (std::strstr(ptype,"unsigned")==ptype) std::fprintf(nfile,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else std::fprintf(nfile,"%u %s %s_endian\n",_width,ptype,etype); + cimglist_for(*this,l) { + const CImg& img = _data[l]; + std::fprintf(nfile,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + const ulongT siz = sizeof(T)*ref.size(); + uLongf csiz = siz + siz/100 + 16; + Bytef *const cbuf = new Bytef[csiz]; + if (compress(cbuf,&csiz,(Bytef*)ref._data,siz)) + cimg::warn(_cimglist_instance + "save_cimg(): Failed to save compressed data for file '%s', saving them uncompressed.", + cimglist_instance, + filename?filename:"(FILE*)"); + else { + std::fprintf(nfile," #%lu\n",csiz); + cimg::fwrite(cbuf,csiz,nfile); + delete[] cbuf; + failed_to_compress = false; + } +#endif + } + if (failed_to_compress) { // Write in a non-compressed way. + std::fputc('\n',nfile); + cimg::fwrite(ref._data,ref.size(),nfile); + } + } else std::fputc('\n',nfile); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Save list into a .cimg file. + /** + \param filename Filename to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(const char *const filename, const bool is_compressed=false) const { + return _save_cimg(0,filename,is_compressed); + } + + //! Save list into a .cimg file. + /** + \param file File to write data to. + \param is_compressed Tells if data compression must be enabled. + **/ + const CImgList& save_cimg(std::FILE *file, const bool is_compressed=false) const { + return _save_cimg(file,0,is_compressed); + } + + const CImgList& _save_cimg(std::FILE *const file, const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { +#define _cimg_save_cimg_case(Ts,Tss) \ + if (!saved && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l0) { \ + if (l=W || y0>=H || z0>=D || c0>=D) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \ + else { \ + const CImg& img = (*this)[l - n0]; \ + const T *ptrs = img._data; \ + const unsigned int \ + x1 = x0 + img._width - 1, \ + y1 = y0 + img._height - 1, \ + z1 = z0 + img._depth - 1, \ + c1 = c0 + img._spectrum - 1, \ + nx1 = x1>=W?W - 1:x1, \ + ny1 = y1>=H?H - 1:y1, \ + nz1 = z1>=D?D - 1:z1, \ + nc1 = c1>=C?C - 1:c1; \ + CImg raw(1 + nx1 - x0); \ + const unsigned int skipvb = c0*W*H*D*sizeof(Tss); \ + if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \ + for (unsigned int v = 1 + nc1 - c0; v; --v) { \ + const unsigned int skipzb = z0*W*H*sizeof(Tss); \ + if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \ + for (unsigned int z = 1 + nz1 - z0; z; --z) { \ + const unsigned int skipyb = y0*W*sizeof(Tss); \ + if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \ + for (unsigned int y = 1 + ny1 - y0; y; --y) { \ + const unsigned int skipxb = x0*sizeof(Tss); \ + if (skipxb) cimg::fseek(nfile,skipxb,SEEK_CUR); \ + raw.assign(ptrs, raw._width); \ + ptrs+=img._width; \ + if (endian) cimg::invert_endianness(raw._data,raw._width); \ + cimg::fwrite(raw._data,raw._width,nfile); \ + const unsigned int skipxe = (W - 1 - nx1)*sizeof(Tss); \ + if (skipxe) cimg::fseek(nfile,skipxe,SEEK_CUR); \ + } \ + const unsigned int skipye = (H - 1 - ny1)*W*sizeof(Tss); \ + if (skipye) cimg::fseek(nfile,skipye,SEEK_CUR); \ + } \ + const unsigned int skipze = (D - 1 - nz1)*W*H*sizeof(Tss); \ + if (skipze) cimg::fseek(nfile,skipze,SEEK_CUR); \ + } \ + const unsigned int skipve = (C - 1 - nc1)*W*H*D*sizeof(Tss); \ + if (skipve) cimg::fseek(nfile,skipve,SEEK_CUR); \ + } \ + } \ + } \ + saved = true; \ + } + + if (!file && !filename) + throw CImgArgumentException(_cimglist_instance + "save_cimg(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_cimg(): Empty instance, for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + + std::FILE *const nfile = file?file:cimg::fopen(filename,"rb+"); + bool saved = false, endian = cimg::endianness(); + CImg tmp(256), str_pixeltype(256), str_endian(256); + *tmp = *str_pixeltype = *str_endian = 0; + unsigned int j, N, W, H, D, C; + int i, err; + j = 0; while ((i=std::fgetc(nfile))!='\n' && i!=EOF && j<256) tmp[j++] = (char)i; tmp[j] = 0; + err = cimg_sscanf(tmp,"%u%*c%255[A-Za-z64_]%*c%255[sA-Za-z_ ]",&N,str_pixeltype._data,str_endian._data); + if (err<2) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): CImg header not found in file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)"); + } + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + const unsigned int lmax = std::min(N,n0 + _width); + _cimg_save_cimg_case("bool",bool); + _cimg_save_cimg_case("unsigned_char",unsigned char); + _cimg_save_cimg_case("uchar",unsigned char); + _cimg_save_cimg_case("char",char); + _cimg_save_cimg_case("unsigned_short",unsigned short); + _cimg_save_cimg_case("ushort",unsigned short); + _cimg_save_cimg_case("short",short); + _cimg_save_cimg_case("unsigned_int",unsigned int); + _cimg_save_cimg_case("uint",unsigned int); + _cimg_save_cimg_case("int",int); + _cimg_save_cimg_case("unsigned_int64",uint64T); + _cimg_save_cimg_case("uint64",uint64T); + _cimg_save_cimg_case("int64",int64T); + _cimg_save_cimg_case("float",float); + _cimg_save_cimg_case("double",double); + if (!saved) { + if (!file) cimg::fclose(nfile); + throw CImgIOException(_cimglist_instance + "save_cimg(): Unsupported data type '%s' for file '%s'.", + cimglist_instance, + filename?filename:"(FILE*)",str_pixeltype._data); + } + if (!file) cimg::fclose(nfile); + return *this; + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param filename Filename to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(const char *const filename, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(0,filename,n0,x0,y0,z0,c0); + } + + //! Insert the image instance into into an existing .cimg file, at specified coordinates. + /** + \param file File to write data to. + \param n0 Starting index of images to write. + \param x0 Starting X-coordinates of image regions to write. + \param y0 Starting Y-coordinates of image regions to write. + \param z0 Starting Z-coordinates of image regions to write. + \param c0 Starting C-coordinates of image regions to write. + **/ + const CImgList& save_cimg(std::FILE *const file, + const unsigned int n0, + const unsigned int x0, const unsigned int y0, + const unsigned int z0, const unsigned int c0) const { + return _save_cimg(file,0,n0,x0,y0,z0,c0); + } + + static void _save_empty_cimg(std::FILE *const file, const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy, + const unsigned int dz, const unsigned int dc) { + std::FILE *const nfile = file?file:cimg::fopen(filename,"wb"); + const ulongT siz = (ulongT)dx*dy*dz*dc*sizeof(T); + std::fprintf(nfile,"%u %s\n",nb,pixel_type()); + for (unsigned int i=nb; i; --i) { + std::fprintf(nfile,"%u %u %u %u\n",dx,dy,dz,dc); + for (ulongT off = siz; off; --off) std::fputc(0,nfile); + } + if (!file) cimg::fclose(nfile); + } + + //! Save empty (non-compressed) .cimg file with specified dimensions. + /** + \param filename Filename to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(const char *const filename, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(0,filename,nb,dx,dy,dz,dc); + } + + //! Save empty .cimg file with specified dimensions. + /** + \param file File to write data to. + \param nb Number of images to write. + \param dx Width of images in the written file. + \param dy Height of images in the written file. + \param dz Depth of images in the written file. + \param dc Spectrum of images in the written file. + **/ + static void save_empty_cimg(std::FILE *const file, + const unsigned int nb, + const unsigned int dx, const unsigned int dy=1, + const unsigned int dz=1, const unsigned int dc=1) { + return _save_empty_cimg(file,0,nb,dx,dy,dz,dc); + } + + //! Save list as a TIFF file. + /** + \param filename Filename to write data to. + \param compression_type Compression mode used to write data. + **/ + const CImgList& save_tiff(const char *const filename, const unsigned int compression_type=0, + const float *const voxel_size=0, const char *const description=0, + const bool use_bigtiff=true) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_tiff(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + +#ifndef cimg_use_tiff + if (_width==1) _data[0].save_tiff(filename,compression_type,voxel_size,description,use_bigtiff); + else cimglist_for(*this,l) { + CImg nfilename(1024); + cimg::number_filename(filename,l,6,nfilename); + _data[l].save_tiff(nfilename,compression_type,voxel_size,description,use_bigtiff); + } +#else + ulongT siz = 0; + cimglist_for(*this,l) siz+=_data[l].size(); + const bool _use_bigtiff = use_bigtiff && sizeof(siz)>=8 && siz*sizeof(T)>=1UL<<31; // No bigtiff for small images. + TIFF *tif = TIFFOpen(filename,_use_bigtiff?"w8":"w4"); + if (tif) { + for (unsigned int dir = 0, l = 0; l<_width; ++l) { + const CImg& img = (*this)[l]; + cimg_forZ(img,z) img._save_tiff(tif,dir++,z,compression_type,voxel_size,description); + } + TIFFClose(tif); + } else + throw CImgIOException(_cimglist_instance + "save_tiff(): Failed to open stream for file '%s'.", + cimglist_instance, + filename); +#endif + return *this; + } + + //! Save list as a gzipped file, using external tool 'gzip'. + /** + \param filename Filename to write data to. + **/ + const CImgList& save_gzip_external(const char *const filename) const { + if (!filename) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Specified filename is (null).", + cimglist_instance); + + CImg command(1024), filename_tmp(256), body(256); + const char + *ext = cimg::split_filename(filename,body), + *ext2 = cimg::split_filename(body,0); + std::FILE *file; + do { + if (!cimg::strcasecmp(ext,"gz")) { + if (*ext2) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext2); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } else { + if (*ext) cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext); + else cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s.cimg", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + } + if ((file=std_fopen(filename_tmp,"rb"))!=0) cimg::fclose(file); + } while (file); + + if (is_saveable(body)) { + save(filename_tmp); + cimg_snprintf(command,command._width,"%s -c \"%s\" > \"%s\"", + cimg::gzip_path(), + CImg::string(filename_tmp)._system_strescape().data(), + CImg::string(filename)._system_strescape().data()); + cimg::system(command); + file = std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_gzip_external(): Failed to save file '%s' with external command 'gzip'.", + cimglist_instance, + filename); + else cimg::fclose(file); + std::remove(filename_tmp); + } else { + CImg nfilename(1024); + cimglist_for(*this,l) { + cimg::number_filename(body,l,6,nfilename); + if (*ext) cimg_sprintf(nfilename._data + std::strlen(nfilename),".%s",ext); + _data[l].save_gzip_external(nfilename); + } + } + return *this; + } + + //! Save image sequence, using the OpenCV library. + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression (See http://www.fourcc.org/codecs.php to see available codecs). + \param keep_open Tells if the video writer associated to the specified filename + must be kept open or not (to allow frames to be added in the same file afterwards). + **/ + const CImgList& save_video(const char *const filename, const unsigned int fps=25, + const char *codec=0, const bool keep_open=false) const { +#ifndef cimg_use_opencv + cimg::unused(codec,keep_open); + return save_ffmpeg_external(filename,fps); +#else + static CvVideoWriter *writers[32] = { 0 }; + static CImgList filenames(32); + static CImg sizes(32,2,1,1,0); + static int last_used_index = -1; + + // Detect if a video writer already exists for the specified filename. + cimg::mutex(9); + int index = -1; + if (filename) { + if (last_used_index>=0 && !std::strcmp(filename,filenames[last_used_index])) { + index = last_used_index; + } else cimglist_for(filenames,l) if (filenames[l] && !std::strcmp(filename,filenames[l])) { + index = l; break; + } + } else index = last_used_index; + cimg::mutex(9,0); + + // Find empty slot for capturing video stream. + if (index<0) { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_video(): No already open video writer found. You must specify a " + "non-(null) filename argument for the first call.", + cimglist_instance); + else { cimg::mutex(9); cimglist_for(filenames,l) if (!filenames[l]) { index = l; break; } cimg::mutex(9,0); } + if (index<0) + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', no video writer slots available. " + "You have to release some of your previously opened videos.", + cimglist_instance,filename); + if (is_empty()) + throw CImgInstanceException(_cimglist_instance + "save_video(): Instance list is empty.", + cimglist_instance); + const unsigned int W = _data?_data[0]._width:0, H = _data?_data[0]._height:0; + if (!W || !H) + throw CImgInstanceException(_cimglist_instance + "save_video(): Frame [0] is an empty image.", + cimglist_instance); + +#define _cimg_docase(x) ((x)>='a'&&(x)<='z'?(x) + 'A' - 'a':(x)) + const char + *const _codec = codec && *codec?codec:"mp4v", + codec0 = _cimg_docase(_codec[0]), + codec1 = _codec[0]?_cimg_docase(_codec[1]):0, + codec2 = _codec[1]?_cimg_docase(_codec[2]):0, + codec3 = _codec[2]?_cimg_docase(_codec[3]):0; + cimg::mutex(9); + writers[index] = cvCreateVideoWriter(filename,CV_FOURCC(codec0,codec1,codec2,codec3), + fps,cvSize(W,H)); + CImg::string(filename).move_to(filenames[index]); + sizes(index,0) = W; sizes(index,1) = H; + cimg::mutex(9,0); + if (!writers[index]) + throw CImgIOException(_cimglist_instance + "save_video(): File '%s', unable to initialize video writer with codec '%c%c%c%c'.", + cimglist_instance,filename, + codec0,codec1,codec2,codec3); + } + + if (!is_empty()) { + const unsigned int W = sizes(index,0), H = sizes(index,1); + cimg::mutex(9); + IplImage *ipl = cvCreateImage(cvSize(W,H),8,3); + cimglist_for(*this,l) { + CImg &src = _data[l]; + if (src.is_empty()) + cimg::warn(_cimglist_instance + "save_video(): Skip empty frame %d for file '%s'.", + cimglist_instance,l,filename); + if (src._depth>1 || src._spectrum>3) + cimg::warn(_cimglist_instance + "save_video(): Frame %u has incompatible dimension (%u,%u,%u,%u). " + "Some image data may be ignored when writing frame into video file '%s'.", + cimglist_instance,l,src._width,src._height,src._depth,src._spectrum,filename); + if (src._width==W && src._height==H && src._spectrum==3) { + const T *ptr_r = src.data(0,0,0,0), *ptr_g = src.data(0,0,0,1), *ptr_b = src.data(0,0,0,2); + char *ptrd = ipl->imageData; + cimg_forXY(src,x,y) { + *(ptrd++) = (char)*(ptr_b++); *(ptrd++) = (char)*(ptr_g++); *(ptrd++) = (char)*(ptr_r++); + } + } else { + CImg _src(src,false); + _src.channels(0,std::min(_src._spectrum - 1,2U)).resize(W,H); + _src.resize(W,H,1,3,_src._spectrum==1); + const unsigned char *ptr_r = _src.data(0,0,0,0), *ptr_g = _src.data(0,0,0,1), *ptr_b = _src.data(0,0,0,2); + char *ptrd = ipl->imageData; + cimg_forXY(_src,x,y) { + *(ptrd++) = (char)*(ptr_b++); *(ptrd++) = (char)*(ptr_g++); *(ptrd++) = (char)*(ptr_r++); + } + } + cvWriteFrame(writers[index],ipl); + } + cvReleaseImage(&ipl); + cimg::mutex(9,0); + } + + cimg::mutex(9); + if (!keep_open) { + cvReleaseVideoWriter(&writers[index]); + writers[index] = 0; + filenames[index].assign(); + sizes(index,0) = sizes(index,1) = 0; + last_used_index = -1; + } else last_used_index = index; + cimg::mutex(9,0); + + return *this; +#endif + } + + //! Save image sequence, using the external tool 'ffmpeg'. + /** + \param filename Filename to write data to. + \param fps Number of frames per second. + \param codec Type of compression. + \param bitrate Output bitrate + **/ + const CImgList& save_ffmpeg_external(const char *const filename, const unsigned int fps=25, + const char *const codec=0, const unsigned int bitrate=2048) const { + if (!filename) + throw CImgArgumentException(_cimglist_instance + "save_ffmpeg_external(): Specified filename is (null).", + cimglist_instance); + if (is_empty()) { cimg::fempty(0,filename); return *this; } + + const char + *const ext = cimg::split_filename(filename), + *const _codec = codec?codec:!cimg::strcasecmp(ext,"flv")?"flv":"mpeg2video"; + + CImg command(1024), filename_tmp(256), filename_tmp2(256); + CImgList filenames; + std::FILE *file = 0; + cimglist_for(*this,l) if (!_data[l].is_sameXYZ(_data[0])) + throw CImgInstanceException(_cimglist_instance + "save_ffmpeg_external(): Invalid instance dimensions for file '%s'.", + cimglist_instance, + filename); + do { + cimg_snprintf(filename_tmp,filename_tmp._width,"%s%c%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand()); + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_000001.ppm",filename_tmp._data); + if ((file=std_fopen(filename_tmp2,"rb"))!=0) cimg::fclose(file); + } while (file); + cimglist_for(*this,l) { + cimg_snprintf(filename_tmp2,filename_tmp2._width,"%s_%.6u.ppm",filename_tmp._data,l + 1); + CImg::string(filename_tmp2).move_to(filenames); + if (_data[l]._depth>1 || _data[l]._spectrum!=3) _data[l].get_resize(-100,-100,1,3).save_pnm(filename_tmp2); + else _data[l].save_pnm(filename_tmp2); + } +#if cimg_OS!=2 + cimg_snprintf(command,command._width,"%s -i \"%s_%%6d.ppm\" -vcodec %s -b %uk -r %u -y \"%s\" >/dev/null 2>&1", + cimg::ffmpeg_path(), + CImg::string(filename_tmp)._system_strescape().data(), + _codec,bitrate,fps, + CImg::string(filename)._system_strescape().data()); +#else + cimg_snprintf(command,command._width,"\"%s -i \"%s_%%6d.ppm\" -vcodec %s -b %uk -r %u -y \"%s\"\" >NUL 2>&1", + cimg::ffmpeg_path(), + CImg::string(filename_tmp)._system_strescape().data(), + _codec,bitrate,fps, + CImg::string(filename)._system_strescape().data()); +#endif + cimg::system(command); + file = std_fopen(filename,"rb"); + if (!file) + throw CImgIOException(_cimglist_instance + "save_ffmpeg_external(): Failed to save file '%s' with external command 'ffmpeg'.", + cimglist_instance, + filename); + else cimg::fclose(file); + cimglist_for(*this,l) std::remove(filenames[l]); + return *this; + } + + //! Serialize a CImgList instance into a raw CImg buffer. + /** + \param is_compressed tells if zlib compression must be used for serialization + (this requires 'cimg_use_zlib' been enabled). + **/ + CImg get_serialize(const bool is_compressed=false) const { +#ifndef cimg_use_zlib + if (is_compressed) + cimg::warn(_cimglist_instance + "get_serialize(): Unable to compress data unless zlib is enabled, " + "storing them uncompressed.", + cimglist_instance); +#endif + CImgList stream; + CImg tmpstr(128); + const char *const ptype = pixel_type(), *const etype = cimg::endianness()?"big":"little"; + if (std::strstr(ptype,"unsigned")==ptype) + cimg_snprintf(tmpstr,tmpstr._width,"%u unsigned_%s %s_endian\n",_width,ptype + 9,etype); + else + cimg_snprintf(tmpstr,tmpstr._width,"%u %s %s_endian\n",_width,ptype,etype); + CImg::string(tmpstr,false).move_to(stream); + cimglist_for(*this,l) { + const CImg& img = _data[l]; + cimg_snprintf(tmpstr,tmpstr._width,"%u %u %u %u",img._width,img._height,img._depth,img._spectrum); + CImg::string(tmpstr,false).move_to(stream); + if (img._data) { + CImg tmp; + if (cimg::endianness()) { tmp = img; cimg::invert_endianness(tmp._data,tmp.size()); } + const CImg& ref = cimg::endianness()?tmp:img; + bool failed_to_compress = true; + if (is_compressed) { +#ifdef cimg_use_zlib + const ulongT siz = sizeof(T)*ref.size(); + uLongf csiz = (ulongT)compressBound(siz); + Bytef *const cbuf = new Bytef[csiz]; + if (compress(cbuf,&csiz,(Bytef*)ref._data,siz)) + cimg::warn(_cimglist_instance + "get_serialize(): Failed to save compressed data, saving them uncompressed.", + cimglist_instance); + else { + cimg_snprintf(tmpstr,tmpstr._width," #%lu\n",csiz); + CImg::string(tmpstr,false).move_to(stream); + CImg(cbuf,csiz).move_to(stream); + delete[] cbuf; + failed_to_compress = false; + } +#endif + } + if (failed_to_compress) { // Write in a non-compressed way. + CImg::string("\n",false).move_to(stream); + stream.insert(1); + stream.back().assign((unsigned char*)ref._data,ref.size()*sizeof(T),1,1,1,true); + } + } else CImg::string("\n",false).move_to(stream); + } + cimglist_apply(stream,unroll)('y'); + return stream>'y'; + } + + //! Unserialize a CImg serialized buffer into a CImgList list. + template + static CImgList get_unserialize(const CImg& buffer) { +#ifdef cimg_use_zlib +#define _cimgz_unserialize_case(Tss) { \ + Bytef *cbuf = (Bytef*)stream; \ + if (sizeof(t)!=1 || cimg::type::string()==cimg::type::string()) { \ + cbuf = new Bytef[csiz]; Bytef *_cbuf = cbuf; \ + for (ulongT i = 0; i raw(W,H,D,C); \ + uLongf destlen = raw.size()*sizeof(Tss); \ + uncompress((Bytef*)raw._data,&destlen,cbuf,csiz); \ + if (!is_bytef) delete[] cbuf; \ + if (endian!=cimg::endianness()) cimg::invert_endianness(raw._data,raw.size()); \ + raw.move_to(img); \ + } +#else +#define _cimgz_unserialize_case(Tss) \ + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Unable to unserialize compressed data " \ + "unless zlib is enabled.", \ + pixel_type()); +#endif + +#define _cimg_unserialize_case(Ts,Tss) \ + if (!loaded && !cimg::strcasecmp(Ts,str_pixeltype)) { \ + for (unsigned int l = 0; l::unserialize(): Invalid specified size (%u,%u,%u,%u) for " \ + "image #%u in serialized buffer.", \ + pixel_type(),W,H,D,C,l); \ + if (W*H*D*C>0) { \ + CImg &img = res._data[l]; \ + if (err==5) _cimgz_unserialize_case(Tss) \ + else { \ + if (sizeof(t)!=1) { \ + CImg raw(W*sizeof(Tss),H,D,C); \ + cimg_for(raw,p,unsigned char) *p = (unsigned char)*(stream++); \ + img.assign((Tss*)raw._data,W,H,D,C); \ + } else img.assign((Tss*)stream,W,H,D,C); \ + if (endian!=cimg::endianness()) cimg::invert_endianness(img._data,img.size()); \ + } \ + } \ + } \ + loaded = true; \ + } + + if (buffer.is_empty()) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Specified serialized buffer is (null).", + pixel_type()); + CImgList res; + const t *stream = buffer._data, *const estream = buffer._data + buffer.size(); + bool loaded = false, endian = cimg::endianness(), is_bytef = false; + CImg 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; + int i, err; + cimg::unused(is_bytef); + do { + j = 0; while ((i=(int)*stream)!='\n' && stream::get_unserialize(): CImg header not found in serialized buffer.", + pixel_type()); + if (!cimg::strncasecmp("little",str_endian,6)) endian = false; + else if (!cimg::strncasecmp("big",str_endian,3)) endian = true; + res.assign(N); + _cimg_unserialize_case("bool",bool); + _cimg_unserialize_case("unsigned_char",unsigned char); + _cimg_unserialize_case("uchar",unsigned char); + _cimg_unserialize_case("char",char); + _cimg_unserialize_case("unsigned_short",unsigned short); + _cimg_unserialize_case("ushort",unsigned short); + _cimg_unserialize_case("short",short); + _cimg_unserialize_case("unsigned_int",unsigned int); + _cimg_unserialize_case("uint",unsigned int); + _cimg_unserialize_case("int",int); + _cimg_unserialize_case("unsigned_int64",uint64T); + _cimg_unserialize_case("uint64",uint64T); + _cimg_unserialize_case("int64",int64T); + _cimg_unserialize_case("float",float); + _cimg_unserialize_case("double",double); + if (!loaded) + throw CImgArgumentException("CImgList<%s>::get_unserialize(): Unsupported pixel type '%s' defined " + "in serialized buffer.", + pixel_type(),str_pixeltype._data); + return res; + } + + //@} + //---------------------------------- + // + //! \name Others + //@{ + //---------------------------------- + + //! Crop font along the X-axis. + /** + **/ + CImgList& crop_font() { + return get_crop_font().move_to(*this); + } + + //! Crop font along the X-axis \newinstance. + /** + **/ + CImgList get_crop_font() const { + CImgList res; + cimglist_for(*this,l) { + const CImg& letter = (*this)[l]; + int xmin = letter.width(), xmax = 0; + cimg_forXY(letter,x,y) if (letter(x,y)) { if (xxmax) xmax = x; } + if (xmin>xmax) CImg(letter._width,letter._height,1,letter._spectrum,0).move_to(res); + else letter.get_crop(xmin,0,xmax,letter._height - 1).move_to(res); + } + res[' '].resize(res['f']._width,-100,-100,-100,0); + if (' ' + 256& font(const unsigned int font_height, const bool is_variable_width=true) { + if (!font_height) return CImgList::const_empty(); + cimg::mutex(11); + + // Decompress nearest base font data if needed. + static const char *data_fonts[] = { cimg::data_font12x13, cimg::data_font20x23, cimg::data_font47x53, 0 }; + static const unsigned int data_widths[] = { 12,20,47,90 }, data_heights[] = { 13,23,53,103 }, + data_Ms[] = { 86,79,57,47 }; + const unsigned int data_ind = font_height<=13U?0U:font_height<=23U?1U:font_height<=53U?2U:3U; + static CImg base_fonts[4]; + CImg &base_font = base_fonts[data_ind]; + if (!base_font) { + const unsigned int w = data_widths[data_ind], h = data_heights[data_ind], M = data_Ms[data_ind]; + base_font.assign(256*w,h); + const char *data_font = data_fonts[data_ind]; + unsigned char *ptrd = base_font; + const unsigned char *const ptrde = base_font.end(); + + // Special case needed for 90x103 to avoid MS compiler limit with big strings. + CImg data90x103; + if (!data_font) { + ((CImg(cimg::_data_font90x103[0], + (unsigned int)std::strlen(cimg::_data_font90x103[0]),1,1,1,true), + CImg(cimg::_data_font90x103[1], + (unsigned int)std::strlen(cimg::_data_font90x103[1]) + 1,1,1,1,true))>'x'). + move_to(data90x103); + data_font = data90x103.data(); + } + + // Uncompress font data (decode RLE). + for (const char *ptrs = data_font; *ptrs; ++ptrs) { + const int c = (int)(*ptrs - M - 32), v = c>=0?255:0, n = c>=0?c:-c; + if (ptrd + n<=ptrde) { std::memset(ptrd,v,n); ptrd+=n; } + else { std::memset(ptrd,v,ptrde - ptrd); break; } + } + } + + // Find optimal font cache location to return. + static CImgList fonts[16]; + static bool is_variable_widths[16] = { 0 }; + unsigned int ind = ~0U; + for (int i = 0; i<16; ++i) + if (!fonts[i] || (is_variable_widths[i]==is_variable_width && font_height==fonts[i][0]._height)) { + ind = (unsigned int)i; break; // Found empty slot or cached font. + } + if (ind==~0U) { // No empty slots nor existing font in cache. + fonts->assign(); + std::memmove(fonts,fonts + 1,15*sizeof(CImgList)); + std::memmove(is_variable_widths,is_variable_widths + 1,15*sizeof(bool)); + std::memset(fonts + (ind=15),0,sizeof(CImgList)); // Free a slot in cache for new font. + } + CImgList &font = fonts[ind]; + + // Render requested font. + if (!font) { + const unsigned int padding_x = font_height<33U?1U:font_height<53U?2U:font_height<103U?3U:4U; + is_variable_widths[ind] = is_variable_width; + font = base_font.get_split('x',256); + if (font_height!=font[0]._height) + cimglist_for(font,l) + font[l].resize(std::max(1U,font[l]._width*font_height/font[l]._height),font_height,-100,-100, + font[0]._height>font_height?2:5); + if (is_variable_width) font.crop_font(); + cimglist_for(font,l) font[l].resize(font[l]._width + padding_x,-100,1,1,0,0,0.5); + font.insert(256,0); + cimglist_for_in(font,0,255,l) font[l].assign(font[l + 256]._width,font[l + 256]._height,1,3,1); + } + cimg::mutex(11,0); + return font; + } + + //! Compute a 1d Fast Fourier Transform, along specified axis. + /** + \param axis Axis along which the Fourier transform is computed. + \param invert Tells if the direct (\c false) or inverse transform (\c true) is computed. + **/ + CImgList& FFT(const char axis, const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + + CImg::FFT(_data[0],_data[1],axis,invert); + return *this; + } + + //! Compute a 1-D Fast Fourier Transform, along specified axis \newinstance. + CImgList get_FFT(const char axis, const bool invert=false) const { + return CImgList(*this,false).FFT(axis,invert); + } + + //! Compute a n-d Fast Fourier Transform. + /** + \param invert Tells if the direct (\c false) or inverse transform (\c true) is computed. + **/ + CImgList& FFT(const bool invert=false) { + if (is_empty()) return *this; + if (_width==1) insert(1); + if (_width>2) + cimg::warn(_cimglist_instance + "FFT(): Instance has more than 2 images", + cimglist_instance); + + CImg::FFT(_data[0],_data[1],invert); + return *this; + } + + //! Compute a n-d Fast Fourier Transform \newinstance. + CImgList get_FFT(const bool invert=false) const { + return CImgList(*this,false).FFT(invert); + } + + //! Reverse primitives orientations of a 3d object. + /** + **/ + CImgList& reverse_object3d() { + cimglist_for(*this,l) { + CImg& p = _data[l]; + switch (p.size()) { + case 2 : case 3: cimg::swap(p[0],p[1]); break; + case 6 : cimg::swap(p[0],p[1],p[2],p[4],p[3],p[5]); break; + case 9 : cimg::swap(p[0],p[1],p[3],p[5],p[4],p[6]); break; + case 4 : cimg::swap(p[0],p[1],p[2],p[3]); break; + case 12 : cimg::swap(p[0],p[1],p[2],p[3],p[4],p[6],p[5],p[7],p[8],p[10],p[9],p[11]); break; + } + } + return *this; + } + + //! Reverse primitives orientations of a 3d object \newinstance. + CImgList get_reverse_object3d() const { + return (+*this).reverse_object3d(); + } + + //@} + }; // struct CImgList { ... + + /* + #--------------------------------------------- + # + # Completion of previously declared functions + # + #---------------------------------------------- + */ + +namespace cimg { + + // Functions to return standard streams 'stdin', 'stdout' and 'stderr'. + // (throw a CImgIOException when macro 'cimg_use_r' is defined). + inline FILE* _stdin() { +#ifndef cimg_use_r + return stdin; +#else + cimg::exception_mode(0); + throw CImgIOException("cimg::stdin(): Reference to 'stdin' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + return 0; +#endif + } + + inline FILE* _stdout() { +#ifndef cimg_use_r + return stdout; +#else + cimg::exception_mode(0); + throw CImgIOException("cimg::stdout(): Reference to 'stdout' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + return 0; +#endif + } + + inline FILE* _stderr() { +#ifndef cimg_use_r + return stderr; +#else + cimg::exception_mode(0); + throw CImgIOException("cimg::stderr(): Reference to 'stderr' stream not allowed in R mode " + "('cimg_use_r' is defined)."); + return 0; +#endif + } + + // Open a file (with wide character support on Windows). + inline std::FILE *win_fopen(const char *const path, const char *const mode) { +#if cimg_OS==2 + // Convert 'path' to a wide-character string. + int err = MultiByteToWideChar(CP_UTF8,0,path,-1,0,0); + if (!err) return std_fopen(path,mode); + CImg wpath(err); + err = MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,err); + if (!err) return std_fopen(path,mode); + + // Convert 'mode' to a wide-character string. + err = MultiByteToWideChar(CP_UTF8,0,mode,-1,0,0); + if (!err) return std_fopen(path,mode); + CImg wmode(err); + err = MultiByteToWideChar(CP_UTF8,0,mode,-1,wmode,err); + if (!err) return std_fopen(path,mode); + + return _wfopen(wpath,wmode); +#else + return std_fopen(path,mode); +#endif + } + + //! Get/set path to store temporary files. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path where temporary files can be saved. + **/ + inline const char* temporary_path(const char *const user_path, const bool reinit_path) { +#define _cimg_test_temporary_path(p) \ + if (!path_found) { \ + cimg_snprintf(s_path,s_path.width(),"%s",p); \ + cimg_snprintf(tmp,tmp._width,"%s%c%s",s_path.data(),cimg_file_separator,filename_tmp._data); \ + if ((file=std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } \ + } + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + CImg tmp(1024), filename_tmp(256); + std::FILE *file = 0; + cimg_snprintf(filename_tmp,filename_tmp._width,"%s.tmp",cimg::filenamerand()); + char *tmpPath = std::getenv("TMP"); + if (!tmpPath) { tmpPath = std::getenv("TEMP"); winformat_string(tmpPath); } + if (tmpPath) _cimg_test_temporary_path(tmpPath); +#if cimg_OS==2 + _cimg_test_temporary_path("C:\\WINNT\\Temp"); + _cimg_test_temporary_path("C:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("C:\\Temp"); + _cimg_test_temporary_path("C:"); + _cimg_test_temporary_path("D:\\WINNT\\Temp"); + _cimg_test_temporary_path("D:\\WINDOWS\\Temp"); + _cimg_test_temporary_path("D:\\Temp"); + _cimg_test_temporary_path("D:"); +#else + _cimg_test_temporary_path("/tmp"); + _cimg_test_temporary_path("/var/tmp"); +#endif + if (!path_found) { + *s_path = 0; + std::strncpy(tmp,filename_tmp,tmp._width - 1); + if ((file=std_fopen(tmp,"wb"))!=0) { cimg::fclose(file); std::remove(tmp); path_found = true; } + } + if (!path_found) { + cimg::mutex(7,0); + throw CImgIOException("cimg::temporary_path(): Failed to locate path for writing temporary files.\n"); + } + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the Program Files/ directory (Windows only). + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the program files. + **/ +#if cimg_OS==2 + inline const char* programfiles_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(MAX_PATH); + *s_path = 0; + // Note: in the following line, 0x26 = CSIDL_PROGRAM_FILES (not defined on every compiler). +#if !defined(__INTEL_COMPILER) + if (!SHGetSpecialFolderPathA(0,s_path,0x0026,false)) { + const char *const pfPath = std::getenv("PROGRAMFILES"); + if (pfPath) std::strncpy(s_path,pfPath,MAX_PATH - 1); + else std::strcpy(s_path,"C:\\PROGRA~1"); + } +#else + std::strcpy(s_path,"C:\\PROGRA~1"); +#endif + } + cimg::mutex(7,0); + return s_path; + } +#endif + + //! Get/set path to the ImageMagick's \c convert binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c convert binary. + **/ + inline const char* imagemagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + const char *const pf_path = programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\convert.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\convert.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\convert.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\convert.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%.2d-\\VISUA~1\\BIN\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d-Q\\VISUA~1\\BIN\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\IMAGEM~1.%d\\VISUA~1\\BIN\\convert.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"convert.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./convert"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"convert"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the GraphicsMagick's \c gm binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gm binary. + **/ + inline const char* graphicsmagick_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + const char *const pf_path = programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\gm.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\gm.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\gm.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\gm.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"%s\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",pf_path,k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"C:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=10 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%.2d-\\VISUA~1\\BIN\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 9; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d-Q\\VISUA~1\\BIN\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + for (int k = 32; k>=0 && !path_found; --k) { + cimg_snprintf(s_path,s_path._width,"D:\\GRAPHI~1.%d\\VISUA~1\\BIN\\gm.exe",k); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gm"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gm"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the XMedcon's \c medcon binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c medcon binary. + **/ + inline const char* medcon_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + const char *const pf_path = programfiles_path(); + if (!path_found) { + std::strcpy(s_path,".\\medcon.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.bat",pf_path); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + cimg_snprintf(s_path,s_path._width,"%s\\XMedCon\\bin\\medcon.exe",pf_path); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) { + std::strcpy(s_path,"C:\\XMedCon\\bin\\medcon.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./medcon"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"medcon"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the FFMPEG's \c ffmpeg binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c ffmpeg binary. + **/ + inline const char *ffmpeg_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (!path_found) { + std::strcpy(s_path,".\\ffmpeg.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"ffmpeg.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./ffmpeg"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"ffmpeg"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gzip binary. + **/ + inline const char *gzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (!path_found) { + std::strcpy(s_path,".\\gzip.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gzip"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c gunzip binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c gunzip binary. + **/ + inline const char *gunzip_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (!path_found) { + std::strcpy(s_path,".\\gunzip.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./gunzip"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"gunzip"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c dcraw binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c dcraw binary. + **/ + inline const char *dcraw_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (!path_found) { + std::strcpy(s_path,".\\dcraw.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./dcraw"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"dcraw"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c wget binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c wget binary. + **/ + inline const char *wget_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (!path_found) { + std::strcpy(s_path,".\\wget.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./wget"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"wget"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + //! Get/set path to the \c curl binary. + /** + \param user_path Specified path, or \c 0 to get the path currently used. + \param reinit_path Force path to be recalculated (may take some time). + \return Path containing the \c curl binary. + **/ + inline const char *curl_path(const char *const user_path, const bool reinit_path) { + static CImg s_path; + cimg::mutex(7); + if (reinit_path) s_path.assign(); + if (user_path) { + if (!s_path) s_path.assign(1024); + std::strncpy(s_path,user_path,1023); + } else if (!s_path) { + s_path.assign(1024); + bool path_found = false; + std::FILE *file = 0; +#if cimg_OS==2 + if (!path_found) { + std::strcpy(s_path,".\\curl.exe"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl.exe"); +#else + if (!path_found) { + std::strcpy(s_path,"./curl"); + if ((file=std_fopen(s_path,"r"))!=0) { cimg::fclose(file); path_found = true; } + } + if (!path_found) std::strcpy(s_path,"curl"); +#endif + winformat_string(s_path); + } + cimg::mutex(7,0); + return s_path; + } + + // [internal] Sorting function, used by cimg::files(). + inline int _sort_files(const void* a, const void* b) { + const CImg &sa = *(CImg*)a, &sb = *(CImg*)b; + return std::strcmp(sa._data,sb._data); + } + + //! Return list of files/directories in specified directory. + /** + \param path Path to the directory. Set to 0 for current directory. + \param is_pattern Tell if specified path has a matching pattern in it. + \param mode Output type, can be primary { 0=files only | 1=folders only | 2=files + folders }. + \param include_path Tell if \c path must be included in resulting filenames. + \return A list of filenames. + **/ + inline CImgList files(const char *const path, const bool is_pattern=false, + const unsigned int mode=2, const bool include_path=false) { + if (!path || !*path) return files("*",true,mode,include_path); + CImgList res; + + // If path is a valid folder name, ignore argument 'is_pattern'. + const bool _is_pattern = is_pattern && !cimg::is_directory(path); + bool is_root = false, is_current = false; + cimg::unused(is_root,is_current); + + // Clean format of input path. + CImg pattern, _path = CImg::string(path); +#if cimg_OS==2 + for (char *ps = _path; *ps; ++ps) if (*ps=='\\') *ps='/'; +#endif + char *pd = _path; + for (char *ps = pd; *ps; ++ps) { if (*ps!='/' || *ps!=*(ps+1)) *(pd++) = *ps; } + *pd = 0; + unsigned int lp = (unsigned int)std::strlen(_path); + if (!_is_pattern && lp && _path[lp - 1]=='/') { + _path[lp - 1] = 0; --lp; +#if cimg_OS!=2 + is_root = !*_path; +#endif + } + + // Separate folder path and matching pattern. + if (_is_pattern) { + const unsigned int bpos = (unsigned int)(cimg::basename(_path,'/') - _path.data()); + CImg::string(_path).move_to(pattern); + if (bpos) { + _path[bpos - 1] = 0; // End 'path' at last slash. +#if cimg_OS!=2 + is_root = !*_path; +#endif + } else { // No path to folder specified, assuming current folder. + is_current = true; *_path = 0; + } + lp = (unsigned int)std::strlen(_path); + } + + // Windows version. +#if cimg_OS==2 + if (!_is_pattern) { + pattern.assign(lp + 3); + std::memcpy(pattern,_path,lp); + pattern[lp] = '/'; pattern[lp + 1] = '*'; pattern[lp + 2] = 0; + } + WIN32_FIND_DATAA file_data; + const HANDLE dir = FindFirstFileA(pattern.data(),&file_data); + if (dir==INVALID_HANDLE_VALUE) return CImgList::const_empty(); + do { + const char *const filename = file_data.cFileName; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode>=2) { + if (include_path) { + CImg full_filename((lp?lp+1:0) + lf + 1); + if (lp) { std::memcpy(full_filename,_path,lp); full_filename[lp] = '/'; } + std::memcpy(full_filename._data + (lp?lp + 1:0),filename,lf + 1); + full_filename.move_to(res); + } else CImg(filename,lf + 1).move_to(res); + } + } + } while (FindNextFileA(dir,&file_data)); + FindClose(dir); + + // Unix version (posix). +#elif cimg_OS == 1 + DIR *const dir = opendir(is_root?"/":is_current?".":_path.data()); + if (!dir) return CImgList::const_empty(); + struct dirent *ent; + while ((ent=readdir(dir))!=0) { + const char *const filename = ent->d_name; + if (*filename!='.' || (filename[1] && (filename[1]!='.' || filename[2]))) { + const unsigned int lf = (unsigned int)std::strlen(filename); + CImg full_filename(lp + lf + 2); + + if (!is_current) { + full_filename.assign(lp + lf + 2); + if (lp) std::memcpy(full_filename,_path,lp); + full_filename[lp] = '/'; + std::memcpy(full_filename._data + lp + 1,filename,lf + 1); + } else full_filename.assign(filename,lf + 1); + + struct stat st; + if (stat(full_filename,&st)==-1) continue; + const bool is_directory = (st.st_mode & S_IFDIR)!=0; + if ((!mode && !is_directory) || (mode==1 && is_directory) || mode==2) { + if (include_path) { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + full_filename.move_to(res); + } else { + if (!_is_pattern || (_is_pattern && !fnmatch(pattern,full_filename,0))) + CImg(filename,lf + 1).move_to(res); + } + } + } + } + closedir(dir); +#endif + + // Sort resulting list by lexicographic order. + if (res._width>=2) std::qsort(res._data,res._width,sizeof(CImg),_sort_files); + + return res; + } + + //! Try to guess format from an image file. + /** + \param file Input file (can be \c 0 if \c filename is set). + \param filename Filename, as a C-string (can be \c 0 if \c file is set). + \return C-string containing the guessed file format, or \c 0 if nothing has been guessed. + **/ + inline const char *ftype(std::FILE *const file, const char *const filename) { + if (!file && !filename) + throw CImgArgumentException("cimg::ftype(): Specified filename is (null)."); + static const char + *const _pnm = "pnm", + *const _pfm = "pfm", + *const _bmp = "bmp", + *const _gif = "gif", + *const _jpg = "jpg", + *const _off = "off", + *const _pan = "pan", + *const _png = "png", + *const _tif = "tif", + *const _inr = "inr", + *const _dcm = "dcm"; + const char *f_type = 0; + CImg header; + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + header._load_raw(file,filename,512,1,1,1,false,false,0); + const unsigned char *const uheader = (unsigned char*)header._data; + if (!std::strncmp(header,"OFF\n",4)) f_type = _off; // OFF. + else if (!std::strncmp(header,"#INRIMAGE",9)) f_type = _inr; // INRIMAGE. + else if (!std::strncmp(header,"PANDORE",7)) f_type = _pan; // PANDORE. + else if (!std::strncmp(header.data() + 128,"DICM",4)) f_type = _dcm; // DICOM. + else if (uheader[0]==0xFF && uheader[1]==0xD8 && uheader[2]==0xFF) f_type = _jpg; // JPEG. + else if (header[0]=='B' && header[1]=='M') f_type = _bmp; // BMP. + else if (header[0]=='G' && header[1]=='I' && header[2]=='F' && header[3]=='8' && header[5]=='a' && // GIF. + (header[4]=='7' || header[4]=='9')) f_type = _gif; + else if (uheader[0]==0x89 && uheader[1]==0x50 && uheader[2]==0x4E && uheader[3]==0x47 && // PNG. + uheader[4]==0x0D && uheader[5]==0x0A && uheader[6]==0x1A && uheader[7]==0x0A) f_type = _png; + else if ((uheader[0]==0x49 && uheader[1]==0x49) || (uheader[0]==0x4D && uheader[1]==0x4D)) f_type = _tif; // TIFF. + else { // PNM or PFM. + CImgList _header = header.get_split(CImg::vector('\n'),0,false); + cimglist_for(_header,l) { + if (_header(l,0)=='#') continue; + if (_header[l]._height==2 && _header(l,0)=='P') { + const char c = _header(l,1); + if (c=='f' || c=='F') { f_type = _pfm; break; } + if (c>='1' && c<='9') { f_type = _pnm; break; } + } + f_type = 0; break; + } + } + } catch (CImgIOException&) { } + cimg::exception_mode(omode); + return f_type; + } + + //! Load file from network as a local temporary file. + /** + \param filename Filename, as a C-string. + \param[out] filename_local C-string containing the path to a local copy of \c filename. + \param timeout Maximum time (in seconds) authorized for downloading the file from the URL. + \param try_fallback When using libcurl, tells using system calls as fallbacks in case of libcurl failure. + \return Value of \c filename_local. + \note Use the \c libcurl library, or the external binaries \c wget or \c curl to perform the download. + **/ + inline char *load_network(const char *const url, char *const filename_local, + const unsigned int timeout, const bool try_fallback, + const char *const referer) { + if (!url) + throw CImgArgumentException("cimg::load_network(): Specified URL is (null)."); + if (!filename_local) + throw CImgArgumentException("cimg::load_network(): Specified destination string is (null)."); + + const char *const __ext = cimg::split_filename(url), *const _ext = (*__ext && __ext>url)?__ext - 1:__ext; + CImg ext = CImg::string(_ext); + std::FILE *file = 0; + *filename_local = 0; + if (ext._width>16 || !cimg::strncasecmp(ext,"cgi",3)) *ext = 0; + else cimg::strwindows_reserved(ext); + do { + cimg_snprintf(filename_local,256,"%s%c%s%s", + cimg::temporary_path(),cimg_file_separator,cimg::filenamerand(),ext._data); + if ((file=std_fopen(filename_local,"rb"))!=0) cimg::fclose(file); + } while (file); + +#ifdef cimg_use_curl + const unsigned int omode = cimg::exception_mode(); + cimg::exception_mode(0); + try { + CURL *curl = 0; + CURLcode res; + curl = curl_easy_init(); + if (curl) { + file = cimg::fopen(filename_local,"wb"); + curl_easy_setopt(curl,CURLOPT_URL,url); + curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,0); + curl_easy_setopt(curl,CURLOPT_WRITEDATA,file); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0L); + curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0L); + curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1L); + if (timeout) curl_easy_setopt(curl,CURLOPT_TIMEOUT,(long)timeout); + if (std::strchr(url,'?')) curl_easy_setopt(curl,CURLOPT_HTTPGET,1L); + if (referer) curl_easy_setopt(curl,CURLOPT_REFERER,referer); + res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + cimg::fseek(file,0,SEEK_END); // Check if file size is 0. + const cimg_ulong siz = cimg::ftell(file); + cimg::fclose(file); + if (siz>0 && res==CURLE_OK) { + cimg::exception_mode(omode); + return filename_local; + } else std::remove(filename_local); + } + } catch (...) { } + cimg::exception_mode(omode); + if (!try_fallback) throw CImgIOException("cimg::load_network(): Failed to load file '%s' with libcurl.",url); +#endif + + CImg command((unsigned int)std::strlen(url) + 64); + cimg::unused(try_fallback); + + // Try with 'curl' first. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"%s -e %s -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,timeout,filename_local,url); + else + cimg_snprintf(command,command._width,"%s -m %u -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),timeout,filename_local,url); + } else { + if (referer) + cimg_snprintf(command,command._width,"%s -e %s -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),referer,filename_local,url); + else + cimg_snprintf(command,command._width,"%s -f --silent --compressed -o \"%s\" \"%s\"", + cimg::curl_path(),filename_local,url); + } + cimg::system(command); + + if (!(file = std_fopen(filename_local,"rb"))) { + + // Try with 'wget' otherwise. + if (timeout) { + if (referer) + cimg_snprintf(command,command._width,"%s --referer=%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,timeout,filename_local,url); + else + cimg_snprintf(command,command._width,"%s -T %u -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),timeout,filename_local,url); + } else { + if (referer) + cimg_snprintf(command,command._width,"%s --referer=%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),referer,filename_local,url); + else + cimg_snprintf(command,command._width,"%s -q -r -l 0 --no-cache -O \"%s\" \"%s\"", + cimg::wget_path(),filename_local,url); + } + cimg::system(command); + + if (!(file = std_fopen(filename_local,"rb"))) + throw CImgIOException("cimg::load_network(): Failed to load file '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + + // Try gunzip it. + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(filename_local,command); + cimg_snprintf(command,command._width,"%s --quiet \"%s.gz\"", + gunzip_path(),filename_local); + cimg::system(command); + file = std_fopen(filename_local,"rb"); + if (!file) { + cimg_snprintf(command,command._width,"%s.gz",filename_local); + std::rename(command,filename_local); + file = std_fopen(filename_local,"rb"); + } + } + cimg::fseek(file,0,SEEK_END); // Check if file size is 0. + if (std::ftell(file)<=0) + throw CImgIOException("cimg::load_network(): Failed to load URL '%s' with external commands " + "'wget' or 'curl'.",url); + cimg::fclose(file); + return filename_local; + } + + // Implement a tic/toc mechanism to display elapsed time of algorithms. + inline cimg_ulong tictoc(const bool is_tic) { + cimg::mutex(2); + static CImg times(64); + static unsigned int pos = 0; + const cimg_ulong t1 = cimg::time(); + if (is_tic) { // Tic. + times[pos++] = t1; + if (pos>=times._width) + throw CImgArgumentException("cimg::tic(): Too much calls to 'cimg::tic()' without calls to 'cimg::toc()'."); + cimg::mutex(2,0); + return t1; + } + // Toc. + if (!pos) + throw CImgArgumentException("cimg::toc(): No previous call to 'cimg::tic()' has been made."); + const cimg_ulong + t0 = times[--pos], + dt = t1>=t0?(t1 - t0):cimg::type::max(); + const unsigned int + edays = (unsigned int)(dt/86400000.0), + ehours = (unsigned int)((dt - edays*86400000.0)/3600000.0), + emin = (unsigned int)((dt - edays*86400000.0 - ehours*3600000.0)/60000.0), + esec = (unsigned int)((dt - edays*86400000.0 - ehours*3600000.0 - emin*60000.0)/1000.0), + ems = (unsigned int)(dt - edays*86400000.0 - ehours*3600000.0 - emin*60000.0 - esec*1000.0); + if (!edays && !ehours && !emin && !esec) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ems,cimg::t_normal); + else { + if (!edays && !ehours && !emin) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",esec,ems,cimg::t_normal); + else { + if (!edays && !ehours) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",emin,esec,ems,cimg::t_normal); + else{ + if (!edays) + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",ehours,emin,esec,ems,cimg::t_normal); + else{ + std::fprintf(cimg::output(),"%s[CImg]%*sElapsed time: %u days %u hours %u min %u sec %u ms%s\n", + cimg::t_red,1 + 2*pos,"",edays,ehours,emin,esec,ems,cimg::t_normal); + } + } + } + } + cimg::mutex(2,0); + return dt; + } + + // Return a temporary string describing the size of a memory buffer. + inline const char *strbuffersize(const cimg_ulong size) { + static CImg res(256); + cimg::mutex(5); + 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); + } else { const float nsize = size/(1024*1024*1024.0f); cimg_snprintf(res,res._width,"%.1f Gio",nsize); } + cimg::mutex(5,0); + return res; + } + + //! Display a simple dialog box, and wait for the user's response. + /** + \param title Title of the dialog window. + \param msg Main message displayed inside the dialog window. + \param button1_label Label of the 1st button. + \param button2_label Label of the 2nd button (\c 0 to hide button). + \param button3_label Label of the 3rd button (\c 0 to hide button). + \param button4_label Label of the 4th button (\c 0 to hide button). + \param button5_label Label of the 5th button (\c 0 to hide button). + \param button6_label Label of the 6th button (\c 0 to hide button). + \param logo Image logo displayed at the left of the main message. + \param is_centered Tells if the dialog window must be centered on the screen. + \return Indice of clicked button (from \c 0 to \c 5), or \c -1 if the dialog window has been closed by the user. + \note + - Up to 6 buttons can be defined in the dialog window. + - The function returns when a user clicked one of the button or closed the dialog window. + - If a button text is set to 0, the corresponding button (and the followings) will not appear in the dialog box. + At least one button must be specified. + **/ + template + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, + const char *const button3_label, const char *const button4_label, + const char *const button5_label, const char *const button6_label, + const CImg& logo, const bool is_centered=false) { +#if cimg_display==0 + cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + logo._data,is_centered); + throw CImgIOException("cimg::dialog(): No display available."); +#else + static const unsigned char + black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 }; + + // Create buttons and canvas graphics + CImgList buttons, cbuttons, sbuttons; + if (button1_label) { CImg().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons); + if (button2_label) { CImg().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons); + if (button3_label) { CImg().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons); + if (button4_label) { CImg().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons); + if (button5_label) { CImg().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons); + if (button6_label) { CImg().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons); + }}}}}} + if (!buttons._width) + throw CImgArgumentException("cimg::dialog(): No buttons have been defined."); + cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3); + + unsigned int bw = 0, bh = 0; + cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); } + bw+=8; bh+=8; + if (bw<64) bw = 64; + if (bw>128) bw = 128; + if (bh<24) bh = 24; + if (bh>48) bh = 48; + + CImg button(bw,bh,1,3); + button.draw_rectangle(0,0,bw - 1,bh - 1,gray); + button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white); + button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black); + button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2); + CImg sbutton(bw,bh,1,3); + sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray); + sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black); + sbutton.draw_line(bw - 1,bh - 1,0,bh - 1,black).draw_line(0,bh - 1,0,0,black); + sbutton.draw_line(1,1,bw - 2,1,white).draw_line(1,bh - 2,1,1,white); + sbutton.draw_line(bw - 2,1,bw - 2,bh - 2,black).draw_line(bw - 2,bh - 2,1,bh - 2,black); + sbutton.draw_line(2,bh - 3,bw - 3,bh - 3,gray2).draw_line(bw - 3,bh - 3,bw - 3,2,gray2); + sbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true).draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + sbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false).draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + CImg cbutton(bw,bh,1,3); + cbutton.draw_rectangle(0,0,bw - 1,bh - 1,black).draw_rectangle(1,1,bw - 2,bh - 2,gray2). + draw_rectangle(2,2,bw - 3,bh - 3,gray); + cbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true).draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false); + cbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false).draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false); + + cimglist_for(buttons,ll) { + CImg(cbutton). + draw_image(1 + (bw -buttons[ll].width())/2,1 + (bh - buttons[ll].height())/2,buttons[ll]). + move_to(cbuttons); + CImg(sbutton). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(sbuttons); + CImg(button). + draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]). + move_to(buttons[ll]); + } + + CImg canvas; + if (msg) + ((CImg().draw_text(0,0,"%s",gray,0,1,13,msg)*=-1)+=200).resize(-100,-100,1,3).move_to(canvas); + + const unsigned int + bwall = (buttons._width - 1)*(12 + bw) + bw, + w = cimg::max(196U,36 + logo._width + canvas._width,24 + bwall), + h = cimg::max(96U,36 + canvas._height + bh,36 + logo._height + bh), + lx = 12 + (canvas._data?0:((w - 24 - logo._width)/2)), + ly = (h - 12 - bh - logo._height)/2, + tx = lx + logo._width + 12, + ty = (h - 12 - bh - canvas._height)/2, + bx = (w - bwall)/2, + by = h - 12 - bh; + + if (canvas._data) + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black). + draw_image(tx,ty,canvas); + else + canvas = CImg(w,h,1,3). + draw_rectangle(0,0,w - 1,h - 1,gray). + draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white). + draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black); + if (logo._data) canvas.draw_image(lx,ly,logo); + + unsigned int xbuttons[6] = { 0 }; + cimglist_for(buttons,lll) { xbuttons[lll] = bx + (bw + 12)*lll; canvas.draw_image(xbuttons[lll],by,buttons[lll]); } + + // Open window and enter events loop + CImgDisplay disp(canvas,title?title:" ",0,false,is_centered?true:false); + if (is_centered) disp.move((CImgDisplay::screen_width() - disp.width())/2, + (CImgDisplay::screen_height() - disp.height())/2); + bool stop_flag = false, refresh = false; + int oselected = -1, oclicked = -1, selected = -1, clicked = -1; + while (!disp.is_closed() && !stop_flag) { + if (refresh) { + if (clicked>=0) + CImg(canvas).draw_image(xbuttons[clicked],by,cbuttons[clicked]).display(disp); + else { + if (selected>=0) + CImg(canvas).draw_image(xbuttons[selected],by,sbuttons[selected]).display(disp); + else canvas.display(disp); + } + refresh = false; + } + disp.wait(15); + if (disp.is_resized()) disp.resize(disp,false); + + if (disp.button()&1) { + oclicked = clicked; + clicked = -1; + cimglist_for(buttons,l) + if (disp.mouse_y()>=(int)by && disp.mouse_y()<(int)(by + bh) && + disp.mouse_x()>=(int)xbuttons[l] && disp.mouse_x()<(int)(xbuttons[l] + bw)) { + clicked = selected = l; + refresh = true; + } + if (clicked!=oclicked) refresh = true; + } else if (clicked>=0) stop_flag = true; + + if (disp.key()) { + oselected = selected; + switch (disp.key()) { + case cimg::keyESC : selected = -1; stop_flag = true; break; + case cimg::keyENTER : if (selected<0) selected = 0; stop_flag = true; break; + case cimg::keyTAB : + case cimg::keyARROWRIGHT : + case cimg::keyARROWDOWN : selected = (selected + 1)%buttons.width(); break; + case cimg::keyARROWLEFT : + case cimg::keyARROWUP : selected = (selected + buttons.width() - 1)%buttons.width(); break; + } + disp.set_key(); + if (selected!=oselected) refresh = true; + } + } + if (!disp) selected = -1; + return selected; +#endif + } + + //! Display a simple dialog box, and wait for the user's response \specialization. + inline int dialog(const char *const title, const char *const msg, + const char *const button1_label, const char *const button2_label, const char *const button3_label, + const char *const button4_label, const char *const button5_label, const char *const button6_label, + const bool is_centered) { + return dialog(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label, + CImg::_logo40x38(),is_centered); + } + + //! Evaluate math expression. + /** + \param expression C-string describing the formula to evaluate. + \param x Value of the pre-defined variable \c x. + \param y Value of the pre-defined variable \c y. + \param z Value of the pre-defined variable \c z. + \param c Value of the pre-defined variable \c c. + \return Result of the formula evaluation. + \note Set \c expression to \c 0 to keep evaluating the last specified \c expression. + \par Example + \code + const double + res1 = cimg::eval("cos(x)^2 + sin(y)^2",2,2), // will return '1'. + res2 = cimg::eval(0,1,1); // will return '1' too. + \endcode + **/ + inline double eval(const char *const expression, const double x, const double y, const double z, const double c) { + static const CImg empty; + return empty.eval(expression,x,y,z,c); + } + + template + inline CImg::type> eval(const char *const expression, const CImg& xyzc) { + static const CImg empty; + return empty.eval(expression,xyzc); + } + + // End of cimg:: namespace +} + + // End of cimg_library:: namespace +} + +//! Short alias name. +namespace cil = cimg_library_suffixed; + +#ifdef _cimg_redefine_False +#define False 0 +#endif +#ifdef _cimg_redefine_True +#define True 1 +#endif +#ifdef _cimg_redefine_None +#define None 0 +#endif +#ifdef _cimg_redefine_min +#define min(a,b) (((a)<(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_max +#define max(a,b) (((a)>(b))?(a):(b)) +#endif +#ifdef _cimg_redefine_PI +#define PI 3.141592653589793238462643383 +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif +// Local Variables: +// mode: c++ +// End: diff --git a/ext/phashion_ext/extconf.rb b/ext/phashion_ext/extconf.rb index 2dda204..dfcde46 100644 --- a/ext/phashion_ext/extconf.rb +++ b/ext/phashion_ext/extconf.rb @@ -9,7 +9,7 @@ $LIBPATH = ["#{HERE}/lib"] $CFLAGS = "#{$includes} #{$libraries} #{$CFLAGS}" $LDFLAGS = "#{$libraries} #{$LDFLAGS}" -$CXXFLAGS = ' -pthread' +$CXXFLAGS = ' -pthread' Dir.chdir(HERE) do if File.exist?("lib") @@ -20,6 +20,9 @@ raise "'#{cmd}' failed" unless system(cmd) Dir.chdir(BUNDLE_PATH) do + puts(cmd = "cp ../CImg.h ./") + raise "'#{cmd}' failed" unless system(cmd) + puts(cmd = "env CXXFLAGS='#{$CXXFLAGS}' CFLAGS='#{$CFLAGS}' LDFLAGS='#{$LDFLAGS}' ./configure --prefix=#{HERE} --disable-audio-hash --disable-video-hash --disable-shared --with-pic 2>&1") raise "'#{cmd}' failed" unless system(cmd) @@ -29,7 +32,7 @@ puts(cmd = "make install || true 2>&1") raise "'#{cmd}' failed" unless system(cmd) - puts(cmd = "mv CImg.h ../include 2>&1") + puts(cmd = "cp ../CImg.h ../include 2>&1") raise "'#{cmd}' failed" unless system(cmd) end diff --git a/ext/phashion_ext/pHash-0.9.6.tar.gz b/ext/phashion_ext/pHash-0.9.6.tar.gz index 3b8e96279666cdd71966f261a33a6a8b3067915c..b9d241ee68acf13902df0c955af381edc60560ea 100644 GIT binary patch literal 1315965 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 #as*hE5 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�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 %nhC0b@0i9fAL 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